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
+1 -1
View File
@@ -105,7 +105,7 @@
}
.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 {
+36 -9
View File
@@ -1,19 +1,18 @@
import {uniqBy, equals, uniq, now, choice} from "@welshman/lib"
import {getRelayTagValues, createEvent, displayProfile} from "@welshman/util"
import {PublishStatus} from "@welshman/net"
import {uniqBy, sleep, chunk, equals, choice} from "@welshman/lib"
import {getPubkeyTagValues, createEvent, displayProfile} from "@welshman/util"
import type {SubscribeRequestWithHandlers} from "@welshman/net"
import {
pubkey,
repository,
load,
makeThunk,
publishThunk,
loadProfile,
profilesByPubkey,
relaySelectionsByPubkey,
loadRelaySelections,
getWriteRelayUrls,
loadFollows,
loadMutes,
followsByPubkey,
} from "@welshman/app"
import {MEMBERSHIPS, INDEXER_RELAYS} from "@app/state"
@@ -49,8 +48,32 @@ export const makeIMeta = (url: string, data: Record<string, string>) => [
// Loaders
export const loadUserData = (pubkey: string, hints: string[] = []) =>
Promise.all([loadProfile(pubkey), loadFollows(pubkey), loadMutes(pubkey)])
export const loadUserData = (
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
@@ -73,10 +96,14 @@ export const addSpaceMembership = (url: string) =>
updateList(MEMBERSHIPS, (tags: string[][]) => uniqBy(t => t.join(""), [...tags, ["r", url]]))
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) =>
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) =>
updateList(MEMBERSHIPS, (tags: string[][]) => tags.filter(t => !equals(["t", topic, url], t)))
@@ -10,12 +10,12 @@
export let selected: NodeViewProps["selected"]
</script>
<NodeViewWrapper class="inline">
<NodeViewWrapper class="inline-block">
<Link
external
href={node.attrs.url}
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)}
</Link>
</NodeViewWrapper>
@@ -65,10 +65,10 @@
data-theme={$theme}
bind:this={element}
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}
<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:click|preventDefault={() => select(term)}>
Use "<svelte:component this={component} value={term} />"
@@ -76,7 +76,7 @@
{/if}
{#each items as value, i (value)}
<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:text-primary-content={index === i}
on:mousedown|preventDefault
@@ -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>
@@ -1,5 +0,0 @@
<script lang="ts">
export let value
</script>
#{value}
-3
View File
@@ -1,9 +1,6 @@
<script lang="ts">
import {displayRelayUrl} from "@welshman/util"
import Button from "@lib/components/Button.svelte"
import Link from "@lib/components/Link.svelte"
import Icon from "@lib/components/Icon.svelte"
import {clip} from "@app/toast"
</script>
<div class="column gap-4">
+1 -1
View File
@@ -26,7 +26,7 @@
const onSuccess = async (session: Session, relays: string[] = []) => {
addSession(session)
await loadUserData(session.pubkey, relays)
await loadUserData(session.pubkey, {relays})
pushToast({message: "Successfully logged in!"})
clearModal()
+2 -10
View File
@@ -1,21 +1,15 @@
<script lang="ts">
import {goto} from "$app/navigation"
import {append, remove} from "@welshman/lib"
import {displayRelayUrl} from "@welshman/util"
import {deriveRelay} from "@welshman/app"
import Field from "@lib/components/Field.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
import {pushModal} from "@app/modal"
import {pushToast} from "@app/toast"
import {addRoomMembership} from "@app/commands"
import {makeSpacePath} from '@app/routes'
import {makeSpacePath} from "@app/routes"
export let url
const relay = deriveRelay(url)
const back = () => history.back()
const tryCreate = async () => {
@@ -39,9 +33,7 @@
</script>
<form class="column gap-4" on:submit|preventDefault={create}>
<h1 class="heading">
Create a Room
</h1>
<h1 class="heading">Create a Room</h1>
<p class="text-center">
On <span class="text-primary">{displayRelayUrl(url)}</span>
</p>
+1 -6
View File
@@ -1,18 +1,13 @@
<script lang="ts">
import {append, remove} from "@welshman/lib"
import {displayRelayUrl} from "@welshman/util"
import {deriveRelay} from "@welshman/app"
import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
import {pushModal, clearModal} from "@app/modal"
import {pushToast} from "@app/toast"
import {clearModal} from "@app/modal"
import {addSpaceMembership} from "@app/commands"
export let url
const relay = deriveRelay(url)
const back = () => history.back()
const tryJoin = async () => {
+25 -31
View File
@@ -21,18 +21,16 @@ import {
FileUploadExtension,
} from "nostr-editor"
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 GroupComposeMention from "@app/components/GroupComposeMention.svelte"
import GroupComposeTopic from "@app/components/GroupComposeTopic.svelte"
import GroupComposeEvent from "@app/components/GroupComposeEvent.svelte"
import GroupComposeImage from "@app/components/GroupComposeImage.svelte"
import GroupComposeBolt11 from "@app/components/GroupComposeBolt11.svelte"
import GroupComposeVideo from "@app/components/GroupComposeVideo.svelte"
import GroupComposeLink from "@app/components/GroupComposeLink.svelte"
import GroupComposeSuggestions from "@app/components/GroupComposeSuggestions.svelte"
import GroupComposeTopicSuggestion from "@app/components/GroupComposeTopicSuggestion.svelte"
import GroupComposeProfileSuggestion from "@app/components/GroupComposeProfileSuggestion.svelte"
import ChatComposeMention from "@app/components/ChatComposeMention.svelte"
import ChatComposeEvent from "@app/components/ChatComposeEvent.svelte"
import ChatComposeImage from "@app/components/ChatComposeImage.svelte"
import ChatComposeBolt11 from "@app/components/ChatComposeBolt11.svelte"
import ChatComposeVideo from "@app/components/ChatComposeVideo.svelte"
import ChatComposeLink from "@app/components/ChatComposeLink.svelte"
import ChatComposeSuggestions from "@app/components/ChatComposeSuggestions.svelte"
import ChatSuggestionProfile from "@app/components/ChatSuggestionProfile.svelte"
import {getPubkeyHints} from "@app/commands"
export const addFile = (editor: Editor) => editor.chain().selectFiles().run()
@@ -74,13 +72,13 @@ export const getChatEditorOptions = ({uploading, sendMessage}: ChatComposeEditor
},
}),
LinkExtension.extend({
addNodeView: () => SvelteNodeViewRenderer(GroupComposeLink),
addNodeView: () => SvelteNodeViewRenderer(ChatComposeLink),
}),
Bolt11Extension.extend(
asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeBolt11)}),
asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeBolt11)}),
),
NProfileExtension.extend({
addNodeView: () => SvelteNodeViewRenderer(GroupComposeMention),
addNodeView: () => SvelteNodeViewRenderer(ChatComposeMention),
addProseMirrorPlugins() {
return [
createSuggestions({
@@ -94,21 +92,19 @@ export const getChatEditorOptions = ({uploading, sendMessage}: ChatComposeEditor
return props.command({pubkey, nprofile, relays})
},
suggestionComponent: GroupComposeProfileSuggestion,
suggestionsComponent: GroupComposeSuggestions,
suggestionComponent: ChatSuggestionProfile,
suggestionsComponent: ChatComposeSuggestions,
}),
]
},
}),
NEventExtension.extend(
asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeEvent)}),
),
NAddrExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeEvent)})),
NEventExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeEvent)})),
NAddrExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeEvent)})),
ImageExtension.extend(
asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeImage)}),
asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeImage)}),
).configure({defaultUploadUrl: "https://nostr.build", defaultUploadType: "nip96"}),
VideoExtension.extend(
asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeVideo)}),
asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeVideo)}),
).configure({defaultUploadUrl: "https://nostr.build", defaultUploadType: "nip96"}),
FileUploadExtension.configure({
immediateUpload: false,
@@ -136,19 +132,17 @@ export const getChatViewOptions = (content: string) => ({
Paragraph,
Text,
LinkExtension.extend({
addNodeView: () => SvelteNodeViewRenderer(GroupComposeLink),
addNodeView: () => SvelteNodeViewRenderer(ChatComposeLink),
}),
Bolt11Extension.extend(
asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeBolt11)}),
asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeBolt11)}),
),
NProfileExtension.extend({
addNodeView: () => SvelteNodeViewRenderer(GroupComposeMention),
addNodeView: () => SvelteNodeViewRenderer(ChatComposeMention),
}),
NEventExtension.extend(
asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeEvent)}),
),
NAddrExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeEvent)})),
ImageExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeImage)})),
VideoExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(GroupComposeVideo)})),
NEventExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeEvent)})),
NAddrExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeEvent)})),
ImageExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeImage)})),
VideoExtension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(ChatComposeVideo)})),
],
})
+4 -3
View File
@@ -1,4 +1,4 @@
import {nip19} from 'nostr-tools'
import {nip19} from "nostr-tools"
import type {Page} from "@sveltejs/kit"
import {userMembership, decodeNEvent} from "@app/state"
@@ -6,7 +6,7 @@ export const makeSpacePath = (url: string, extra = "") => {
let path = `/spaces/${nip19.nrelayEncode(url)}`
if (extra) {
path += '/' + extra
path += "/" + extra
}
return path
@@ -20,10 +20,11 @@ export const getPrimaryNavItemIndex = ($page: Page) => {
switch (getPrimaryNavItem($page)) {
case "discover":
return urls.length + 2
case "spaces":
case "spaces": {
const routeUrl = decodeNEvent($page.params.nrelay)
return urls.findIndex(url => url === routeUrl) + 1
}
case "settings":
return urls.length + 3
default:
+2 -21
View File
@@ -1,24 +1,10 @@
import {nip19} from 'nostr-tools'
import type {FuseResult} from "fuse.js"
import {nip19} from "nostr-tools"
import {get, derived, writable} from "svelte/store"
import type {Maybe} from "@welshman/lib"
import {
setContext,
max,
between,
groupBy,
pushToMapKey,
nthEq,
stripProtocol,
indexBy,
uniq,
} from "@welshman/lib"
import {setContext, max, groupBy, pushToMapKey, nthEq} from "@welshman/lib"
import {
getIdFilters,
getIdentifier,
normalizeRelayUrl,
RELAYS,
APP_DATA,
REACTION,
ZAP_RESPONSE,
getRelayTagValues,
@@ -29,21 +15,16 @@ import type {TrustedEvent} from "@welshman/util"
import {
pubkey,
repository,
createSearch,
load,
subscribe,
collection,
loadRelay,
relaysByPubkey,
loadProfile,
profilesByPubkey,
loadRelaySelections,
getWriteRelayUrls,
getDefaultAppContext,
getDefaultNetContext,
makeRouter,
} from "@welshman/app"
import type {Relay} from "@welshman/app"
import type {SubscribeRequestWithHandlers} from "@welshman/net"
import {deriveEvents, deriveEventsMapped, withGetter} from "@welshman/store"
+3 -3
View File
@@ -20,8 +20,8 @@
freshness,
storageAdapters,
} from "@welshman/app"
import type {PublishStatusData, PublishStatusDataByUrlById} from "@welshman/app"
import {createEventStore, adapter} from "@welshman/store"
import * as app from "@welshman/app"
import {createEventStore} from "@welshman/store"
import ModalBox from "@lib/components/ModalBox.svelte"
import Toast from "@app/components/Toast.svelte"
import Landing from "@app/components/Landing.svelte"
@@ -59,7 +59,7 @@
}
onMount(() => {
Object.assign(window, {get, state})
Object.assign(window, {get, ...app, ...state})
ready = db
? Promise.resolve()
+2 -2
View File
@@ -2,7 +2,7 @@
import {onMount} from "svelte"
import Masonry from "svelte-bricks"
import {displayRelayUrl} from "@welshman/util"
import {load, relaySearch} from "@welshman/app"
import {relaySearch} from "@welshman/app"
import Icon from "@lib/components/Icon.svelte"
import {makeSpacePath} from "@app/routes"
import {userMembership, discoverRelays} from "@app/state"
@@ -58,7 +58,7 @@
<div class="card-body">
<h2 class="card-title justify-center">{displayRelayUrl(relay.url)}</h2>
{#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}
</div>
</a>
+2 -3
View File
@@ -1,9 +1,8 @@
<script lang="ts">
import {onMount} from "svelte"
import {readable} from "svelte/store"
import {displayRelayUrl, isShareableRelayUrl} from "@welshman/util"
import type {SignedEvent} from "@welshman/util"
import {subscribe, loadRelay, relaySearch} from "@welshman/app"
import {displayRelayUrl} from "@welshman/util"
import {relaySearch} from "@welshman/app"
import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte"
import {INDEXER_RELAYS, discoverRelays} from "@app/state"
+4 -4
View File
@@ -1,8 +1,7 @@
<script lang="ts">
import {nip19} from 'nostr-tools'
import {page} from "$app/stores"
import {sort} from '@welshman/lib'
import {displayRelayUrl} from '@welshman/util'
import {sort} from "@welshman/lib"
import {displayRelayUrl} from "@welshman/util"
import {fly} from "@lib/transition"
import Icon from "@lib/components/Icon.svelte"
import Page from "@lib/components/Page.svelte"
@@ -104,7 +103,8 @@
{#each rooms as topic, i (topic)}
<div transition:fly|local={{delay: 250 + i * 50}}>
<SecondaryNavItem href={makeSpacePath(url, topic)}>
<Icon icon="hashtag" /> {topic}
<Icon icon="hashtag" />
{topic}
</SecondaryNavItem>
</div>
{/each}
@@ -15,9 +15,9 @@
import {subscribe, formatTimestampAsDate} from "@welshman/app"
import Icon from "@lib/components/Icon.svelte"
import Spinner from "@lib/components/Spinner.svelte"
import GroupNote from "@app/components/GroupNote.svelte"
import GroupCompose from "@app/components/GroupCompose.svelte"
import {deriveChat, userMembership, MESSAGE, REPLY} from "@app/state"
import ChatMessage from "@app/components/ChatMessage.svelte"
import ChatCompose from "@app/components/ChatCompose.svelte"
import {deriveChat, MESSAGE, REPLY} from "@app/state"
const {url, topic} = $page.params
const chat = deriveChat(url)
@@ -62,7 +62,7 @@
onMount(() => {
const since = now() - 30
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]})
return () => sub.close()
@@ -87,7 +87,7 @@
<div class="h-px flex-grow bg-base-content opacity-25" />
</div>
{:else}
<GroupNote event={assertEvent(value)} {showPubkey} />
<ChatMessage event={assertEvent(value)} {showPubkey} />
{/if}
{/each}
<p class="flex h-10 items-center justify-center py-20">
@@ -100,5 +100,5 @@
</Spinner>
</p>
</div>
<GroupCompose {url} {topic} />
<ChatCompose {url} {topic} />
</div>