Lint, rename chat compose stuff

This commit is contained in:
Jon Staab 2024-09-11 11:09:25 -07:00
parent 4ad67921a0
commit 339e53e506
26 changed files with 94 additions and 131 deletions

View file

@ -105,7 +105,7 @@
} }
.link-content { .link-content {
@apply inline-block max-w-full overflow-hidden text-ellipsis whitespace-nowrap rounded bg-neutral px-1 text-sm text-neutral-content no-underline; @apply max-w-full overflow-hidden text-ellipsis whitespace-nowrap rounded bg-neutral px-1 text-neutral-content no-underline;
} }
.link-content.link-content-selected { .link-content.link-content-selected {

View file

@ -1,19 +1,18 @@
import {uniqBy, equals, uniq, now, choice} from "@welshman/lib" import {uniqBy, sleep, chunk, equals, choice} from "@welshman/lib"
import {getRelayTagValues, createEvent, displayProfile} from "@welshman/util" import {getPubkeyTagValues, createEvent, displayProfile} from "@welshman/util"
import {PublishStatus} from "@welshman/net" import type {SubscribeRequestWithHandlers} from "@welshman/net"
import { import {
pubkey, pubkey,
repository, repository,
load,
makeThunk, makeThunk,
publishThunk, publishThunk,
loadProfile, loadProfile,
profilesByPubkey, profilesByPubkey,
relaySelectionsByPubkey, relaySelectionsByPubkey,
loadRelaySelections,
getWriteRelayUrls, getWriteRelayUrls,
loadFollows, loadFollows,
loadMutes, loadMutes,
followsByPubkey,
} from "@welshman/app" } from "@welshman/app"
import {MEMBERSHIPS, INDEXER_RELAYS} from "@app/state" import {MEMBERSHIPS, INDEXER_RELAYS} from "@app/state"
@ -49,8 +48,32 @@ export const makeIMeta = (url: string, data: Record<string, string>) => [
// Loaders // Loaders
export const loadUserData = (pubkey: string, hints: string[] = []) => export const loadUserData = (
Promise.all([loadProfile(pubkey), loadFollows(pubkey), loadMutes(pubkey)]) pubkey: string,
request: Partial<SubscribeRequestWithHandlers> = {},
) => {
const promise = Promise.all([
loadProfile(pubkey, request),
loadFollows(pubkey, request),
loadMutes(pubkey, request),
])
// Load followed profiles slowly in the background without clogging other stuff up
promise.then(async () => {
const followsList = followsByPubkey.get().get(pubkey)
const follows = getPubkeyTagValues(followsList?.event.tags || [])
for (const pubkeys of chunk(50, follows)) {
await sleep(300)
for (const pubkey of pubkeys) {
loadProfile(pubkey)
}
}
})
return promise
}
// Updates // Updates
@ -73,10 +96,14 @@ export const addSpaceMembership = (url: string) =>
updateList(MEMBERSHIPS, (tags: string[][]) => uniqBy(t => t.join(""), [...tags, ["r", url]])) updateList(MEMBERSHIPS, (tags: string[][]) => uniqBy(t => t.join(""), [...tags, ["r", url]]))
export const addRoomMembership = (url: string, topic: string) => export const addRoomMembership = (url: string, topic: string) =>
updateList(MEMBERSHIPS, (tags: string[][]) => uniqBy(t => t.join(""), [...tags, ["t", topic, url]])) updateList(MEMBERSHIPS, (tags: string[][]) =>
uniqBy(t => t.join(""), [...tags, ["t", topic, url]]),
)
export const removeSpaceMembership = (url: string) => export const removeSpaceMembership = (url: string) =>
updateList(MEMBERSHIPS, (tags: string[][]) => tags.filter(t => !equals(["r", url], t) && t[2] !== url)) updateList(MEMBERSHIPS, (tags: string[][]) =>
tags.filter(t => !equals(["r", url], t) && t[2] !== url),
)
export const removeRoomMembership = (url: string, topic: string) => export const removeRoomMembership = (url: string, topic: string) =>
updateList(MEMBERSHIPS, (tags: string[][]) => tags.filter(t => !equals(["t", topic, url], t))) updateList(MEMBERSHIPS, (tags: string[][]) => tags.filter(t => !equals(["t", topic, url], t)))

View file

@ -10,12 +10,12 @@
export let selected: NodeViewProps["selected"] export let selected: NodeViewProps["selected"]
</script> </script>
<NodeViewWrapper class="inline"> <NodeViewWrapper class="inline-block">
<Link <Link
external external
href={node.attrs.url} href={node.attrs.url}
class={cx("link-content", {"link-content-selected": selected})}> class={cx("link-content", {"link-content-selected": selected})}>
<Icon icon="link-round" size={3} class="inline-block translate-y-px" /> <Icon icon="link-round" size={3} class="inline-block" />
{displayUrl(node.attrs.url)} {displayUrl(node.attrs.url)}
</Link> </Link>
</NodeViewWrapper> </NodeViewWrapper>

View file

@ -65,10 +65,10 @@
data-theme={$theme} data-theme={$theme}
bind:this={element} bind:this={element}
transition:slide|local={{duration: 100}} transition:slide|local={{duration: 100}}
class="mt-2 flex max-h-[350px] flex-col overflow-y-auto overflow-x-hidden shadow-xl"> class="mt-2 max-h-[350px] overflow-y-auto overflow-x-hidden shadow-xl">
{#if term && allowCreate} {#if term && allowCreate}
<button <button
class="white-space-nowrap min-w-0 cursor-pointer overflow-hidden text-ellipsis px-4 py-2 text-left transition-colors hover:bg-primary hover:text-primary-content" class="white-space-nowrap block w-full min-w-0 cursor-pointer overflow-x-hidden text-ellipsis px-4 py-2 text-left transition-colors hover:bg-primary hover:text-primary-content"
on:mousedown|preventDefault on:mousedown|preventDefault
on:click|preventDefault={() => select(term)}> on:click|preventDefault={() => select(term)}>
Use "<svelte:component this={component} value={term} />" Use "<svelte:component this={component} value={term} />"
@ -76,7 +76,7 @@
{/if} {/if}
{#each items as value, i (value)} {#each items as value, i (value)}
<button <button
class="white-space-nowrap min-w-0 cursor-pointer overflow-hidden text-ellipsis px-4 py-2 text-left transition-colors hover:bg-primary hover:text-primary-content" class="white-space-nowrap block w-full min-w-0 cursor-pointer overflow-x-hidden text-ellipsis px-4 py-2 text-left transition-colors hover:bg-primary hover:text-primary-content"
class:bg-primary={index === i} class:bg-primary={index === i}
class:text-primary-content={index === i} class:text-primary-content={index === i}
on:mousedown|preventDefault on:mousedown|preventDefault

View file

@ -1,18 +0,0 @@
<script lang="ts">
import cx from "classnames"
import type {NodeViewProps} from "@tiptap/core"
import {NodeViewWrapper} from "svelte-tiptap"
import Link from "@lib/components/Link.svelte"
export let node: NodeViewProps["node"]
export let selected: NodeViewProps["selected"]
</script>
<NodeViewWrapper class="inline">
<Link
external
href="https://coracle.social/topics/{node.attrs.topic.toLowerCase()}"
class={cx("link-content", {"link-content-selected": selected})}>
#{node.attrs.topic}
</Link>
</NodeViewWrapper>

View file

@ -1,5 +0,0 @@
<script lang="ts">
export let value
</script>
#{value}

View file

@ -1,9 +1,6 @@
<script lang="ts"> <script lang="ts">
import {displayRelayUrl} from "@welshman/util"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components/Link.svelte"
import Icon from "@lib/components/Icon.svelte"
import {clip} from "@app/toast"
</script> </script>
<div class="column gap-4"> <div class="column gap-4">

View file

@ -26,7 +26,7 @@
const onSuccess = async (session: Session, relays: string[] = []) => { const onSuccess = async (session: Session, relays: string[] = []) => {
addSession(session) addSession(session)
await loadUserData(session.pubkey, relays) await loadUserData(session.pubkey, {relays})
pushToast({message: "Successfully logged in!"}) pushToast({message: "Successfully logged in!"})
clearModal() clearModal()

View file

@ -1,21 +1,15 @@
<script lang="ts"> <script lang="ts">
import {goto} from "$app/navigation" import {goto} from "$app/navigation"
import {append, remove} from "@welshman/lib"
import {displayRelayUrl} from "@welshman/util" import {displayRelayUrl} from "@welshman/util"
import {deriveRelay} from "@welshman/app"
import Field from "@lib/components/Field.svelte" import Field from "@lib/components/Field.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import {pushModal} from "@app/modal"
import {pushToast} from "@app/toast"
import {addRoomMembership} from "@app/commands" import {addRoomMembership} from "@app/commands"
import {makeSpacePath} from '@app/routes' import {makeSpacePath} from "@app/routes"
export let url export let url
const relay = deriveRelay(url)
const back = () => history.back() const back = () => history.back()
const tryCreate = async () => { const tryCreate = async () => {
@ -39,9 +33,7 @@
</script> </script>
<form class="column gap-4" on:submit|preventDefault={create}> <form class="column gap-4" on:submit|preventDefault={create}>
<h1 class="heading"> <h1 class="heading">Create a Room</h1>
Create a Room
</h1>
<p class="text-center"> <p class="text-center">
On <span class="text-primary">{displayRelayUrl(url)}</span> On <span class="text-primary">{displayRelayUrl(url)}</span>
</p> </p>

View file

@ -1,18 +1,13 @@
<script lang="ts"> <script lang="ts">
import {append, remove} from "@welshman/lib"
import {displayRelayUrl} from "@welshman/util" import {displayRelayUrl} from "@welshman/util"
import {deriveRelay} from "@welshman/app"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import {pushModal, clearModal} from "@app/modal" import {clearModal} from "@app/modal"
import {pushToast} from "@app/toast"
import {addSpaceMembership} from "@app/commands" import {addSpaceMembership} from "@app/commands"
export let url export let url
const relay = deriveRelay(url)
const back = () => history.back() const back = () => history.back()
const tryJoin = async () => { const tryJoin = async () => {

View file

@ -21,18 +21,16 @@ import {
FileUploadExtension, FileUploadExtension,
} from "nostr-editor" } from "nostr-editor"
import type {StampedEvent} from "@welshman/util" import type {StampedEvent} from "@welshman/util"
import {signer, topicSearch, profileSearch} from "@welshman/app" import {signer, profileSearch} from "@welshman/app"
import {LinkExtension, asInline, createSuggestions} from "@lib/tiptap" import {LinkExtension, asInline, createSuggestions} from "@lib/tiptap"
import GroupComposeMention from "@app/components/GroupComposeMention.svelte" import ChatComposeMention from "@app/components/ChatComposeMention.svelte"
import GroupComposeTopic from "@app/components/GroupComposeTopic.svelte" import ChatComposeEvent from "@app/components/ChatComposeEvent.svelte"
import GroupComposeEvent from "@app/components/GroupComposeEvent.svelte" import ChatComposeImage from "@app/components/ChatComposeImage.svelte"
import GroupComposeImage from "@app/components/GroupComposeImage.svelte" import ChatComposeBolt11 from "@app/components/ChatComposeBolt11.svelte"
import GroupComposeBolt11 from "@app/components/GroupComposeBolt11.svelte" import ChatComposeVideo from "@app/components/ChatComposeVideo.svelte"
import GroupComposeVideo from "@app/components/GroupComposeVideo.svelte" import ChatComposeLink from "@app/components/ChatComposeLink.svelte"
import GroupComposeLink from "@app/components/GroupComposeLink.svelte" import ChatComposeSuggestions from "@app/components/ChatComposeSuggestions.svelte"
import GroupComposeSuggestions from "@app/components/GroupComposeSuggestions.svelte" import ChatSuggestionProfile from "@app/components/ChatSuggestionProfile.svelte"
import GroupComposeTopicSuggestion from "@app/components/GroupComposeTopicSuggestion.svelte"
import GroupComposeProfileSuggestion from "@app/components/GroupComposeProfileSuggestion.svelte"
import {getPubkeyHints} from "@app/commands" import {getPubkeyHints} from "@app/commands"
export const addFile = (editor: Editor) => editor.chain().selectFiles().run() export const addFile = (editor: Editor) => editor.chain().selectFiles().run()
@ -74,13 +72,13 @@ export const getChatEditorOptions = ({uploading, sendMessage}: ChatComposeEditor
}, },
}), }),
LinkExtension.extend({ LinkExtension.extend({
addNodeView: () => SvelteNodeViewRenderer(GroupComposeLink), addNodeView: () => SvelteNodeViewRenderer(ChatComposeLink),
}), }),
Bolt11Extension.extend( Bolt11Extension.extend(
asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeBolt11)}), asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeBolt11)}),
), ),
NProfileExtension.extend({ NProfileExtension.extend({
addNodeView: () => SvelteNodeViewRenderer(GroupComposeMention), addNodeView: () => SvelteNodeViewRenderer(ChatComposeMention),
addProseMirrorPlugins() { addProseMirrorPlugins() {
return [ return [
createSuggestions({ createSuggestions({
@ -94,21 +92,19 @@ export const getChatEditorOptions = ({uploading, sendMessage}: ChatComposeEditor
return props.command({pubkey, nprofile, relays}) return props.command({pubkey, nprofile, relays})
}, },
suggestionComponent: GroupComposeProfileSuggestion, suggestionComponent: ChatSuggestionProfile,
suggestionsComponent: GroupComposeSuggestions, suggestionsComponent: ChatComposeSuggestions,
}), }),
] ]
}, },
}), }),
NEventExtension.extend( NEventExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeEvent)})),
asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeEvent)}), NAddrExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeEvent)})),
),
NAddrExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeEvent)})),
ImageExtension.extend( ImageExtension.extend(
asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeImage)}), asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeImage)}),
).configure({defaultUploadUrl: "https://nostr.build", defaultUploadType: "nip96"}), ).configure({defaultUploadUrl: "https://nostr.build", defaultUploadType: "nip96"}),
VideoExtension.extend( VideoExtension.extend(
asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeVideo)}), asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeVideo)}),
).configure({defaultUploadUrl: "https://nostr.build", defaultUploadType: "nip96"}), ).configure({defaultUploadUrl: "https://nostr.build", defaultUploadType: "nip96"}),
FileUploadExtension.configure({ FileUploadExtension.configure({
immediateUpload: false, immediateUpload: false,
@ -136,19 +132,17 @@ export const getChatViewOptions = (content: string) => ({
Paragraph, Paragraph,
Text, Text,
LinkExtension.extend({ LinkExtension.extend({
addNodeView: () => SvelteNodeViewRenderer(GroupComposeLink), addNodeView: () => SvelteNodeViewRenderer(ChatComposeLink),
}), }),
Bolt11Extension.extend( Bolt11Extension.extend(
asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeBolt11)}), asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeBolt11)}),
), ),
NProfileExtension.extend({ NProfileExtension.extend({
addNodeView: () => SvelteNodeViewRenderer(GroupComposeMention), addNodeView: () => SvelteNodeViewRenderer(ChatComposeMention),
}), }),
NEventExtension.extend( NEventExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeEvent)})),
asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeEvent)}), NAddrExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeEvent)})),
), ImageExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeImage)})),
NAddrExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeEvent)})), VideoExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeVideo)})),
ImageExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeImage)})),
VideoExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeVideo)})),
], ],
}) })

View file

@ -1,4 +1,4 @@
import {nip19} from 'nostr-tools' import {nip19} from "nostr-tools"
import type {Page} from "@sveltejs/kit" import type {Page} from "@sveltejs/kit"
import {userMembership, decodeNEvent} from "@app/state" import {userMembership, decodeNEvent} from "@app/state"
@ -6,7 +6,7 @@ export const makeSpacePath = (url: string, extra = "") => {
let path = `/spaces/${nip19.nrelayEncode(url)}` let path = `/spaces/${nip19.nrelayEncode(url)}`
if (extra) { if (extra) {
path += '/' + extra path += "/" + extra
} }
return path return path
@ -20,10 +20,11 @@ export const getPrimaryNavItemIndex = ($page: Page) => {
switch (getPrimaryNavItem($page)) { switch (getPrimaryNavItem($page)) {
case "discover": case "discover":
return urls.length + 2 return urls.length + 2
case "spaces": case "spaces": {
const routeUrl = decodeNEvent($page.params.nrelay) const routeUrl = decodeNEvent($page.params.nrelay)
return urls.findIndex(url => url === routeUrl) + 1 return urls.findIndex(url => url === routeUrl) + 1
}
case "settings": case "settings":
return urls.length + 3 return urls.length + 3
default: default:

View file

@ -1,24 +1,10 @@
import {nip19} from 'nostr-tools' import {nip19} from "nostr-tools"
import type {FuseResult} from "fuse.js"
import {get, derived, writable} from "svelte/store" import {get, derived, writable} from "svelte/store"
import type {Maybe} from "@welshman/lib" import type {Maybe} from "@welshman/lib"
import { import {setContext, max, groupBy, pushToMapKey, nthEq} from "@welshman/lib"
setContext,
max,
between,
groupBy,
pushToMapKey,
nthEq,
stripProtocol,
indexBy,
uniq,
} from "@welshman/lib"
import { import {
getIdFilters, getIdFilters,
getIdentifier,
normalizeRelayUrl,
RELAYS, RELAYS,
APP_DATA,
REACTION, REACTION,
ZAP_RESPONSE, ZAP_RESPONSE,
getRelayTagValues, getRelayTagValues,
@ -29,21 +15,16 @@ import type {TrustedEvent} from "@welshman/util"
import { import {
pubkey, pubkey,
repository, repository,
createSearch,
load, load,
subscribe, subscribe,
collection, collection,
loadRelay, loadRelay,
relaysByPubkey,
loadProfile, loadProfile,
profilesByPubkey, profilesByPubkey,
loadRelaySelections,
getWriteRelayUrls,
getDefaultAppContext, getDefaultAppContext,
getDefaultNetContext, getDefaultNetContext,
makeRouter, makeRouter,
} from "@welshman/app" } from "@welshman/app"
import type {Relay} from "@welshman/app"
import type {SubscribeRequestWithHandlers} from "@welshman/net" import type {SubscribeRequestWithHandlers} from "@welshman/net"
import {deriveEvents, deriveEventsMapped, withGetter} from "@welshman/store" import {deriveEvents, deriveEventsMapped, withGetter} from "@welshman/store"

View file

@ -20,8 +20,8 @@
freshness, freshness,
storageAdapters, storageAdapters,
} from "@welshman/app" } from "@welshman/app"
import type {PublishStatusData, PublishStatusDataByUrlById} from "@welshman/app" import * as app from "@welshman/app"
import {createEventStore, adapter} from "@welshman/store" import {createEventStore} from "@welshman/store"
import ModalBox from "@lib/components/ModalBox.svelte" import ModalBox from "@lib/components/ModalBox.svelte"
import Toast from "@app/components/Toast.svelte" import Toast from "@app/components/Toast.svelte"
import Landing from "@app/components/Landing.svelte" import Landing from "@app/components/Landing.svelte"
@ -59,7 +59,7 @@
} }
onMount(() => { onMount(() => {
Object.assign(window, {get, state}) Object.assign(window, {get, ...app, ...state})
ready = db ready = db
? Promise.resolve() ? Promise.resolve()

View file

@ -2,7 +2,7 @@
import {onMount} from "svelte" import {onMount} from "svelte"
import Masonry from "svelte-bricks" import Masonry from "svelte-bricks"
import {displayRelayUrl} from "@welshman/util" import {displayRelayUrl} from "@welshman/util"
import {load, relaySearch} from "@welshman/app" import {relaySearch} from "@welshman/app"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import {makeSpacePath} from "@app/routes" import {makeSpacePath} from "@app/routes"
import {userMembership, discoverRelays} from "@app/state" import {userMembership, discoverRelays} from "@app/state"
@ -58,7 +58,7 @@
<div class="card-body"> <div class="card-body">
<h2 class="card-title justify-center">{displayRelayUrl(relay.url)}</h2> <h2 class="card-title justify-center">{displayRelayUrl(relay.url)}</h2>
{#if relay.profile?.description} {#if relay.profile?.description}
<p class="py-4 text-sm text-center">{relay.profile.description}</p> <p class="py-4 text-center text-sm">{relay.profile.description}</p>
{/if} {/if}
</div> </div>
</a> </a>

View file

@ -1,9 +1,8 @@
<script lang="ts"> <script lang="ts">
import {onMount} from "svelte" import {onMount} from "svelte"
import {readable} from "svelte/store" import {readable} from "svelte/store"
import {displayRelayUrl, isShareableRelayUrl} from "@welshman/util" import {displayRelayUrl} from "@welshman/util"
import type {SignedEvent} from "@welshman/util" import {relaySearch} from "@welshman/app"
import {subscribe, loadRelay, relaySearch} from "@welshman/app"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import {INDEXER_RELAYS, discoverRelays} from "@app/state" import {INDEXER_RELAYS, discoverRelays} from "@app/state"

View file

@ -1,8 +1,7 @@
<script lang="ts"> <script lang="ts">
import {nip19} from 'nostr-tools'
import {page} from "$app/stores" import {page} from "$app/stores"
import {sort} from '@welshman/lib' import {sort} from "@welshman/lib"
import {displayRelayUrl} from '@welshman/util' import {displayRelayUrl} from "@welshman/util"
import {fly} from "@lib/transition" import {fly} from "@lib/transition"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Page from "@lib/components/Page.svelte" import Page from "@lib/components/Page.svelte"
@ -104,7 +103,8 @@
{#each rooms as topic, i (topic)} {#each rooms as topic, i (topic)}
<div transition:fly|local={{delay: 250 + i * 50}}> <div transition:fly|local={{delay: 250 + i * 50}}>
<SecondaryNavItem href={makeSpacePath(url, topic)}> <SecondaryNavItem href={makeSpacePath(url, topic)}>
<Icon icon="hashtag" /> {topic} <Icon icon="hashtag" />
{topic}
</SecondaryNavItem> </SecondaryNavItem>
</div> </div>
{/each} {/each}

View file

@ -15,9 +15,9 @@
import {subscribe, formatTimestampAsDate} from "@welshman/app" import {subscribe, formatTimestampAsDate} from "@welshman/app"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import GroupNote from "@app/components/GroupNote.svelte" import ChatMessage from "@app/components/ChatMessage.svelte"
import GroupCompose from "@app/components/GroupCompose.svelte" import ChatCompose from "@app/components/ChatCompose.svelte"
import {deriveChat, userMembership, MESSAGE, REPLY} from "@app/state" import {deriveChat, MESSAGE, REPLY} from "@app/state"
const {url, topic} = $page.params const {url, topic} = $page.params
const chat = deriveChat(url) const chat = deriveChat(url)
@ -62,7 +62,7 @@
onMount(() => { onMount(() => {
const since = now() - 30 const since = now() - 30
const kinds = [MESSAGE, REPLY] const kinds = [MESSAGE, REPLY]
const filter = topic ? {kinds, since, "#t": [topic]} : {kinds, since} as Filter const filter = topic ? {kinds, since, "#t": [topic]} : ({kinds, since} as Filter)
const sub = subscribe({filters: [filter], relays: [url]}) const sub = subscribe({filters: [filter], relays: [url]})
return () => sub.close() return () => sub.close()
@ -87,7 +87,7 @@
<div class="h-px flex-grow bg-base-content opacity-25" /> <div class="h-px flex-grow bg-base-content opacity-25" />
</div> </div>
{:else} {:else}
<GroupNote event={assertEvent(value)} {showPubkey} /> <ChatMessage event={assertEvent(value)} {showPubkey} />
{/if} {/if}
{/each} {/each}
<p class="flex h-10 items-center justify-center py-20"> <p class="flex h-10 items-center justify-center py-20">
@ -100,5 +100,5 @@
</Spinner> </Spinner>
</p> </p>
</div> </div>
<GroupCompose {url} {topic} /> <ChatCompose {url} {topic} />
</div> </div>