diff --git a/src/app/components/RoomDetail.svelte b/src/app/components/RoomDetail.svelte new file mode 100644 index 00000000..0402c51e --- /dev/null +++ b/src/app/components/RoomDetail.svelte @@ -0,0 +1,190 @@ + + +
+
+
+ +
+ + {displayRelayUrl(url)} +
+
+
+ {#if $room?.isRestricted} + + {/if} + {#if $room?.isPrivate} + + {/if} + {#if $room?.isHidden} + + {/if} + {#if $room?.isClosed} + + {/if} +
+
+ {#if $room?.about} +

{$room.about}

+ {/if} + {#if $members.length > 0} +
+ Members: + +
+ {/if} + + +
+ {#if $userIsAdmin} + + + {:else if $membershipStatus === MembershipStatus.Initial} + + {:else if $membershipStatus === MembershipStatus.Pending} + + {:else} + + {/if} +
+
+
diff --git a/src/app/components/RoomEdit.svelte b/src/app/components/RoomEdit.svelte index 11e940fc..57daa45e 100644 --- a/src/app/components/RoomEdit.svelte +++ b/src/app/components/RoomEdit.svelte @@ -2,20 +2,15 @@ import {goto} from "$app/navigation" import type {RoomMeta} from "@welshman/util" import {displayRelayUrl} from "@welshman/util" - import {deleteRoom, waitForThunkError, repository} from "@welshman/app" - import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import Spinner from "@lib/components/Spinner.svelte" import Button from "@lib/components/Button.svelte" import Icon from "@lib/components/Icon.svelte" - import Confirm from "@lib/components/Confirm.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte" import RoomForm from "@app/components/RoomForm.svelte" import {deriveRoom} from "@app/core/state" import {makeSpacePath} from "@app/util/routes" - import {pushModal} from "@app/util/modal" - import {pushToast} from "@app/util/toast" type Props = { url: string @@ -29,24 +24,6 @@ const back = () => history.back() const onsubmit = (room: RoomMeta) => goto(makeSpacePath(url, h)) - - const startDelete = () => - pushModal(Confirm, { - title: "Are you sure you want to delete this room?", - message: - "This room will no longer be accessible to space members, and all messages posted to it will be deleted.", - confirm: async () => { - const thunk = deleteRoom(url, $room) - const message = await waitForThunkError(thunk) - - if (message) { - repository.removeEvent(thunk.event.id) - pushToast({theme: "error", message}) - } else { - goto(makeSpacePath(url)) - } - }, - }) @@ -68,15 +45,9 @@ Go back -
- - -
+ {/snippet}
diff --git a/src/app/components/RoomImage.svelte b/src/app/components/RoomImage.svelte index 7c12abcb..4268eff1 100644 --- a/src/app/components/RoomImage.svelte +++ b/src/app/components/RoomImage.svelte @@ -5,17 +5,18 @@ import {deriveRoom} from "@app/core/state" interface Props { - h: any - url: any + h: string + url: string + size?: number } - const {url, h}: Props = $props() + const {url, h, size = 5}: Props = $props() const room = deriveRoom(url, h) {#if $room.picture} - + {:else} - + {/if} diff --git a/src/app/components/RoomName.svelte b/src/app/components/RoomName.svelte index f03ee241..f657a6b7 100644 --- a/src/app/components/RoomName.svelte +++ b/src/app/components/RoomName.svelte @@ -1,9 +1,17 @@ - - {$roomsById.get(makeRoomId(url, h))?.name || h} + + {$room?.name || h} diff --git a/src/app/components/RoomNameWithImage.svelte b/src/app/components/RoomNameWithImage.svelte index e784eb8a..a9113b09 100644 --- a/src/app/components/RoomNameWithImage.svelte +++ b/src/app/components/RoomNameWithImage.svelte @@ -3,14 +3,15 @@ import RoomImage from "@app/components/RoomImage.svelte" interface Props { - h: any - url: any + h: string + url: string + class?: string } - const {url, h}: Props = $props() + const {url, h, ...props}: Props = $props() -
+
diff --git a/src/app/core/state.ts b/src/app/core/state.ts index 99b4adb4..97fe3d18 100644 --- a/src/app/core/state.ts +++ b/src/app/core/state.ts @@ -806,18 +806,29 @@ export enum MembershipStatus { Granted, } +export const deriveUserIsSpaceAdmin = (url: string) => { + const store = writable(false) + + manageRelay(url, {method: ManagementMethod.SupportedMethods, params: []}).then(res => + store.set(Boolean(res.result?.length)), + ) + + return store +} + export const deriveUserSpaceMembershipStatus = (url: string) => derived( [ pubkey, deriveSpaceMembers(url), deriveEventsForUrl(url, [{kinds: [RELAY_JOIN, RELAY_LEAVE]}]), + deriveUserIsSpaceAdmin(url), ], - ([$pubkey, $members, $events]) => { - const isMember = $members.includes($pubkey) + ([$pubkey, $members, $events, $isAdmin]) => { + const isMember = $members.includes($pubkey) || $isAdmin for (const event of $events) { - if (!getPubkeyTagValues(event.tags).includes($pubkey!)) { + if (event.pubkey !== $pubkey) { continue } @@ -834,18 +845,25 @@ export const deriveUserSpaceMembershipStatus = (url: string) => }, ) +export const deriveUserIsRoomAdmin = (url: string, h: string) => + derived( + [pubkey, deriveRoomAdmins(url, h), deriveUserIsSpaceAdmin(url)], + ([$pubkey, $admins, $isSpaceAdmin]) => $isSpaceAdmin || $admins.includes($pubkey!), + ) + export const deriveUserRoomMembershipStatus = (url: string, h: string) => derived( [ pubkey, deriveRoomMembers(url, h), deriveEventsForUrl(url, [{kinds: [ROOM_JOIN, ROOM_LEAVE], "#h": [h]}]), + deriveUserIsRoomAdmin(url, h), ], - ([$pubkey, $members, $events]) => { - const isMember = $members.includes($pubkey) + ([$pubkey, $members, $events, $isAdmin]) => { + const isMember = $members.includes($pubkey) || $isAdmin for (const event of $events) { - if (!getPubkeyTagValues(event.tags).includes($pubkey!)) { + if (event.pubkey !== $pubkey) { continue } @@ -872,19 +890,6 @@ export const deriveUserCanCreateRoom = (url: string) => }, ) -export const deriveUserIsRoomAdmin = (url: string, h: string) => - derived([pubkey, deriveRoomAdmins(url, h)], ([$pubkey, $admins]) => $admins.includes($pubkey!)) - -export const deriveUserIsSpaceAdmin = (url: string) => { - const store = writable(false) - - manageRelay(url, {method: ManagementMethod.SupportedMethods, params: []}).then(res => - store.set(Boolean(res.result?.length)), - ) - - return store -} - // Other utils export const encodeRelay = (url: string) => diff --git a/src/lib/components/ImageIcon.svelte b/src/lib/components/ImageIcon.svelte index 4574d8bb..c0ab10b6 100644 --- a/src/lib/components/ImageIcon.svelte +++ b/src/lib/components/ImageIcon.svelte @@ -4,13 +4,14 @@ type Props = { src: string alt: string + size?: number } - const {src, alt}: Props = $props() + const {src, alt, size = 5}: Props = $props() {#if src.includes("image/svg") || src.endsWith(".svg")} - + {:else} - + {/if} diff --git a/src/routes/spaces/[relay]/[h]/+page.svelte b/src/routes/spaces/[relay]/[h]/+page.svelte index 0cbd7d62..c55d2fb9 100644 --- a/src/routes/spaces/[relay]/[h]/+page.svelte +++ b/src/routes/spaces/[relay]/[h]/+page.svelte @@ -16,11 +16,10 @@ } from "@welshman/util" import {pubkey, publishThunk, waitForThunkError, joinRoom, leaveRoom} from "@welshman/app" import {slide, fade, fly} from "@lib/transition" - import Pen from "@assets/icons/pen.svg?dataurl" + import InfoCircle from "@assets/icons/info-circle.svg?dataurl" import ClockCircle from "@assets/icons/clock-circle.svg?dataurl" import Login2 from "@assets/icons/login-3.svg?dataurl" import AltArrowDown from "@assets/icons/alt-arrow-down.svg?dataurl" - import Logout2 from "@assets/icons/logout-3.svg?dataurl" import Bookmark from "@assets/icons/bookmark.svg?dataurl" import Icon from "@lib/components/Icon.svelte" import Button from "@lib/components/Button.svelte" @@ -30,10 +29,9 @@ import Divider from "@lib/components/Divider.svelte" import ThunkToast from "@app/components/ThunkToast.svelte" import MenuSpaceButton from "@app/components/MenuSpaceButton.svelte" - import RoomEdit from "@app/components/RoomEdit.svelte" import RoomName from "@app/components/RoomName.svelte" - import RoomAccess from "@app/components/RoomAccess.svelte" import RoomImage from "@app/components/RoomImage.svelte" + import RoomDetail from "@app/components/RoomDetail.svelte" import RoomItem from "@app/components/RoomItem.svelte" import RoomItemAddMember from "@src/app/components/RoomItemAddMember.svelte" import RoomItemRemoveMember from "@src/app/components/RoomItemRemoveMember.svelte" @@ -49,7 +47,6 @@ MembershipStatus, PROTECTED, MESSAGE_KINDS, - deriveUserIsRoomAdmin, } from "@app/core/state" import {setChecked, checked} from "@app/util/notifications" import { @@ -71,10 +68,11 @@ const room = deriveRoom(url, h) const shouldProtect = canEnforceNip70(url) const userRooms = deriveUserRooms(url) - const userIsAdmin = deriveUserIsRoomAdmin(url, h) const isFavorite = $derived($userRooms.includes(h)) const membershipStatus = deriveUserRoomMembershipStatus(url, h) + const showRoomDetail = () => pushModal(RoomDetail, {url, h}) + const addFavorite = () => addRoomMembership(url, h) const removeFavorite = () => removeRoomMembership(url, h) @@ -304,8 +302,6 @@ } } - const startEdit = () => pushModal(RoomEdit, {url, h}) - onMount(() => { const observer = new ResizeObserver(() => { if (dynamicPadding && chatCompose) { @@ -342,47 +338,18 @@ {/snippet} {#snippet action()}
- - {#if $userIsAdmin} - - {:else if $membershipStatus === MembershipStatus.Initial} - - {:else if $membershipStatus === MembershipStatus.Pending} - - {:else} - - {/if} +
{/snippet}