Query events through welshman's Events plugin and delete the repository.ts wrappers around it
This commit is contained in:
parent
f10dc96c43
commit
964a1bb6fa
36 changed files with 123 additions and 193 deletions
|
|
@ -324,7 +324,7 @@ card, and `NoteContentClassified` renders a listing wherever `NoteContent` is us
|
|||
|
||||
**Routes.** `src/routes/spaces/[relay]/classifieds/+page.svelte` loads listings and their comments
|
||||
with `makeFeed` and filters them with the `classifieds.ts` helpers. `[address]/+page.svelte` reads
|
||||
one listing with `deriveEvent(address, [url])`.
|
||||
one listing with `$events.one(address, [url]).$`.
|
||||
|
||||
Articles are composed on a full page (`spaces/[relay]/articles/create`, built by
|
||||
`makeArticleCreatePath`) instead of in a modal.
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ members and pins, the space member list, and roles. Anyone can publish events of
|
|||
readers must check the author. The welshman collections do: `Rooms` and every
|
||||
`RelaySignedDerivedPlugin` (`RelayMemberLists`, `RelayRoles`, `RoomPinLists`) drop events whose
|
||||
author isn't the relay's `self`, and re-check when NIP-11 loads. For a relay-authored kind with no
|
||||
plugin, filter `deriveEventsForUrl(url, filters)` on that `self` key yourself rather than reading a
|
||||
bare `deriveEventsForUrl`.
|
||||
plugin, read `$events.relaySignedForUrl(url, filters)`, which keeps only events signed by that
|
||||
`self` key, rather than a bare `$events.forUrl`.
|
||||
|
||||
The app signs everything it publishes with the user's own key. Space-wide content with no author of
|
||||
its own belongs to the space's owner, the pubkey NIP-11 names: featured content
|
||||
|
|
@ -235,7 +235,7 @@ space it lists or used to list, so each relay hears about joins and leaves. Kind
|
|||
so `RoomChat` and `publishRoomQuote` publish raw templates through `Thunks`.
|
||||
|
||||
Reads are scoped the same way. Request from the space relay (`relays: [url]`, plus `"#h": [h]` for
|
||||
a room) and read results with `deriveEventsForUrl(url, filters)`, which uses the tracker to keep
|
||||
a room) and read results with `$events.forUrl(url, filters)`, which uses the tracker to keep
|
||||
only events seen on that relay. A repository-wide query would mix rooms that share an `h` across
|
||||
relays. `src/app/sync.ts` pulls each space's room state, membership and recent content in the
|
||||
background; see flotilla-state.
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ The app is therefore stable for as long as anything under the login gate is moun
|
|||
| `session` | the persisted `Session` | `undefined` |
|
||||
| `user` | `User.require($app)`, derived | subscribing or `.get()` throws |
|
||||
| `usePlugin(Plugin)` | a store holding `$app.use(Plugin)` for the current app | safe |
|
||||
| `profiles`, `rooms`, `relays`, `thunks`, … | `usePlugin` for 27 welshman plugins | safe |
|
||||
| `profiles`, `rooms`, `relays`, `events`, `thunks`, … | `usePlugin` for 28 welshman plugins | safe |
|
||||
| `fromApp(read)` | a store that re-reads `read($app)` when the app changes | safe |
|
||||
| `deriveUserItem(Plugin)` | the signed-in user's entry in a keyed plugin | `undefined` |
|
||||
| `userSearchRelayUrls` | the user's search relays, or `DEFAULT_SEARCH_RELAYS` | the defaults |
|
||||
|
|
@ -175,16 +175,19 @@ Events enter `app.repository` from `ingestPolicy` (which calls `tracker.track`,
|
|||
optimistically. The tracker records which relays each event was seen on, which is what lets
|
||||
space content be keyed by relay.
|
||||
|
||||
`src/app/repository.ts` wraps the `@welshman/store` derivations in `fromApp`:
|
||||
Raw event queries go through welshman's `Events` plugin, exported from `core.ts` as `events`.
|
||||
Every method returns a projection over the current app's repository:
|
||||
|
||||
- `deriveEvent`, `deriveEvents`, `deriveEventsById`, `deriveIsDeleted`
|
||||
- relay-scoped: `deriveEventsForUrl`, `deriveEventsByIdForUrl`, `deriveEventsByIdByUrl`,
|
||||
`getEventsForUrl`
|
||||
- `deriveLatestEvent`
|
||||
- `one(idOrAddress, relays)` (loads when nothing local matches, keeps deleted events), `byId`,
|
||||
`all`, `asc`, `desc`, `isDeleted`
|
||||
- relay-scoped through the tracker: `forUrl`, `byIdForUrl`, `byIdByUrl`, and
|
||||
`relaySignedForUrl`, which keeps only events signed by the relay's NIP-11 `self`
|
||||
|
||||
Use these for raw event queries. Welshman's `Events` plugin has the same surface returning
|
||||
projections, and flotilla does not use it. Plugin reads (`get`, `one`, `load`, `index`) are
|
||||
documented in welshman-app.
|
||||
Components bind `$events.forUrl(url, filters).$`. A `derive*` function called from gated code
|
||||
binds `events.get().forUrl(...).$` at call time, and a module-scope store wraps it in
|
||||
`fromApp($app => $app.use(Events).byIdByUrl(filters).$)`, as `latestActivityByPath` does.
|
||||
`src/app/repository.ts` holds only `deriveLatestEvent`. Plugin reads (`get`, `one`, `load`,
|
||||
`index`) are documented in welshman-app.
|
||||
|
||||
### Free functions in an app module
|
||||
|
||||
|
|
@ -196,7 +199,7 @@ projections and repository derivations:
|
|||
export const deriveSpaceActionItems = (url: string) =>
|
||||
derived(
|
||||
[
|
||||
deriveEventsForUrl(url, [{kinds: [REPORT]}]),
|
||||
events.get().forUrl(url, [{kinds: [REPORT]}]).$,
|
||||
rooms.get().pendingJoins(url).$,
|
||||
deriveSpacePermissions(url),
|
||||
],
|
||||
|
|
@ -424,7 +427,7 @@ store, consumed in components with `$store`.
|
|||
Take the first answer that fits:
|
||||
|
||||
1. **It is an event, or derived from events.** It is already in the repository, or should be.
|
||||
Read it with a plugin or an `@app/repository` derivation, and put the domain logic in a
|
||||
Read it with a plugin or the `events` projections, and put the domain logic in a
|
||||
`derive*` function in the owning app module (`deriveUserRooms`). Don't copy it into a
|
||||
writable.
|
||||
2. **It is a keyed collection of one kind, loaded by key.** Write a plugin. A generic kind goes
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ stores, so a component takes the key and looks up the rest: `RoomName` takes `{u
|
|||
`$rooms.forRoom(url, h)`, `ProfileName` takes `pubkey` and reads `$profiles.display`.
|
||||
|
||||
Events are the exception, and 66 components take `event: TrustedEvent`, since the parent already
|
||||
holds the event from a feed or a `deriveEvent`. An event prop usually travels with `url`, the
|
||||
holds the event from a feed or `$events.one`. An event prop usually travels with `url`, the
|
||||
relay it lives on, which routes its replies and reactions, and with `context: FeedContext`, the
|
||||
shared loader below. A component takes a pointer instead only when it has to load the event
|
||||
itself, as `ContentQuote` does. Anything with neither a store nor an event is passed as its
|
||||
|
|
@ -281,7 +281,7 @@ param change and lists key by id. A prop that does change while mounted needs `$
|
|||
## Reading state in a component
|
||||
|
||||
Components read plugins through the `usePlugin` stores exported from `src/app/core.ts`
|
||||
(`$profiles`, `$relays`, `$rooms`, `$roomLists`, `$network`, `$thunks`, `$deletes`,
|
||||
(`$profiles`, `$relays`, `$rooms`, `$roomLists`, `$events`, `$network`, `$thunks`, `$deletes`,
|
||||
`$relayManagement`, …). `$app.use(X)` covers plugins with no export, such as `Zappers`,
|
||||
`Pinboards` and `Feeds`; flotilla-state has the rules about which to use where.
|
||||
|
||||
|
|
@ -291,6 +291,7 @@ How you bind depends on what the method returns:
|
|||
<script lang="ts">
|
||||
const room = $rooms.forRoom(url, h) // Readable: one, forRoom
|
||||
const display = $profiles.display(pubkey, removeUndefined([url])).$ // Projection: take .$
|
||||
const replies = $events.asc(filters).$ // raw repository queries
|
||||
const shouldProtect = $relays.hasNip(url, 70) // Promise: load, hasNip
|
||||
</script>
|
||||
|
||||
|
|
@ -298,7 +299,7 @@ How you bind depends on what the method returns:
|
|||
```
|
||||
|
||||
In a handler, call `.get()` on a projection instead of subscribing. The app modules add `derive*`
|
||||
factories over the same data: `deriveEvent` and `deriveEventsById` in `src/app/repository.ts`,
|
||||
factories over the same data: `deriveSpaceActionItems` in `src/app/actionItems.ts`,
|
||||
`deriveSpaceSupportedMethods` in `src/app/management.ts`, `deriveRelayAuthError` in
|
||||
`src/app/access.ts`. Call them at the top of the script with fixed arguments, and wrap one in
|
||||
`$derived` only when its arguments change, as the thread page does for filters that wait on the
|
||||
|
|
@ -316,7 +317,7 @@ data every page needs lives in `src/app/sync.ts`.
|
|||
`people/[npub]/+page.svelte` does for the profile, relay list, follow, pin, room and messaging
|
||||
lists before loading the author's outbox with `$network.loadLenient`.
|
||||
|
||||
**A detail page:** `deriveEvent(address, [url])` loads when nothing local matches. While it is
|
||||
**A detail page:** `$events.one(address, [url]).$` loads when nothing local matches. While it is
|
||||
empty, seven pages show a spinner that turns into a failure message:
|
||||
|
||||
```svelte
|
||||
|
|
@ -328,7 +329,7 @@ empty, seven pages show a spinner that turns into a failure message:
|
|||
```
|
||||
|
||||
**Related events:** request them, abort on teardown, and read them back from the repository with
|
||||
`deriveEventsAsc(deriveEventsById(filters))`.
|
||||
`$events.asc(filters).$`.
|
||||
|
||||
```typescript
|
||||
onMount(() => {
|
||||
|
|
@ -460,8 +461,8 @@ Rich text uses `makeEditor` from `src/app/editor` with `EditorContent`.
|
|||
- `flotilla-architecture`: layer rules and exceptions, the `src/app` modules, boot, placement
|
||||
- `flotilla-state`: plugin stores, `derive*` stores, drafts, settings, thunks and commands
|
||||
- `flotilla-model`: spaces, rooms, NIP-43/29/86, content kinds, and where events are published
|
||||
- `welshman-app`: plugins, projections, `Command`, thunks, `Feeds`
|
||||
- `welshman-store`: `deriveEventsById`, `deriveEventsAsc`, the other repository stores
|
||||
- `welshman-app`: plugins, projections, `Command`, thunks, `Events`, `Feeds`
|
||||
- `welshman-store`: `deriveEventsById`, `deriveEventsAsc`, the repository stores under `Events`
|
||||
- `welshman-domain`: the readers and writers behind `reader` and `writer`
|
||||
- `welshman-feeds`: `FeedController`, still used by `ProfileFeed`
|
||||
- `welshman-editor`: the composer behind `makeEditor`
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import {derived} from "svelte/store"
|
||||
import {REPORT, sortEventsDesc} from "@welshman/util"
|
||||
import {rooms} from "@app/core"
|
||||
import {events, rooms} from "@app/core"
|
||||
import {deriveSpacePermissions} from "@app/management"
|
||||
import {deriveEventsForUrl} from "@app/repository"
|
||||
|
||||
// Action items (admin review queue)
|
||||
|
||||
|
|
@ -10,7 +9,7 @@ import {deriveEventsForUrl} from "@app/repository"
|
|||
export const deriveSpaceActionItems = (url: string) =>
|
||||
derived(
|
||||
[
|
||||
deriveEventsForUrl(url, [{kinds: [REPORT]}]),
|
||||
events.get().forUrl(url, [{kinds: [REPORT]}]).$,
|
||||
rooms.get().pendingJoins(url).$,
|
||||
deriveSpacePermissions(url),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@ import type {TrustedEvent} from "@welshman/util"
|
|||
import {CalendarRsvp, TimeEvent} from "@welshman/domain"
|
||||
import type {RsvpStatus} from "@welshman/domain"
|
||||
import {synced} from "@welshman/store"
|
||||
import {deletes, reader, relays, thunks, writer} from "@app/core"
|
||||
import {deriveEvents} from "@app/repository"
|
||||
import {deletes, events, reader, relays, thunks, writer} from "@app/core"
|
||||
import {toSpace} from "@app/rooms"
|
||||
import {kv} from "@app/storage"
|
||||
|
||||
|
|
@ -237,7 +236,7 @@ export const makeRsvpFilter = (event: TrustedEvent) => ({
|
|||
"#a": [getAddress(event)],
|
||||
})
|
||||
|
||||
export const deriveRsvps = (event: TrustedEvent) => deriveEvents([makeRsvpFilter(event)])
|
||||
export const deriveRsvps = (event: TrustedEvent) => events.get().desc([makeRsvpFilter(event)]).$
|
||||
|
||||
export const isAttending = (status?: RsvpStatus) => status === "accepted" || status === "tentative"
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import {deriveDeduplicated} from "@welshman/store"
|
|||
import {makeRoomKey} from "@welshman/app"
|
||||
import type {Room} from "@welshman/app"
|
||||
import type {Room as LiveKitRoom} from "livekit-client"
|
||||
import {network} from "@app/core"
|
||||
import {deriveEventsForUrl} from "@app/repository"
|
||||
import {events, network} from "@app/core"
|
||||
|
||||
export const LIVEKIT_PARTICIPANTS = 39004
|
||||
|
||||
|
|
@ -304,7 +303,7 @@ export const deriveCallParticipants = (url: string, h: string) =>
|
|||
participantMediaState,
|
||||
callTargetRoom,
|
||||
deriveDeduplicated(
|
||||
deriveEventsForUrl(url, [{kinds: [LIVEKIT_PARTICIPANTS], "#d": [h]}]),
|
||||
events.get().forUrl(url, [{kinds: [LIVEKIT_PARTICIPANTS], "#d": [h]}]).$,
|
||||
events => first(sortEventsDesc(events)),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@
|
|||
import EventActivity from "@app/components/EventActivity.svelte"
|
||||
import EventActions from "@app/components/EventActions.svelte"
|
||||
import EventActionBar from "@app/components/EventActionBar.svelte"
|
||||
import {reader} from "@app/core"
|
||||
import {deriveIsDeleted} from "@app/repository"
|
||||
import {events, reader} from "@app/core"
|
||||
import {makeSpacePath} from "@app/routes"
|
||||
|
||||
type Props = {
|
||||
|
|
@ -30,7 +29,7 @@
|
|||
const article = $derived(reader(Article)(event))
|
||||
const h = $derived(article.room())
|
||||
const topics = $derived(article.topics())
|
||||
const deleted = $derived(deriveIsDeleted(event))
|
||||
const deleted = $derived($events.isDeleted(event).$)
|
||||
|
||||
const deleteReaction = (reaction: TrustedEvent) => retractReaction(reaction, {url, h})
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@
|
|||
import Profile from "@app/components/Profile.svelte"
|
||||
import ProfileName from "@app/components/ProfileName.svelte"
|
||||
import ProfileAbout from "@app/components/ProfileAbout.svelte"
|
||||
import {network, reader} from "@app/core"
|
||||
import {deriveEventsForUrl} from "@app/repository"
|
||||
import {events, network, reader} from "@app/core"
|
||||
import {displayReadingTime} from "@app/articles"
|
||||
import {makeArticlePath} from "@app/routes"
|
||||
|
||||
|
|
@ -24,15 +23,15 @@
|
|||
const MAX_ARTICLES = 6
|
||||
|
||||
const filters = [{kinds: [LONG_FORM], authors: [event.pubkey], limit: 20}]
|
||||
const events = deriveEventsForUrl(url, filters)
|
||||
const articles = $events.forUrl(url, filters).$
|
||||
const address = getAddress(event)
|
||||
|
||||
const articleCount = $derived($events.length)
|
||||
const articleCount = $derived($articles.length)
|
||||
|
||||
const others = $derived(
|
||||
sortBy(
|
||||
e => -reader(Article)(e).publishedAt(),
|
||||
$events.filter(e => getAddress(e) !== address),
|
||||
$articles.filter(e => getAddress(e) !== address),
|
||||
).slice(0, MAX_ARTICLES),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@
|
|||
import NoteCard from "@app/components/NoteCard.svelte"
|
||||
import NoteContent from "@app/components/NoteContent.svelte"
|
||||
import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte"
|
||||
import {network, router} from "@app/core"
|
||||
import {deriveEvent} from "@app/repository"
|
||||
import {events, network, router} from "@app/core"
|
||||
import {entityLink} from "@app/env"
|
||||
import {goToEvent} from "@app/routes"
|
||||
|
||||
|
|
@ -39,7 +38,7 @@
|
|||
|
||||
const mergedRelays = writable(hints)
|
||||
|
||||
const quote = deriveEvent(idOrAddress, hints)
|
||||
const quote = $events.one(idOrAddress, hints).$
|
||||
|
||||
// Whoever quoted the event must have seen it, so the quoting event's relays are asked too.
|
||||
$router.resolver
|
||||
|
|
|
|||
|
|
@ -3,15 +3,13 @@
|
|||
import {removeUndefined} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {getCommentFiltersForRoot} from "@welshman/util"
|
||||
import {deriveEventsAsc} from "@welshman/store"
|
||||
import Reply from "@assets/icons/reply-2.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import CommentTree from "@app/components/CommentTree.svelte"
|
||||
import type {FeedContext} from "@app/feeds"
|
||||
import CommentCompose from "@app/components/CommentCompose.svelte"
|
||||
import {network} from "@app/core"
|
||||
import {deriveEventsById} from "@app/repository"
|
||||
import {events, network} from "@app/core"
|
||||
import {buildCommentTree} from "@app/social"
|
||||
|
||||
type Props = {
|
||||
|
|
@ -24,7 +22,7 @@
|
|||
|
||||
const relays = removeUndefined([url])
|
||||
const filters = getCommentFiltersForRoot([event])
|
||||
const comments = deriveEventsAsc(deriveEventsById(filters))
|
||||
const comments = $events.asc(filters).$
|
||||
|
||||
const nodes = $derived(buildCommentTree(event, $comments))
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,11 @@
|
|||
import {POLL_RESPONSE} from "@welshman/util"
|
||||
import {Poll} from "@welshman/domain"
|
||||
import ContentMinimal from "@app/components/ContentMinimal.svelte"
|
||||
import {reader} from "@app/core"
|
||||
import {deriveEvents} from "@app/repository"
|
||||
import {events, reader} from "@app/core"
|
||||
|
||||
const props: ComponentProps<typeof ContentMinimal> = $props()
|
||||
|
||||
const responses = deriveEvents([{kinds: [POLL_RESPONSE], "#e": [props.event.id]}])
|
||||
const responses = $events.desc([{kinds: [POLL_RESPONSE], "#e": [props.event.id]}]).$
|
||||
|
||||
const voters = $derived(reader(Poll)(props.event).results($responses).voters)
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
import {onDestroy} from "svelte"
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
import NoteItem from "@app/components/NoteItem.svelte"
|
||||
import {events} from "@app/core"
|
||||
import {makeFeedContext} from "@app/feeds"
|
||||
import {deriveEvent} from "@app/repository"
|
||||
|
||||
type Props = {
|
||||
url?: string
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
const {url, value, relays}: Props = $props()
|
||||
|
||||
const event = deriveEvent(value, relays)
|
||||
const event = $events.one(value, relays).$
|
||||
const context = makeFeedContext({relays})
|
||||
|
||||
onDestroy(context.cleanup)
|
||||
|
|
|
|||
|
|
@ -15,9 +15,8 @@
|
|||
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
|
||||
import RelayName from "@app/components/RelayName.svelte"
|
||||
import PinAdd from "@app/components/PinAdd.svelte"
|
||||
import {reader} from "@app/core"
|
||||
import {events, reader} from "@app/core"
|
||||
import {eventToReference} from "@app/pinboards"
|
||||
import {deriveEventsForUrl} from "@app/repository"
|
||||
import {makeSpacePath} from "@app/routes"
|
||||
import {pushModal} from "@app/modal"
|
||||
|
||||
|
|
@ -28,8 +27,8 @@
|
|||
|
||||
const {url, event}: Props = $props()
|
||||
|
||||
const boards = derived(deriveEventsForUrl(url, [{kinds: [PINBOARD]}]), $events =>
|
||||
$events.map(reader(Pinboard)),
|
||||
const boards = derived($events.forUrl(url, [{kinds: [PINBOARD]}]).$, $pinboards =>
|
||||
$pinboards.map(reader(Pinboard)),
|
||||
)
|
||||
|
||||
const reference = eventToReference(event)
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@
|
|||
import {Poll, PollResponse} from "@welshman/domain"
|
||||
import type {Thunk} from "@welshman/app"
|
||||
import PollOption from "@app/components/PollOption.svelte"
|
||||
import {command, reader, thunks, user, writer} from "@app/core"
|
||||
import {deriveEvents} from "@app/repository"
|
||||
import {command, events, reader, thunks, user, writer} from "@app/core"
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
|
|
@ -16,7 +15,7 @@
|
|||
|
||||
const {url, event}: Props = $props()
|
||||
|
||||
const responses = deriveEvents([{kinds: [POLL_RESPONSE], "#e": [event.id]}])
|
||||
const responses = $events.desc([{kinds: [POLL_RESPONSE], "#e": [event.id]}]).$
|
||||
|
||||
const getOwnResponse = (responses: TrustedEvent[]) => {
|
||||
let latest: TrustedEvent | undefined
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
import ModalBody from "@lib/components/ModalBody.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||
import {deriveEventsById} from "@app/repository"
|
||||
import ReportItem from "@app/components/ReportItem.svelte"
|
||||
import {events} from "@app/core"
|
||||
|
||||
type Props = {
|
||||
url: string
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
const {url, event}: Props = $props()
|
||||
|
||||
const reports = deriveEventsById([{kinds: [REPORT], "#e": [event.id]}])
|
||||
const reports = $events.byId([{kinds: [REPORT], "#e": [event.id]}]).$
|
||||
|
||||
const back = () => history.back()
|
||||
|
||||
|
|
|
|||
|
|
@ -32,12 +32,11 @@
|
|||
import RoomItemMenuButton from "@app/components/RoomItemMenuButton.svelte"
|
||||
import RoomItemMenuMobile from "@app/components/RoomItemMenuMobile.svelte"
|
||||
import RoomItemContent from "@app/components/RoomItemContent.svelte"
|
||||
import {profiles, thunks, user} from "@app/core"
|
||||
import {events, profiles, thunks, user} from "@app/core"
|
||||
import {noThunks, thunksByEventId} from "@app/thunks"
|
||||
import {colorFor} from "@app/theme"
|
||||
import {ENABLE_ZAPS} from "@app/env"
|
||||
import type {FeedContext} from "@app/feeds"
|
||||
import {deriveEvent, deriveEventsForUrl} from "@app/repository"
|
||||
import {highlightedEvent, makeContentPath, makeThreadPath} from "@app/routes"
|
||||
import {pushModal} from "@app/modal"
|
||||
|
||||
|
|
@ -70,16 +69,16 @@
|
|||
// A message that is nothing but a reference renders as the event it quotes.
|
||||
const isQuoteOnly = event.content.trim().split(/\s/).length === 1
|
||||
const quote = isQuoteOnly ? getContentQuote(event.content) : undefined
|
||||
const innerEvent = quote ? deriveEvent(quote.value, [url]) : readable(undefined)
|
||||
const innerEvent = quote ? $events.one(quote.value, [url]).$ : readable(undefined)
|
||||
const innerComments = $derived(
|
||||
$innerEvent ? deriveEventsForUrl(url, getCommentFiltersForParent([$innerEvent])) : readable([]),
|
||||
$innerEvent ? $events.forUrl(url, getCommentFiltersForParent([$innerEvent])).$ : readable([]),
|
||||
)
|
||||
|
||||
const path = $derived(
|
||||
$innerEvent && makeContentPath(url, $innerEvent.kind, getIdOrAddress($innerEvent)),
|
||||
)
|
||||
|
||||
const threads = deriveEventsForUrl(url, [{kinds: [THREAD], "#q": [event.id]}])
|
||||
const threads = $events.forUrl(url, [{kinds: [THREAD], "#q": [event.id]}]).$
|
||||
|
||||
const commenterDisplays = $derived(
|
||||
deriveDisplaysByPubkey(uniq($innerComments.map(e => e.pubkey)), url),
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@
|
|||
import PeopleItem from "@app/components/PeopleItem.svelte"
|
||||
import NoteCard from "@app/components/NoteCard.svelte"
|
||||
import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte"
|
||||
import {getEventsForUrl} from "@app/repository"
|
||||
import {network, profiles} from "@app/core"
|
||||
import {events, network, profiles} from "@app/core"
|
||||
import {popModal} from "@app/modal"
|
||||
import {pushToast} from "@app/toast"
|
||||
import {goToEvent} from "@app/routes"
|
||||
|
|
@ -52,7 +51,7 @@
|
|||
results = sortEventsDesc(
|
||||
uniqBy(
|
||||
(e: TrustedEvent) => e.id,
|
||||
relays.flatMap(relay => Array.from(getEventsForUrl(relay, filters))),
|
||||
relays.flatMap(relay => events.get().forUrl(relay, filters).get()),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@
|
|||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import Profile from "@app/components/Profile.svelte"
|
||||
import {relayMemberLists, relays} from "@app/core"
|
||||
import {deriveEventsForUrl} from "@app/repository"
|
||||
import {events, relayMemberLists, relays} from "@app/core"
|
||||
import {makeSpacePath} from "@app/routes"
|
||||
|
||||
type Props = {
|
||||
|
|
@ -18,7 +17,7 @@
|
|||
|
||||
const relay = $relays.one(url)
|
||||
const members = $relayMemberLists.forUrl(url)
|
||||
const memberEvents = deriveEventsForUrl(url, [{kinds: [RELAY_ADD_MEMBER, RELAY_JOIN]}])
|
||||
const memberEvents = $events.forUrl(url, [{kinds: [RELAY_ADD_MEMBER, RELAY_JOIN]}]).$
|
||||
|
||||
const admins = $derived($relay?.pubkey ? [$relay.pubkey] : [])
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,9 @@
|
|||
import Icon from "@lib/components/Icon.svelte"
|
||||
import SecondaryNavItem from "@lib/components/SecondaryNavItem.svelte"
|
||||
import SpaceSearch from "@app/components/SpaceSearch.svelte"
|
||||
import {relays} from "@app/core"
|
||||
import {events, relays} from "@app/core"
|
||||
import {ENABLE_ZAPS} from "@app/env"
|
||||
import {CONTENT_KINDS} from "@app/content"
|
||||
import {deriveEventsForUrl} from "@app/repository"
|
||||
import {makeSpacePath} from "@app/routes"
|
||||
import {allNotifications, notifications} from "@app/notifications"
|
||||
import {pushModal} from "@app/modal"
|
||||
|
|
@ -46,8 +45,8 @@
|
|||
const cachedKinds: number[] = getJson(spaceKindsKey) ?? []
|
||||
|
||||
const spaceKinds = deriveDeduplicatedByValue(
|
||||
deriveEventsForUrl(url, [{kinds: CONTENT_KINDS}]),
|
||||
$events => new Set([...cachedKinds, ...$events.map(e => e.kind)]),
|
||||
$events.forUrl(url, [{kinds: CONTENT_KINDS}]).$,
|
||||
$content => new Set([...cachedKinds, ...$content.map(e => e.kind)]),
|
||||
)
|
||||
|
||||
// A comment can name content this space doesn't have, and it counts toward the space either way.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||
import ReportItem from "@app/components/ReportItem.svelte"
|
||||
import RelayName from "@app/components/RelayName.svelte"
|
||||
import {deriveEventsForUrl} from "@app/repository"
|
||||
import {events} from "@app/core"
|
||||
|
||||
interface Props {
|
||||
url: string
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
const {url}: Props = $props()
|
||||
|
||||
const reports = deriveEventsForUrl(url, [{kinds: [REPORT]}])
|
||||
const reports = $events.forUrl(url, [{kinds: [REPORT]}]).$
|
||||
|
||||
const back = () => history.back()
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import {
|
|||
BlossomServerLists,
|
||||
Deletes,
|
||||
Domain,
|
||||
Events,
|
||||
FollowLists,
|
||||
Handles,
|
||||
Logger,
|
||||
|
|
@ -130,6 +131,7 @@ export const blockedRelayLists = usePlugin(BlockedRelayLists)
|
|||
export const blossomServerLists = usePlugin(BlossomServerLists)
|
||||
export const deletes = usePlugin(Deletes)
|
||||
export const domain = usePlugin(Domain)
|
||||
export const events = usePlugin(Events)
|
||||
export const followLists = usePlugin(FollowLists)
|
||||
export const handles = usePlugin(Handles)
|
||||
export const logger = usePlugin(Logger)
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import {derived} from "svelte/store"
|
|||
import {APP_DATA, sortEventsDesc, tagSpec, tagValues} from "@welshman/util"
|
||||
import {AppData} from "@welshman/domain"
|
||||
import {Relays, publish} from "@welshman/app"
|
||||
import {command, fromApp, writer} from "@app/core"
|
||||
import {deriveEventsForUrl} from "@app/repository"
|
||||
import {command, events, fromApp, writer} from "@app/core"
|
||||
import {toSpace} from "@app/rooms"
|
||||
|
||||
// NIP-78 app data from the pubkey the space's NIP-11 names, one ["content", <value>] tag per entry.
|
||||
|
|
@ -13,7 +12,7 @@ export const deriveFeaturedContent = (url: string) =>
|
|||
derived(
|
||||
[
|
||||
fromApp($app => $app.use(Relays).one(url)),
|
||||
deriveEventsForUrl(url, [{kinds: [APP_DATA], "#d": [FEATURED_CONTENT_D]}]),
|
||||
events.get().forUrl(url, [{kinds: [APP_DATA], "#d": [FEATURED_CONTENT_D]}]).$,
|
||||
],
|
||||
([$relay, $events]) => {
|
||||
const [event] = sortEventsDesc($events.filter(e => e.pubkey === $relay?.pubkey))
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import {
|
|||
tagValues,
|
||||
} from "@welshman/util"
|
||||
import {Comment, TimeEvent} from "@welshman/domain"
|
||||
import {Events} from "@welshman/app"
|
||||
import type {Maybe} from "@welshman/lib"
|
||||
import type {Filter, TrustedEvent} from "@welshman/util"
|
||||
import {mergeRepositoryUpdates} from "@welshman/net"
|
||||
|
|
@ -39,7 +40,6 @@ import type {ScrollerOpts} from "@lib/html"
|
|||
import {daysBetween} from "@lib/util"
|
||||
import {EVENT_CONTEXT_KINDS, REACTION_KINDS} from "@app/content"
|
||||
import {app, network, reader} from "@app/core"
|
||||
import {getEventsForUrl} from "@app/repository"
|
||||
|
||||
const noEvents: TrustedEvent[] = []
|
||||
|
||||
|
|
@ -661,7 +661,7 @@ export const makeFeed = ({
|
|||
|
||||
// What the repository already holds is an answer too, so a page of it renders before any relay replies.
|
||||
const stored = relays.map(url =>
|
||||
Array.from(getEventsForUrl(url, filters)).sort(compareEventsAsc).slice(-PAGE_SIZE),
|
||||
app.get().use(Events).forUrl(url, filters).get().sort(compareEventsAsc).slice(-PAGE_SIZE),
|
||||
)
|
||||
|
||||
if (stored.every(page => page.length > 0)) {
|
||||
|
|
@ -712,7 +712,7 @@ export const makeCalendarFeed = ({
|
|||
const events = writable(
|
||||
uniqBy(
|
||||
e => e.id,
|
||||
relays.flatMap(url => Array.from(getEventsForUrl(url, filters))),
|
||||
relays.flatMap(url => app.get().use(Events).forUrl(url, filters).get()),
|
||||
).sort(compareByStart),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ import {ago, MINUTE, now, simpleCache} from "@welshman/lib"
|
|||
import {ROOM_CREATE_PERMISSION, hexTags, tagValues} from "@welshman/util"
|
||||
import {RelayManagement, Relays} from "@welshman/app"
|
||||
import type {IApp} from "@welshman/app"
|
||||
import {fromApp, usePlugin, user} from "@app/core"
|
||||
import {deriveEventsForUrl} from "@app/repository"
|
||||
import {events, fromApp, usePlugin, user} from "@app/core"
|
||||
|
||||
// `supportedmethods` answers for the pubkey that signed the request, so this catalog is the client's.
|
||||
export const MANAGEMENT_METHOD_GROUPS = [
|
||||
|
|
@ -221,7 +220,7 @@ export const deriveUserCanCreateRoom = (url: string) =>
|
|||
derived(
|
||||
[
|
||||
user,
|
||||
deriveEventsForUrl(url, [{kinds: [ROOM_CREATE_PERMISSION]}]),
|
||||
events.get().forUrl(url, [{kinds: [ROOM_CREATE_PERMISSION]}]).$,
|
||||
deriveUserIsSpaceStaff(url),
|
||||
],
|
||||
([$user, $events, $isStaff]) =>
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ import {
|
|||
} from "@welshman/util"
|
||||
import {Comment} from "@welshman/domain"
|
||||
import {synced, throttled, withGetter} from "@welshman/store"
|
||||
import {Relays, RoomLists} from "@welshman/app"
|
||||
import {deriveEventsByIdByUrl} from "@app/repository"
|
||||
import {Events, Relays, RoomLists} from "@welshman/app"
|
||||
import {app, fromApp, reader} from "@app/core"
|
||||
import {makeRoomPath, makeSpaceChatPath, makeChatPath, makeContentPath} from "@app/routes"
|
||||
import {CONTENT_KINDS, makeCommentFilter} from "@app/content"
|
||||
|
|
@ -236,10 +235,13 @@ export const latestActivityByPath = derived(
|
|||
chatsById,
|
||||
fromApp($app => $app.use(Relays).index.$),
|
||||
fromApp($app => $app.use(RoomLists).index.$),
|
||||
deriveEventsByIdByUrl([
|
||||
{kinds: [MESSAGE, ...CONTENT_KINDS]},
|
||||
makeCommentFilter(CONTENT_KINDS),
|
||||
]),
|
||||
fromApp(
|
||||
$app =>
|
||||
$app
|
||||
.use(Events)
|
||||
.byIdByUrl([{kinds: [MESSAGE, ...CONTENT_KINDS]}, makeCommentFilter(CONTENT_KINDS)])
|
||||
.$,
|
||||
),
|
||||
userSettingsValues,
|
||||
],
|
||||
identity,
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import {derived} from "svelte/store"
|
|||
import type {Readable} from "svelte/store"
|
||||
import {getIdFilters, outbox} from "@welshman/util"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {network, pinLists, router} from "@app/core"
|
||||
import {deriveEvents} from "@app/repository"
|
||||
import {events, network, pinLists, router} from "@app/core"
|
||||
|
||||
export const derivePinnedEvents = (pubkey: string): Readable<TrustedEvent[]> =>
|
||||
derived(
|
||||
|
|
@ -22,7 +21,7 @@ export const derivePinnedEvents = (pubkey: string): Readable<TrustedEvent[]> =>
|
|||
network.get().loadLenient({relays: $relays, filters, signal: controller.signal}),
|
||||
)
|
||||
|
||||
const unsubscribe = deriveEvents(filters).subscribe(set)
|
||||
const unsubscribe = events.get().desc(filters).$.subscribe(set)
|
||||
|
||||
return () => {
|
||||
controller.abort()
|
||||
|
|
|
|||
|
|
@ -3,61 +3,8 @@ import type {Unsubscriber} from "svelte/store"
|
|||
import {first, on} from "@welshman/lib"
|
||||
import type {Maybe} from "@welshman/lib"
|
||||
import {sortEventsDesc} from "@welshman/util"
|
||||
import type {Filter, TrustedEvent} from "@welshman/util"
|
||||
import * as store from "@welshman/store"
|
||||
import {Network} from "@welshman/app"
|
||||
import {app, fromApp} from "@app/core"
|
||||
|
||||
// Events
|
||||
|
||||
export const deriveEvent = (idOrAddress: string, relays: string[] = []) =>
|
||||
fromApp($app =>
|
||||
store.makeDeriveEvent({
|
||||
repository: $app.repository,
|
||||
includeDeleted: true,
|
||||
onDerive: (filters: Filter[], hints: string[]) =>
|
||||
$app.use(Network).loadLenient({filters, relays: hints}),
|
||||
})(idOrAddress, relays),
|
||||
)
|
||||
|
||||
export const deriveEventsById = (filters: Filter[] = [{}]) =>
|
||||
fromApp($app => store.deriveEventsById({repository: $app.repository, filters}))
|
||||
|
||||
export const deriveEvents = (filters: Filter[] = [{}]) =>
|
||||
store.deriveEventsDesc(deriveEventsById(filters))
|
||||
|
||||
export const deriveIsDeleted = (event: TrustedEvent) =>
|
||||
fromApp($app => store.deriveIsDeleted($app.repository, event))
|
||||
|
||||
// Events on a relay
|
||||
|
||||
export const getEventsForUrl = (url: string, filters: Filter[] = [{}]) =>
|
||||
store
|
||||
.getEventsByIdForUrl({
|
||||
url,
|
||||
filters,
|
||||
tracker: app.get().tracker,
|
||||
repository: app.get().repository,
|
||||
})
|
||||
.values()
|
||||
|
||||
export const deriveEventsByIdForUrl = (url: string, filters: Filter[] = [{}]) =>
|
||||
fromApp($app =>
|
||||
store.deriveEventsByIdForUrl({
|
||||
url,
|
||||
filters,
|
||||
tracker: $app.tracker,
|
||||
repository: $app.repository,
|
||||
}),
|
||||
)
|
||||
|
||||
export const deriveEventsForUrl = (url: string, filters: Filter[] = [{}]) =>
|
||||
store.deriveArray(deriveEventsByIdForUrl(url, filters))
|
||||
|
||||
export const deriveEventsByIdByUrl = (filters: Filter[] = [{}]) =>
|
||||
fromApp($app =>
|
||||
store.deriveEventsByIdByUrl({filters, tracker: $app.tracker, repository: $app.repository}),
|
||||
)
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {app} from "@app/core"
|
||||
|
||||
// The most recent event held from one author.
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import {derived, readable} from "svelte/store"
|
|||
import type {Readable} from "svelte/store"
|
||||
import {getIdFilters, getIdOrAddress} from "@welshman/util"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {network, roomPinLists} from "@app/core"
|
||||
import {deriveEventsForUrl} from "@app/repository"
|
||||
import {events, network, roomPinLists} from "@app/core"
|
||||
|
||||
export const deriveRoomPinnedEvents = (url: string, h: string): Readable<TrustedEvent[]> =>
|
||||
readable<TrustedEvent[]>([], set => {
|
||||
|
|
@ -24,22 +23,25 @@ export const deriveRoomPinnedEvents = (url: string, h: string): Readable<Trusted
|
|||
|
||||
network.get().loadLenient({relays: [url], filters, signal: controller.signal})
|
||||
|
||||
return deriveEventsForUrl(url, filters).subscribe($events => {
|
||||
const byPin = new Map(
|
||||
$events.flatMap(event => [
|
||||
[event.id, event],
|
||||
[getIdOrAddress(event), event],
|
||||
]),
|
||||
)
|
||||
return events
|
||||
.get()
|
||||
.forUrl(url, filters)
|
||||
.$.subscribe($events => {
|
||||
const byPin = new Map(
|
||||
$events.flatMap(event => [
|
||||
[event.id, event],
|
||||
[getIdOrAddress(event), event],
|
||||
]),
|
||||
)
|
||||
|
||||
setEvents(
|
||||
$pins.flatMap(pin => {
|
||||
const event = byPin.get(pin)
|
||||
setEvents(
|
||||
$pins.flatMap(pin => {
|
||||
const event = byPin.get(pin)
|
||||
|
||||
return event ? [event] : []
|
||||
}),
|
||||
)
|
||||
})
|
||||
return event ? [event] : []
|
||||
}),
|
||||
)
|
||||
})
|
||||
},
|
||||
).subscribe(set)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,7 @@
|
|||
import EventComments from "@app/components/EventComments.svelte"
|
||||
import EventMenu from "@app/components/EventMenu.svelte"
|
||||
import ReadingProgress from "@app/components/ReadingProgress.svelte"
|
||||
import {reader} from "@app/core"
|
||||
import {deriveEvent} from "@app/repository"
|
||||
import {events, reader} from "@app/core"
|
||||
import {makeFeedContext} from "@app/feeds"
|
||||
import {decodeRelay} from "@app/relays"
|
||||
import {displayReadingTime} from "@app/articles"
|
||||
|
|
@ -29,7 +28,7 @@
|
|||
const {relay, address} = params
|
||||
const url = decodeRelay(relay)
|
||||
const context = makeFeedContext({relays: [url]})
|
||||
const event = deriveEvent(address, [url])
|
||||
const event = $events.one(address, [url]).$
|
||||
const article = derived(event, $event => ($event ? reader(Article)($event) : undefined))
|
||||
const h = $derived($article?.room())
|
||||
const topics = $derived(uniq($article?.topics() ?? []))
|
||||
|
|
|
|||
|
|
@ -23,8 +23,7 @@
|
|||
import CalendarEventPeople from "@app/components/CalendarEventPeople.svelte"
|
||||
import CalendarRsvp from "@app/components/CalendarRsvp.svelte"
|
||||
import {deriveRsvps, getRsvpsByStatus, makeRsvpFilter} from "@app/calendar"
|
||||
import {network, reader} from "@app/core"
|
||||
import {deriveEvent, deriveEvents} from "@app/repository"
|
||||
import {events, network, reader} from "@app/core"
|
||||
import {makeFeedContext} from "@app/feeds"
|
||||
import {decodeRelay} from "@app/relays"
|
||||
import type {PageProps} from "./$types"
|
||||
|
|
@ -34,10 +33,10 @@
|
|||
const {relay, address} = params
|
||||
const url = decodeRelay(relay)
|
||||
const context = makeFeedContext({relays: [url]})
|
||||
const event = deriveEvent(address, [url])
|
||||
const event = $events.one(address, [url]).$
|
||||
const timeEvent = derived(event, $event => ($event ? reader(TimeEvent)($event) : undefined))
|
||||
const filters = $derived($event ? getCommentFiltersForRoot([$event]) : [])
|
||||
const replies = $derived(deriveEvents(filters))
|
||||
const replies = $derived($events.desc(filters).$)
|
||||
const rsvps = $derived($event ? deriveRsvps($event) : readable<TrustedEvent[]>([]))
|
||||
const people = $derived(getRsvpsByStatus($rsvps))
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@
|
|||
import NoteCard from "@app/components/NoteCard.svelte"
|
||||
import ClassifiedActions from "@app/components/ClassifiedActions.svelte"
|
||||
import EventComments from "@app/components/EventComments.svelte"
|
||||
import {reader} from "@app/core"
|
||||
import {deriveEvent} from "@app/repository"
|
||||
import {events, reader} from "@app/core"
|
||||
import {makeFeedContext} from "@app/feeds"
|
||||
import {decodeRelay} from "@app/relays"
|
||||
import type {PageProps} from "./$types"
|
||||
|
|
@ -21,7 +20,7 @@
|
|||
const {relay, address} = params
|
||||
const url = decodeRelay(relay)
|
||||
const context = makeFeedContext({relays: [url]})
|
||||
const event = deriveEvent(address, [url])
|
||||
const event = $events.one(address, [url]).$
|
||||
const classified = derived(event, $event => ($event ? reader(Classified)($event) : undefined))
|
||||
|
||||
const back = () => history.back()
|
||||
|
|
|
|||
|
|
@ -18,10 +18,9 @@
|
|||
import GoalStatus from "@app/components/GoalStatus.svelte"
|
||||
import GoalSupporters from "@app/components/GoalSupporters.svelte"
|
||||
import EventComments from "@app/components/EventComments.svelte"
|
||||
import {reader} from "@app/core"
|
||||
import {events, reader} from "@app/core"
|
||||
import {ENABLE_ZAPS} from "@app/env"
|
||||
import {deriveGoalProgress} from "@app/goals"
|
||||
import {deriveEvent} from "@app/repository"
|
||||
import {makeFeedContext} from "@app/feeds"
|
||||
import {decodeRelay} from "@app/relays"
|
||||
import type {PageProps} from "./$types"
|
||||
|
|
@ -31,7 +30,7 @@
|
|||
const {relay, id} = params
|
||||
const url = decodeRelay(relay)
|
||||
const context = makeFeedContext({relays: [url]})
|
||||
const event = deriveEvent(id, [url])
|
||||
const event = $events.one(id, [url]).$
|
||||
const goal = derived(event, $event => ($event ? reader(ZapGoal)($event) : undefined))
|
||||
const progress = $derived($event ? deriveGoalProgress($event, url) : undefined)
|
||||
const remaining = $derived($progress ? Math.max(0, $progress.target - $progress.raised) : 0)
|
||||
|
|
|
|||
|
|
@ -21,9 +21,8 @@
|
|||
import PinAdd from "@app/components/PinAdd.svelte"
|
||||
import PinboardItem from "@app/components/PinboardItem.svelte"
|
||||
import PinboardEdit from "@app/components/PinboardEdit.svelte"
|
||||
import {app, network, reader} from "@app/core"
|
||||
import {app, events, network, reader} from "@app/core"
|
||||
import {decodeRelay} from "@app/relays"
|
||||
import {deriveEventsForUrl} from "@app/repository"
|
||||
import {makeLibraryPath} from "@app/routes"
|
||||
import {pushModal} from "@app/modal"
|
||||
import type {PageProps} from "./$types"
|
||||
|
|
@ -36,8 +35,8 @@
|
|||
let loading = $state(true)
|
||||
|
||||
// A shelf belongs to the space it was published to rather than to the pubkey that signed it.
|
||||
const boards = derived(deriveEventsForUrl(url, [{kinds: [PINBOARD]}]), $events =>
|
||||
$events.map(reader(Pinboard)),
|
||||
const boards = derived($events.forUrl(url, [{kinds: [PINBOARD]}]).$, $pinboards =>
|
||||
$pinboards.map(reader(Pinboard)),
|
||||
)
|
||||
|
||||
const address = $derived($page.url.searchParams.get("board") ?? "")
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
import {onDestroy, onMount} from "svelte"
|
||||
import {sleep} from "@welshman/lib"
|
||||
import {POLL, POLL_RESPONSE, getCommentFiltersForRoot} from "@welshman/util"
|
||||
import {deriveEventsAsc} from "@welshman/store"
|
||||
import SortVertical from "@assets/icons/sort-vertical.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import PageContent from "@lib/components/PageContent.svelte"
|
||||
|
|
@ -13,8 +12,7 @@
|
|||
import NoteContent from "@app/components/NoteContent.svelte"
|
||||
import CommentActions from "@app/components/CommentActions.svelte"
|
||||
import EventReply from "@app/components/EventReply.svelte"
|
||||
import {network} from "@app/core"
|
||||
import {deriveEvent, deriveEventsById} from "@app/repository"
|
||||
import {events, network} from "@app/core"
|
||||
import {makeFeedContext} from "@app/feeds"
|
||||
import {decodeRelay} from "@app/relays"
|
||||
import type {PageProps} from "./$types"
|
||||
|
|
@ -24,9 +22,9 @@
|
|||
const {relay, id} = params
|
||||
const url = decodeRelay(relay)
|
||||
const context = makeFeedContext({relays: [url]})
|
||||
const event = deriveEvent(id, [url])
|
||||
const event = $events.one(id, [url]).$
|
||||
const filters = $derived($event ? getCommentFiltersForRoot([$event]) : [])
|
||||
const comments = $derived(deriveEventsAsc(deriveEventsById(filters)))
|
||||
const comments = $derived($events.asc(filters).$)
|
||||
|
||||
const back = () => history.back()
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
import {page} from "$app/state"
|
||||
import {sleep, spec} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {deriveEventsAsc} from "@welshman/store"
|
||||
import {getCommentFiltersForRoot} from "@welshman/util"
|
||||
import Reply from "@assets/icons/reply-2.svg?dataurl"
|
||||
import AltArrowDown from "@assets/icons/alt-arrow-down.svg?dataurl"
|
||||
|
|
@ -15,8 +14,7 @@
|
|||
import ThreadPost from "@app/components/ThreadPost.svelte"
|
||||
import ThreadSummaryBar from "@app/components/ThreadSummaryBar.svelte"
|
||||
import EventReply from "@app/components/EventReply.svelte"
|
||||
import {deriveEvent, deriveEventsById} from "@app/repository"
|
||||
import {network} from "@app/core"
|
||||
import {events, network} from "@app/core"
|
||||
import {makeFeedContext} from "@app/feeds"
|
||||
import {getChecked} from "@app/notifications"
|
||||
import {decodeRelay} from "@app/relays"
|
||||
|
|
@ -29,11 +27,11 @@
|
|||
|
||||
const {relay, id} = params
|
||||
const url = decodeRelay(relay)
|
||||
const event = deriveEvent(id, [url])
|
||||
const event = $events.one(id, [url]).$
|
||||
// Rows register themselves with `related`, so the whole page's reactions load in one batch
|
||||
const context = makeFeedContext({relays: [url]})
|
||||
const filters = $derived($event ? getCommentFiltersForRoot([$event]) : [])
|
||||
const replies = $derived(deriveEventsAsc(deriveEventsById(filters)))
|
||||
const replies = $derived($events.asc(filters).$)
|
||||
|
||||
const scrollToTop = () => element?.scrollTo({top: 0, behavior: "smooth"})
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue