diff --git a/src/app/components/Chat.svelte b/src/app/components/Chat.svelte index 45755372..dfc45dfc 100644 --- a/src/app/components/Chat.svelte +++ b/src/app/components/Chat.svelte @@ -113,7 +113,9 @@ }) const observer = new ResizeObserver(() => { - dynamicPadding!.style.minHeight = `${chatCompose!.offsetHeight}px` + if (dynamicPadding && chatCompose) { + dynamicPadding.style.minHeight = `${chatCompose.offsetHeight}px` + } }) observer.observe(chatCompose!) diff --git a/src/app/components/ReactionSummary.svelte b/src/app/components/ReactionSummary.svelte index 967e2191..e0d7b335 100644 --- a/src/app/components/ReactionSummary.svelte +++ b/src/app/components/ReactionSummary.svelte @@ -5,8 +5,7 @@ import {REACTION, getTag, REPORT, DELETE} from "@welshman/util" import type {TrustedEvent} from "@welshman/util" import {deriveEvents} from "@welshman/store" - import type {MultiRequest} from "@welshman/net" - import {load, request, RequestEvent} from "@welshman/net" + import {load} from "@welshman/net" import {pubkey, repository, displayProfileByPubkey} from "@welshman/app" import {displayList} from "@lib/util" import {isMobile, preventDefault, stopPropagation} from "@lib/html" @@ -53,27 +52,24 @@ ) onMount(() => { - let req: MultiRequest + const controller = new AbortController() if (url) { - req = request({ + load({ relays: [url], + signal: controller.signal, filters: [{kinds: [REACTION, REPORT, DELETE], "#e": [event.id]}], - }) - - req.on( - RequestEvent.Event, - batch(300, (events: TrustedEvent[]) => { + onEvent: batch(300, (events: TrustedEvent[]) => { load({ relays: [url], filters: [{kinds: [DELETE], "#e": events.map(e => e.id)}], }) }), - ) + }) } return () => { - req?.close() + controller.abort() } }) diff --git a/src/app/requests.ts b/src/app/requests.ts index 6dfbfa25..1892de1b 100644 --- a/src/app/requests.ts +++ b/src/app/requests.ts @@ -28,8 +28,7 @@ import { } from "@welshman/util" import type {TrustedEvent, Filter, List} from "@welshman/util" import {feedFromFilters, makeRelayFeed, makeIntersectionFeed} from "@welshman/feeds" -import {load, request, RequestEvent} from "@welshman/net" -import type {MultiRequest} from "@welshman/net" +import {load, request} from "@welshman/net" import type {AppSyncOpts, Thunk} from "@welshman/app" import { repository, @@ -101,6 +100,7 @@ export const makeFeed = ({ const seen = new Set() const buffer = writable([]) const events = writable(initialEvents) + const controller = new AbortController() for (const event of initialEvents) { if (!seen.has(event.id)) { @@ -151,11 +151,14 @@ export const makeFeed = ({ onExhausted, }) - const req = request({relays, filters: subscriptionFilters}) - - req.on(RequestEvent.Event, (e: TrustedEvent) => { - if (matchFilters(feedFilters, e)) insertEvent(e) - if (e.kind === DELETE) handleDelete(e) + request({ + relays, + signal: controller.signal, + filters: subscriptionFilters, + onEvent: (e: TrustedEvent) => { + if (matchFilters(feedFilters, e)) insertEvent(e) + if (e.kind === DELETE) handleDelete(e) + }, }) const scroller = createScroller({ @@ -178,9 +181,9 @@ export const makeFeed = ({ return { events, cleanup: () => { - req.close() unsubscribe() scroller.stop() + controller.abort() }, } } @@ -201,6 +204,7 @@ export const makeCalendarFeed = ({ initialEvents?: TrustedEvent[] }) => { const interval = int(5, DAY) + const controller = new AbortController() let exhaustedScrollers = 0 let backwardWindow = [now() - interval, now()] @@ -242,22 +246,25 @@ export const makeCalendarFeed = ({ } } - const req = request({relays, filters: subscriptionFilters}) - - req.on(RequestEvent.Event, (e: TrustedEvent) => { - if (matchFilters(feedFilters, e)) insertEvent(e) + request({ + relays, + signal: controller.signal, + filters: subscriptionFilters, + onEvent: (e: TrustedEvent) => { + if (matchFilters(feedFilters, e)) insertEvent(e) + }, }) const loadTimeframe = (since: number, until: number) => { const hashes = daysBetween(since, until).map(String) - const req = request({ + request({ relays, + signal: controller.signal, autoClose: true, filters: [{kinds: [EVENT_TIME], "#D": hashes}], + onEvent: insertEvent, }) - - req.on(RequestEvent.Event, insertEvent) } const maybeExhausted = () => { @@ -306,8 +313,8 @@ export const makeCalendarFeed = ({ cleanup: () => { backwardScroller.stop() forwardScroller.stop() + controller.abort() unsubscribe() - req.close() }, } } @@ -329,7 +336,7 @@ export const loadAlertStatuses = (pubkey: string) => // Application requests export const listenForNotifications = () => { - const reqs: MultiRequest[] = [] + const controller = new AbortController() for (const [url, allRooms] of userRoomsByUrl.get()) { // Limit how many rooms we load at a time, since we have to send a separate filter @@ -337,6 +344,7 @@ export const listenForNotifications = () => { const rooms = shuffle(Array.from(allRooms)).slice(0, 30) load({ + signal: controller.signal, relays: [url], filters: [ {kinds: [THREAD], limit: 1}, @@ -347,23 +355,18 @@ export const listenForNotifications = () => { ], }) - reqs.push( - request({ - relays: [url], - filters: [ - {kinds: [THREAD, EVENT_TIME], since: now()}, - {kinds: [COMMENT], "#K": [String(THREAD), String(EVENT_TIME)], since: now()}, - ...rooms.map(room => ({kinds: [MESSAGE], "#h": [room], since: now()})), - ], - }), - ) + request({ + signal: controller.signal, + relays: [url], + filters: [ + {kinds: [THREAD, EVENT_TIME], since: now()}, + {kinds: [COMMENT], "#K": [String(THREAD), String(EVENT_TIME)], since: now()}, + ...rooms.map(room => ({kinds: [MESSAGE], "#h": [room], since: now()})), + ], + }) } - return () => { - for (const req of reqs) { - req.close() - } - } + return () => controller.abort() } export const loadUserData = (pubkey: string, relays: string[] = []) => { diff --git a/src/app/state.ts b/src/app/state.ts index 73d31ac4..3349a73b 100644 --- a/src/app/state.ts +++ b/src/app/state.ts @@ -332,7 +332,7 @@ export const { name: "settings", store: settings, getKey: settings => settings.event.pubkey, - load: makeOutboxLoader([SETTINGS]), + load: makeOutboxLoader(SETTINGS), }) // Alerts @@ -409,7 +409,7 @@ export const { name: "memberships", store: memberships, getKey: list => list.event.pubkey, - load: makeOutboxLoader([GROUPS]), + load: makeOutboxLoader(GROUPS), }) // Chats diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 4e1fecce..1564c72c 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -160,14 +160,16 @@ ) // Listen for chats, populate chat-based notifications - let chatsReq: any + let controller: AbortController derived([pubkey, canDecrypt, userInboxRelaySelections], identity).subscribe( ([$pubkey, $canDecrypt, $userInboxRelaySelections]) => { - chatsReq?.close() + controller?.abort() + controller = new AbortController() if ($pubkey && $canDecrypt) { - chatsReq = request({ + request({ + signal: controller.signal, filters: [ {kinds: [WRAP], "#p": [$pubkey], since: ago(WEEK, 2)}, {kinds: [WRAP], "#p": [$pubkey], limit: 100}, diff --git a/src/routes/[bech32]/+page.svelte b/src/routes/[bech32]/+page.svelte index 414c09bd..5798517f 100644 --- a/src/routes/[bech32]/+page.svelte +++ b/src/routes/[bech32]/+page.svelte @@ -3,7 +3,7 @@ import * as nip19 from "nostr-tools/nip19" import type {TrustedEvent} from "@welshman/util" import {Address, getIdFilters, getTagValue} from "@welshman/util" - import {request, RequestEvent} from "@welshman/net" + import {request} from "@welshman/net" import {page} from "$app/stores" import {goto} from "$app/navigation" import {scrollToEvent} from "@lib/html" @@ -21,29 +21,27 @@ let found = false - const req = request({ + request({ autoClose: true, filters: getIdFilters([type === "nevent" ? data.id : Address.fromNaddr(bech32).toString()]), relays: data.relays, - }) + onEvent: (event: TrustedEvent) => { + found = true - req.on(RequestEvent.Event, (event: TrustedEvent) => { - found = true - - if (event.kind === 9) { - goto(makeRoomPath(data.relays[0], getTagValue("h", event.tags)!), {replaceState: true}) - scrollToEvent(event.id) - } else if (event.kind === 11) { - goto(makeThreadPath(data.relays[0], event.id), {replaceState: true}) - } else { - goto("/", {replaceState: true}) - } - }) - - req.on(RequestEvent.Close, () => { - if (!found) { - goto("/", {replaceState: true}) - } + if (event.kind === 9) { + goto(makeRoomPath(data.relays[0], getTagValue("h", event.tags)!), {replaceState: true}) + scrollToEvent(event.id) + } else if (event.kind === 11) { + goto(makeThreadPath(data.relays[0], event.id), {replaceState: true}) + } else { + goto("/", {replaceState: true}) + } + }, + onClose: () => { + if (!found) { + goto("/", {replaceState: true}) + } + }, }) } diff --git a/src/routes/spaces/[relay]/+layout.svelte b/src/routes/spaces/[relay]/+layout.svelte index 2d382664..d60ab815 100644 --- a/src/routes/spaces/[relay]/+layout.svelte +++ b/src/routes/spaces/[relay]/+layout.svelte @@ -65,10 +65,12 @@ }) // Completely refresh our groups list and listen for new ones - const req = request({relays, filters: [{kinds: [GROUPS]}]}) + const controller = new AbortController() + + request({relays, filters: [{kinds: [GROUPS]}], signal: controller.signal}) return () => { - req.close() + controller.abort() } }) diff --git a/src/routes/spaces/[relay]/calendar/[id]/+page.svelte b/src/routes/spaces/[relay]/calendar/[id]/+page.svelte index b1b9b1b4..223e4f09 100644 --- a/src/routes/spaces/[relay]/calendar/[id]/+page.svelte +++ b/src/routes/spaces/[relay]/calendar/[id]/+page.svelte @@ -46,10 +46,12 @@ let showReply = $state(false) onMount(() => { - const req = request({relays: [url], filters}) + const controller = new AbortController() + + request({relays: [url], filters, signal: controller.signal}) return () => { - req.close() + controller.abort() setChecked($page.url.pathname) } }) diff --git a/src/routes/spaces/[relay]/threads/[id]/+page.svelte b/src/routes/spaces/[relay]/threads/[id]/+page.svelte index 2e086e92..46d646bf 100644 --- a/src/routes/spaces/[relay]/threads/[id]/+page.svelte +++ b/src/routes/spaces/[relay]/threads/[id]/+page.svelte @@ -43,10 +43,12 @@ let showReply = $state(false) onMount(() => { - const req = request({relays: [url], filters}) + const controller = new AbortController() + + request({relays: [url], filters, signal: controller.signal}) return () => { - req.close() + controller.abort() setChecked($page.url.pathname) } })