Make sharing indicator nicer

This commit is contained in:
Jon Staab
2025-02-06 11:33:01 -08:00
parent 98a0511b34
commit 19f657e348
8 changed files with 56 additions and 30 deletions

View File

@@ -6,7 +6,7 @@
* Migrate to svelte 5 (fixes some bugs, probably introduces others) * Migrate to svelte 5 (fixes some bugs, probably introduces others)
* Migrate to new welshman editor * Migrate to new welshman editor
* Make reply indicator nicer * Make reply indicator nicer
* (pending) Make share indicator nicer * Make share indicator nicer
* Improve feed loading * Improve feed loading
* (pending) Show marker for last activity in chat * (pending) Show marker for last activity in chat

View File

@@ -1,5 +1,4 @@
<script lang="ts"> <script lang="ts">
import {onMount} from "svelte"
import {writable} from "svelte/store" import {writable} from "svelte/store"
import {isMobile, preventDefault} from "@lib/html" import {isMobile, preventDefault} from "@lib/html"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
@@ -9,10 +8,9 @@
interface Props { interface Props {
onSubmit: any onSubmit: any
content?: string
} }
const {onSubmit, content = ""}: Props = $props() const {onSubmit}: Props = $props()
const autofocus = !isMobile const autofocus = !isMobile
@@ -36,10 +34,6 @@
} }
const editor = makeEditor({autofocus, submit, uploading, aggressive: true}) const editor = makeEditor({autofocus, submit, uploading, aggressive: true})
onMount(() => {
editor.chain().setContent(content).run()
})
</script> </script>
<form class="relative z-feature flex gap-2 p-2" onsubmit={preventDefault(submit)}> <form class="relative z-feature flex gap-2 p-2" onsubmit={preventDefault(submit)}>

View File

@@ -6,18 +6,21 @@
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Content from "@app/components/Content.svelte" import Content from "@app/components/Content.svelte"
interface Props { const {
verb,
event,
clear,
}: {
verb: string
event: TrustedEvent event: TrustedEvent
clear: () => void clear: () => void
} } = $props()
const {event, clear}: Props = $props()
</script> </script>
<div <div
class="relative border-l-2 border-solid border-primary bg-base-300 px-2 py-1 pr-8 text-xs" class="relative border-l-2 border-solid border-primary bg-base-300 px-2 py-1 pr-8 text-xs"
transition:slide> transition:slide>
<p class="text-primary">Replying to @{displayProfileByPubkey(event.pubkey)}</p> <p class="text-primary">{verb} @{displayProfileByPubkey(event.pubkey)}</p>
{#key event.id} {#key event.id}
<Content {event} hideMedia minLength={100} maxLength={300} expandMode="disabled" /> <Content {event} hideMedia minLength={100} maxLength={300} expandMode="disabled" />
{/key} {/key}

View File

@@ -1,4 +1,5 @@
<script lang="ts"> <script lang="ts">
import type {Snippet} from "svelte"
import {onMount} from "svelte" import {onMount} from "svelte"
import {int, nthNe, MINUTE, sortBy, remove} from "@welshman/lib" import {int, nthNe, MINUTE, sortBy, remove} from "@welshman/lib"
import type {TrustedEvent, EventContent} from "@welshman/util" import type {TrustedEvent, EventContent} from "@welshman/util"
@@ -28,7 +29,13 @@
import {pushModal} from "@app/modal" import {pushModal} from "@app/modal"
import {sendWrapped, prependParent} from "@app/commands" import {sendWrapped, prependParent} from "@app/commands"
const {id, info = undefined} = $props() const {
id,
info,
}: {
id: string
info?: Snippet
} = $props()
const chat = deriveChat(id) const chat = deriveChat(id)
const pubkeys = splitChatId(id) const pubkeys = splitChatId(id)
@@ -205,7 +212,7 @@
</p> </p>
</div> </div>
{#if parent} {#if parent}
<ChatComposeParent event={parent} clear={clearParent} /> <ChatComposeParent event={parent} clear={clearParent} verb="Replying to" />
{/if} {/if}
<ChatCompose bind:this={compose} {onSubmit} /> <ChatCompose bind:this={compose} {onSubmit} />
</div> </div>

View File

@@ -115,6 +115,8 @@
const hasEllipsis = $derived(shortContent.some(isEllipsis)) const hasEllipsis = $derived(shortContent.some(isEllipsis))
const expandInline = $derived(hasEllipsis && expandMode === "inline") const expandInline = $derived(hasEllipsis && expandMode === "inline")
const expandBlock = $derived(hasEllipsis && expandMode === "block") const expandBlock = $derived(hasEllipsis && expandMode === "block")
$inspect(fullContent)
</script> </script>
<div class="relative"> <div class="relative">
@@ -131,8 +133,8 @@
class="overflow-hidden text-ellipsis break-words" class="overflow-hidden text-ellipsis break-words"
style={expandBlock ? "mask-image: linear-gradient(0deg, transparent 0px, black 100px)" : ""}> style={expandBlock ? "mask-image: linear-gradient(0deg, transparent 0px, black 100px)" : ""}>
{#each shortContent as parsed, i} {#each shortContent as parsed, i}
{#if isNewline(parsed)} {#if isNewline(parsed) && !isBlock(i - 1)}
<ContentNewline value={parsed.value.slice(isBlock(i - 1) ? 1 : 0)} /> <ContentNewline value={parsed.value} />
{:else if isTopic(parsed)} {:else if isTopic(parsed)}
<ContentTopic value={parsed.value} /> <ContentTopic value={parsed.value} />
{:else if isCode(parsed)} {:else if isCode(parsed)}

View File

@@ -3,12 +3,12 @@
import {goto} from "$app/navigation" import {goto} from "$app/navigation"
import {ctx, nthEq} from "@welshman/lib" import {ctx, nthEq} from "@welshman/lib"
import {tracker, repository} from "@welshman/app" import {tracker, repository} from "@welshman/app"
import {Address, DIRECT_MESSAGE, MESSAGE, THREAD} from "@welshman/util" import {Address, DIRECT_MESSAGE, MESSAGE, THREAD, EVENT_TIME} from "@welshman/util"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import NoteCard from "@app/components/NoteCard.svelte" import NoteCard from "@app/components/NoteCard.svelte"
import {deriveEvent, entityLink, ROOM} from "@app/state" import {deriveEvent, entityLink, ROOM} from "@app/state"
import {makeThreadPath, makeRoomPath} from "@app/routes" import {makeThreadPath, makeCalendarPath, makeRoomPath} from "@app/routes"
const {value, event, noteContent, relays = [], minimal = false} = $props() const {value, event, noteContent, relays = [], minimal = false} = $props()
@@ -70,6 +70,10 @@
return goto(makeThreadPath(url, $quote.id)) return goto(makeThreadPath(url, $quote.id))
} }
if ($quote.kind === EVENT_TIME) {
return goto(makeCalendarPath(url, $quote.id))
}
if ($quote.kind === MESSAGE) { if ($quote.kind === MESSAGE) {
return scrollToEvent($quote.id) || openMessage(url, room, $quote.id) return scrollToEvent($quote.id) || openMessage(url, room, $quote.id)
} }
@@ -82,6 +86,10 @@
return goto(makeThreadPath(url, id)) return goto(makeThreadPath(url, id))
} }
if (parseInt(kind) === EVENT_TIME) {
return goto(makeCalendarPath(url, id))
}
if (parseInt(kind) === MESSAGE) { if (parseInt(kind) === MESSAGE) {
return scrollToEvent(id) || openMessage(url, room, id) return scrollToEvent(id) || openMessage(url, room, id)
} }

