Streamline deriveRoom

This commit is contained in:
Jon Staab
2025-10-31 16:18:58 -07:00
parent 3978e32d5f
commit b1c68972c9
6 changed files with 34 additions and 22 deletions

View File

@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import {goto} from "$app/navigation" import {goto} from "$app/navigation"
import type {RoomMeta} from "@welshman/util" import type {RoomMeta} from "@welshman/util"
import {displayRelayUrl, makeRoomMeta, readRoomMeta} from "@welshman/util" import {displayRelayUrl} from "@welshman/util"
import {deleteRoom, waitForThunkError, repository} from "@welshman/app" import {deleteRoom, waitForThunkError, repository} from "@welshman/app"
import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl" import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
@@ -25,11 +25,10 @@
const {url, h}: Props = $props() const {url, h}: Props = $props()
const room = deriveRoom(url, h) const room = deriveRoom(url, h)
const initialValues = $room ? readRoomMeta($room.event) : makeRoomMeta({h})
const back = () => history.back() const back = () => history.back()
const onsubmit = (room: RoomMeta) => goto(makeSpacePath(url, room.h)) const onsubmit = (room: RoomMeta) => goto(makeSpacePath(url, h))
const startDelete = () => const startDelete = () =>
pushModal(Confirm, { pushModal(Confirm, {
@@ -37,7 +36,7 @@
message: message:
"This room will no longer be accessible to space members, and all messages posted to it will be deleted.", "This room will no longer be accessible to space members, and all messages posted to it will be deleted.",
confirm: async () => { confirm: async () => {
const thunk = deleteRoom(url, makeRoomMeta({h})) const thunk = deleteRoom(url, $room)
const message = await waitForThunkError(thunk) const message = await waitForThunkError(thunk)
if (message) { if (message) {
@@ -50,7 +49,7 @@
}) })
</script> </script>
<RoomForm {url} {onsubmit} {initialValues}> <RoomForm {url} {onsubmit} initialValues={$room}>
{#snippet header()} {#snippet header()}
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}

View File

@@ -9,6 +9,7 @@
import {preventDefault, compressFile} from "@lib/html" import {preventDefault, compressFile} from "@lib/html"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components/FieldInline.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import ImageIcon from "@lib/components/ImageIcon.svelte"
import IconPickerButton from "@lib/components/IconPickerButton.svelte" import IconPickerButton from "@lib/components/IconPickerButton.svelte"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
import {uploadFile} from "@app/core/commands" import {uploadFile} from "@app/core/commands"
@@ -113,10 +114,7 @@
{#if imagePreview} {#if imagePreview}
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<span class="text-sm opacity-75">Selected:</span> <span class="text-sm opacity-75">Selected:</span>
<img <ImageIcon src={imagePreview} alt="Room icon preview" />
src={imagePreview}
alt="Room icon preview"
class="h-5 w-5 rounded-lg object-cover" />
</div> </div>
{:else if selectedIcon} {:else if selectedIcon}
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
@@ -148,7 +146,7 @@
{#snippet input()} {#snippet input()}
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input input-bordered flex w-full items-center gap-2">
{#if imagePreview} {#if imagePreview}
<img src={imagePreview} alt="Room icon preview" class="h-5 w-5 rounded-lg object-cover" /> <ImageIcon src={imagePreview} alt="Room icon preview" />
{:else if selectedIcon} {:else if selectedIcon}
<Icon icon={selectedIcon} class="h-8 w-8" /> <Icon icon={selectedIcon} class="h-8 w-8" />
{:else} {:else}

View File

@@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import Hashtag from "@assets/icons/hashtag.svg?dataurl" import Hashtag from "@assets/icons/hashtag.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import ImageIcon from "@lib/components/ImageIcon.svelte"
import RoomName from "@app/components/RoomName.svelte" import RoomName from "@app/components/RoomName.svelte"
import {deriveRoom} from "@app/core/state" import {deriveRoom} from "@app/core/state"
@@ -14,13 +15,9 @@
const room = deriveRoom(url, h) const room = deriveRoom(url, h)
</script> </script>
{#if $room?.picture} {#if $room.picture}
{@const src = $room.picture} {@const src = $room.picture}
{#if src.match("\.(png|svg)$") || src.match("image/(png|svg)")} <ImageIcon {src} alt="Room icon" />
<Icon icon={src} />
{:else}
<img alt="Room icon" {src} class="h-6 w-6 rounded-lg" />
{/if}
{:else} {:else}
<Icon icon={Hashtag} /> <Icon icon={Hashtag} />
{/if} {/if}

View File

@@ -98,6 +98,7 @@ import {
RelayMode, RelayMode,
verifyEvent, verifyEvent,
readRoomMeta, readRoomMeta,
makeRoomMeta,
} from "@welshman/util" } from "@welshman/util"
import type { import type {
TrustedEvent, TrustedEvent,
@@ -612,7 +613,8 @@ export const {
}, },
}) })
export const deriveRoom = (url: string, h: string) => _deriveRoom(makeRoomId(url, h)) export const deriveRoom = (url: string, h: string) =>
derived(_deriveRoom(makeRoomId(url, h)), $meta => $meta || makeRoomMeta({h}))
export const displayRoom = (url: string, h: string) => export const displayRoom = (url: string, h: string) =>
roomsById.get().get(makeRoomId(url, h))?.name || h roomsById.get().get(makeRoomId(url, h))?.name || h

View File

@@ -0,0 +1,16 @@
<script lang="ts">
import Icon from "@lib/components/Icon.svelte"
type Props = {
src: string
alt: string
}
const {src, alt}: Props = $props()
</script>
{#if src.includes("image/svg") || src.endsWith(".svg")}
<Icon icon={src} />
{:else}
<img {src} {alt} class="h-5 w-5 rounded-lg object-cover" />
{/if}

View File

@@ -386,11 +386,11 @@
<PageContent bind:element onscroll={onScroll} class="flex flex-col-reverse pt-4"> <PageContent bind:element onscroll={onScroll} class="flex flex-col-reverse pt-4">
<div bind:this={dynamicPadding}></div> <div bind:this={dynamicPadding}></div>
{#if $room?.isPrivate && $membershipStatus !== MembershipStatus.Granted} {#if $room.isPrivate && $membershipStatus !== MembershipStatus.Granted}
<div class="py-20"> <div class="py-20">
<div class="card2 col-8 m-auto max-w-md items-center text-center"> <div class="card2 col-8 m-auto max-w-md items-center text-center">
<p class="opacity-75">You aren't currently a member of this room.</p> <p class="opacity-75">You aren't currently a member of this room.</p>
{#if !$room?.isClosed} {#if !$room.isClosed}
{#if $membershipStatus === MembershipStatus.Pending} {#if $membershipStatus === MembershipStatus.Pending}
<Button class="btn btn-neutral btn-sm" disabled={leaving} onclick={leave}> <Button class="btn btn-neutral btn-sm" disabled={leaving} onclick={leave}>
<Icon icon={ClockCircle} /> <Icon icon={ClockCircle} />
@@ -452,12 +452,12 @@
</PageContent> </PageContent>
<div class="chat__compose bg-base-200" bind:this={chatCompose}> <div class="chat__compose bg-base-200" bind:this={chatCompose}>
{#if $room?.isPrivate && $membershipStatus !== MembershipStatus.Granted} {#if $room.isPrivate && $membershipStatus !== MembershipStatus.Granted}
<!-- pass --> <!-- pass -->
{:else if $room?.isRestricted && $membershipStatus !== MembershipStatus.Granted} {:else if $room.isRestricted && $membershipStatus !== MembershipStatus.Granted}
<div class="bg-alt card m-4 flex flex-row items-center justify-between px-4 py-3"> <div class="bg-alt card m-4 flex flex-row items-center justify-between px-4 py-3">
<p>Only members are allowed to post to this room.</p> <p>Only members are allowed to post to this room.</p>
{#if !$room?.isClosed} {#if !$room.isClosed}
{#if $membershipStatus === MembershipStatus.Pending} {#if $membershipStatus === MembershipStatus.Pending}
<Button class="btn btn-neutral btn-sm" disabled={leaving} onclick={leave}> <Button class="btn btn-neutral btn-sm" disabled={leaving} onclick={leave}>
<Icon icon={ClockCircle} /> <Icon icon={ClockCircle} />