From e0099141aa9bd076f79fa38dd212523a4dda6f91 Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Mon, 6 Oct 2025 11:23:19 -0700 Subject: [PATCH] Refactor synchronization logic --- src/app/components/MenuSpace.svelte | 25 +-- src/app/components/MenuSpaceButton.svelte | 2 +- .../components/NewNotificationSound.svelte | 3 +- src/app/components/ProfileBadges.svelte | 6 +- src/app/components/ReactionSummary.svelte | 4 +- src/app/components/SpaceJoinConfirm.svelte | 13 +- src/app/core/requests.ts | 169 ++++----------- src/app/core/state.ts | 56 +++-- src/app/core/sync.ts | 194 +++++++++++++++--- src/app/util/notifications.ts | 17 ++ src/routes/chat/+layout.svelte | 12 +- src/routes/spaces/[relay]/+layout.svelte | 26 +-- src/routes/spaces/[relay]/[room]/+page.svelte | 43 +--- .../spaces/[relay]/calendar/+page.svelte | 22 +- src/routes/spaces/[relay]/chat/+page.svelte | 34 +-- src/routes/spaces/[relay]/goals/+page.svelte | 52 ++--- .../spaces/[relay]/threads/+page.svelte | 54 ++--- 17 files changed, 357 insertions(+), 375 deletions(-) diff --git a/src/app/components/MenuSpace.svelte b/src/app/components/MenuSpace.svelte index eca97a59..9731c4e9 100644 --- a/src/app/components/MenuSpace.svelte +++ b/src/app/components/MenuSpace.svelte @@ -1,7 +1,8 @@ diff --git a/src/app/components/NewNotificationSound.svelte b/src/app/components/NewNotificationSound.svelte index a6d23712..d6a13ee4 100644 --- a/src/app/components/NewNotificationSound.svelte +++ b/src/app/components/NewNotificationSound.svelte @@ -14,11 +14,12 @@ enabled = false } }) + let notificationCount = $state($notifications.size) const playSound = () => { if (enabled && $userSettingsValues.play_notification_sound) { - audioElement.play() + audioElement?.play() } } diff --git a/src/app/components/ProfileBadges.svelte b/src/app/components/ProfileBadges.svelte index 5520b534..e99d7261 100644 --- a/src/app/components/ProfileBadges.svelte +++ b/src/app/components/ProfileBadges.svelte @@ -5,11 +5,11 @@ import type {Filter} from "@welshman/util" import {deriveEvents} from "@welshman/store" import {formatTimestampRelative} from "@welshman/lib" - import {NOTE, ROOMS, MESSAGE, THREAD, COMMENT, getRelayTags, getListTags} from "@welshman/util" + import {NOTE, ROOMS, COMMENT, getRelayTags, getListTags} from "@welshman/util" import {repository, loadRelaySelections} from "@welshman/app" import Button from "@lib/components/Button.svelte" import ProfileSpaces from "@app/components/ProfileSpaces.svelte" - import {membershipsByPubkey} from "@app/core/state" + import {membershipsByPubkey, MESSAGE_KINDS} from "@app/core/state" import {goToEvent} from "@app/util/routes" import {pushModal} from "@app/util/modal" @@ -36,7 +36,7 @@ load({ filters: [ {authors: [pubkey], kinds: [ROOMS]}, - {authors: [pubkey], limit: 1, kinds: [NOTE, MESSAGE, THREAD, COMMENT]}, + {authors: [pubkey], limit: 1, kinds: [NOTE, COMMENT, ...MESSAGE_KINDS]}, ], relays: Router.get().FromPubkeys([pubkey]).getUrls(), }) diff --git a/src/app/components/ReactionSummary.svelte b/src/app/components/ReactionSummary.svelte index 0bba7337..325d569c 100644 --- a/src/app/components/ReactionSummary.svelte +++ b/src/app/components/ReactionSummary.svelte @@ -3,6 +3,7 @@ import type {Snippet} from "svelte" import {groupBy, sum, uniq, uniqBy, batch, displayList} from "@welshman/lib" import { + REPORT, REACTION, ZAP_RESPONSE, getReplyFilters, @@ -10,7 +11,6 @@ getEmojiTag, fromMsats, getTag, - REPORT, DELETE, } from "@welshman/util" import type {TrustedEvent, EventContent, Zap} from "@welshman/util" @@ -96,7 +96,7 @@ load({ relays: [url], signal: controller.signal, - filters: getReplyFilters([event], {kinds: [REPORT, DELETE, ...REACTION_KINDS]}), + filters: getReplyFilters([event], {kinds: REACTION_KINDS}), onEvent: batch(300, (events: TrustedEvent[]) => { load({ relays: [url], diff --git a/src/app/components/SpaceJoinConfirm.svelte b/src/app/components/SpaceJoinConfirm.svelte index a58c1b5f..c048340a 100644 --- a/src/app/components/SpaceJoinConfirm.svelte +++ b/src/app/components/SpaceJoinConfirm.svelte @@ -1,8 +1,6 @@ diff --git a/src/routes/spaces/[relay]/+layout.svelte b/src/routes/spaces/[relay]/+layout.svelte index e4705a35..f5fd83b9 100644 --- a/src/routes/spaces/[relay]/+layout.svelte +++ b/src/routes/spaces/[relay]/+layout.svelte @@ -2,8 +2,8 @@ import type {Snippet} from "svelte" import {onMount} from "svelte" import {page} from "$app/stores" - import {ago, sleep, once, MONTH} from "@welshman/lib" - import {ROOM_META, EVENT_TIME, THREAD, COMMENT, MESSAGE, displayRelayUrl} from "@welshman/util" + import {sleep, once} from "@welshman/lib" + import {displayRelayUrl} from "@welshman/util" import {SocketStatus} from "@welshman/net" import Page from "@lib/components/Page.svelte" import Dialog from "@lib/components/Dialog.svelte" @@ -19,10 +19,7 @@ deriveRelayAuthError, relaysPendingTrust, deriveSocket, - userRoomsByUrl, } from "@app/core/state" - import {pullConservatively} from "@app/core/requests" - import {hasBlossomSupport} from "@app/core/commands" import {notifications} from "@app/util/notifications" type Props = { @@ -33,8 +30,6 @@ const url = decodeRelay($page.params.relay!) - const rooms = Array.from($userRoomsByUrl.get(url) || []) - const socket = deriveSocket(url) const authError = deriveRelayAuthError(url) @@ -56,8 +51,6 @@ }) onMount(() => { - const since = ago(MONTH) - sleep(2000).then(() => { if ($socket.status !== SocketStatus.Open) { pushToast({ @@ -66,21 +59,6 @@ }) } }) - - // Prime our cache so we can upload images quicker - hasBlossomSupport(url) - - // Load group meta, threads, calendar events, comments, and recent messages - // for user rooms to help with a quick page transition - pullConservatively({ - relays: [url], - filters: [ - {kinds: [ROOM_META]}, - {kinds: [THREAD, EVENT_TIME, MESSAGE], since}, - {kinds: [COMMENT], "#K": [String(THREAD), String(EVENT_TIME)], since}, - ...rooms.map(room => ({kinds: [MESSAGE], "#h": [room], since})), - ], - }) }) diff --git a/src/routes/spaces/[relay]/[room]/+page.svelte b/src/routes/spaces/[relay]/[room]/+page.svelte index 7b5fd658..16094fbf 100644 --- a/src/routes/spaces/[relay]/[room]/+page.svelte +++ b/src/routes/spaces/[relay]/[room]/+page.svelte @@ -6,19 +6,8 @@ import type {Readable} from "svelte/store" import type {MakeNonOptional} from "@welshman/lib" import {now, formatTimestampAsDate, ago, MINUTE} from "@welshman/lib" - import {request} from "@welshman/net" import type {TrustedEvent, EventContent} from "@welshman/util" - import { - makeEvent, - makeRoomMeta, - MESSAGE, - DELETE, - THREAD, - EVENT_TIME, - ZAP_GOAL, - ROOM_ADD_USER, - ROOM_REMOVE_USER, - } from "@welshman/util" + import {makeEvent, makeRoomMeta, MESSAGE} from "@welshman/util" import {pubkey, publishThunk, waitForThunkError, joinRoom, leaveRoom} from "@welshman/app" import {slide, fade, fly} from "@lib/transition" import Hashtag from "@assets/icons/hashtag.svg?dataurl" @@ -43,11 +32,11 @@ userRoomsByUrl, userSettingsValues, decodeRelay, - getEventsForUrl, deriveUserMembershipStatus, deriveChannel, MembershipStatus, - REACTION_KINDS, + PROTECTED, + MESSAGE_KINDS, } from "@app/core/state" import {setChecked, checked} from "@app/util/notifications" import { @@ -57,7 +46,6 @@ prependParent, publishDelete, } from "@app/core/commands" - import {PROTECTED} from "@app/core/state" import {makeFeed} from "@app/core/requests" import {popKey} from "@lib/implicit" import {pushToast} from "@app/util/toast" @@ -68,7 +56,6 @@ const lastChecked = $checked[$page.url.pathname] const url = decodeRelay(relay) const channel = deriveChannel(url, room) - const filter = {kinds: [MESSAGE, THREAD, EVENT_TIME, ZAP_GOAL], "#h": [room]} const isFavorite = $derived($userRoomsByUrl.get(url)?.has(room)) const shouldProtect = canEnforceNip70(url) const membershipStatus = deriveUserMembershipStatus(url, room) @@ -267,13 +254,9 @@ cleanup?.() const feed = makeFeed({ + url, element: element!, - relays: [url], - feedFilters: [filter], - subscriptionFilters: [ - {kinds: [DELETE, MESSAGE, ...REACTION_KINDS], "#h": [room], since: now()}, - ], - initialEvents: getEventsForUrl(url, [{...filter, limit: 20}]), + filters: [{kinds: MESSAGE_KINDS, "#h": [room]}], onExhausted: () => { loadingEvents = false }, @@ -301,21 +284,6 @@ } onMount(() => { - const controller = new AbortController() - - request({ - signal: controller.signal, - relays: [url], - filters: [ - { - kinds: [ROOM_ADD_USER, ROOM_REMOVE_USER], - "#p": [$pubkey!], - "#h": [room], - limit: 10, - }, - ], - }) - const observer = new ResizeObserver(() => { if (dynamicPadding && chatCompose) { dynamicPadding!.style.minHeight = `${chatCompose!.offsetHeight}px` @@ -327,7 +295,6 @@ start() return () => { - controller.abort() observer.unobserve(chatCompose!) observer.unobserve(dynamicPadding!) } diff --git a/src/routes/spaces/[relay]/calendar/+page.svelte b/src/routes/spaces/[relay]/calendar/+page.svelte index 540acfb5..3dae6818 100644 --- a/src/routes/spaces/[relay]/calendar/+page.svelte +++ b/src/routes/spaces/[relay]/calendar/+page.svelte @@ -5,7 +5,7 @@ import {page} from "$app/stores" import {now, last, formatTimestampAsDate} from "@welshman/lib" import type {TrustedEvent} from "@welshman/util" - import {DELETE, EVENT_TIME, getTagValue} from "@welshman/util" + import {EVENT_TIME, getTagValue} from "@welshman/util" import {fly} from "@lib/transition" import CalendarMinimalistic from "@assets/icons/calendar-minimalistic.svg?dataurl" import CalendarAdd from "@assets/icons/calendar-add.svg?dataurl" @@ -19,7 +19,7 @@ import CalendarEventItem from "@app/components/CalendarEventItem.svelte" import CalendarEventCreate from "@app/components/CalendarEventCreate.svelte" import {pushModal} from "@app/util/modal" - import {getEventsForUrl, decodeRelay, REACTION_KINDS} from "@app/core/state" + import {decodeRelay, makeCommentFilter} from "@app/core/state" import {makeCalendarFeed} from "@app/core/requests" import {setChecked} from "@app/util/notifications" @@ -31,7 +31,6 @@ let element: HTMLElement | undefined = $state() let loading = $state(true) - let cleanup: () => void let events: Readable = $state(readable([])) type Item = { @@ -96,23 +95,20 @@ }) onMount(() => { - const feedFilters = [{kinds: [EVENT_TIME]}] - const subscriptionFilters = [{kinds: [DELETE, EVENT_TIME, ...REACTION_KINDS], since: now()}] - - ;({events, cleanup} = makeCalendarFeed({ + const feed = makeCalendarFeed({ + url, element: element!, - relays: [url], - feedFilters, - subscriptionFilters, - initialEvents: getEventsForUrl(url, feedFilters), + filters: [{kinds: [EVENT_TIME]}, makeCommentFilter([EVENT_TIME])], onExhausted: () => { loading = false }, - })) + }) + + events = feed.events return () => { + feed.cleanup() setChecked($page.url.pathname) - cleanup?.() } }) diff --git a/src/routes/spaces/[relay]/chat/+page.svelte b/src/routes/spaces/[relay]/chat/+page.svelte index 7c5d8419..19a0d108 100644 --- a/src/routes/spaces/[relay]/chat/+page.svelte +++ b/src/routes/spaces/[relay]/chat/+page.svelte @@ -1,11 +1,11 @@ diff --git a/src/routes/spaces/[relay]/goals/+page.svelte b/src/routes/spaces/[relay]/goals/+page.svelte index 0e9a69c7..3abb72ed 100644 --- a/src/routes/spaces/[relay]/goals/+page.svelte +++ b/src/routes/spaces/[relay]/goals/+page.svelte @@ -1,10 +1,11 @@