View File

@@ -1,9 +1,6 @@
<script lang="ts"> <script lang="ts">
import {nip19} from "nostr-tools"
import {goto} from "$app/navigation" import {goto} from "$app/navigation"
import {ctx} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import {toNostrURI} from "@welshman/util"
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
@@ -16,13 +13,10 @@
const {url, noun, event}: {url: string; noun: string; event: TrustedEvent} = $props() const {url, noun, event}: {url: string; noun: string; event: TrustedEvent} = $props()
const relays = ctx.app.router.Event(event).getUrls()
const nevent = nip19.neventEncode({id: event.id, relays})
const back = () => history.back() const back = () => history.back()
const onSubmit = () => { const onSubmit = () => {
setKey("content", toNostrURI(nevent)) setKey("share", event)
goto(makeRoomPath(url, selection), {replaceState: true}) goto(makeRoomPath(url, selection), {replaceState: true})
} }

View File

@@ -42,7 +42,6 @@
const {room = GENERAL} = $page.params const {room = GENERAL} = $page.params
const lastChecked = $checked[$page.url.pathname] const lastChecked = $checked[$page.url.pathname]
const content = popKey<string>("content") || ""
const url = decodeRelay($page.params.relay) const url = decodeRelay($page.params.relay)
const filter = {kinds: [MESSAGE], "#h": [room]} const filter = {kinds: [MESSAGE], "#h": [room]}
const relay = deriveRelay(url) const relay = deriveRelay(url)
@@ -78,17 +77,32 @@
parent = undefined parent = undefined
} }
const clearShare = () => {
share = undefined
}
const onSubmit = ({content, tags}: EventContent) => { const onSubmit = ({content, tags}: EventContent) => {
tags.push(tagRoom(room, url)) tags.push(tagRoom(room, url))
tags.push(PROTECTED) tags.push(PROTECTED)
let template = {content, tags}
if (share) {
template = prependParent(share, template)
}
if (parent) {
template = prependParent(parent, template)
}
publishThunk({ publishThunk({
relays: [url], relays: [url],
event: createEvent(MESSAGE, prependParent(parent, {content, tags})), event: createEvent(MESSAGE, template),
delay: $userSettingValues.send_delay, delay: $userSettingValues.send_delay,
}) })
clearParent() clearParent()
clearShare()
} }
const onScroll = () => { const onScroll = () => {
@@ -113,6 +127,7 @@
const scrollToBottom = () => element?.scrollTo({top: 0, behavior: "smooth"}) const scrollToBottom = () => element?.scrollTo({top: 0, behavior: "smooth"})
let loading = $state(true) let loading = $state(true)
let share = $state(popKey<TrustedEvent | undefined>("share"))
let parent: TrustedEvent | undefined = $state() let parent: TrustedEvent | undefined = $state()
let element: HTMLElement | undefined = $state() let element: HTMLElement | undefined = $state()
let newMessages: HTMLElement | undefined = $state() let newMessages: HTMLElement | undefined = $state()
@@ -264,9 +279,12 @@
{/if} {/if}
<div class="saib"> <div class="saib">
{#if parent} {#if parent}
<ChannelComposeParent event={parent} clear={clearParent} /> <ChannelComposeParent event={parent} clear={clearParent} verb="Replying to" />
{/if} {/if}
<ChannelCompose bind:this={compose} {content} {onSubmit} /> {#if share}
<ChannelComposeParent event={share} clear={clearShare} verb="Sharing" />
{/if}
<ChannelCompose bind:this={compose} {onSubmit} />
</div> </div>
</div> </div>