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
|
**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
|
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
|
Articles are composed on a full page (`spaces/[relay]/articles/create`, built by
|
||||||
`makeArticleCreatePath`) instead of in a modal.
|
`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
|
readers must check the author. The welshman collections do: `Rooms` and every
|
||||||
`RelaySignedDerivedPlugin` (`RelayMemberLists`, `RelayRoles`, `RoomPinLists`) drop events whose
|
`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
|
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
|
plugin, read `$events.relaySignedForUrl(url, filters)`, which keeps only events signed by that
|
||||||
bare `deriveEventsForUrl`.
|
`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
|
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
|
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`.
|
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
|
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
|
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
|
relays. `src/app/sync.ts` pulls each space's room state, membership and recent content in the
|
||||||
background; see flotilla-state.
|
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` |
|
| `session` | the persisted `Session` | `undefined` |
|
||||||
| `user` | `User.require($app)`, derived | subscribing or `.get()` throws |
|
| `user` | `User.require($app)`, derived | subscribing or `.get()` throws |
|
||||||
| `usePlugin(Plugin)` | a store holding `$app.use(Plugin)` for the current app | safe |
|
| `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 |
|
| `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` |
|
| `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 |
|
| `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
|
optimistically. The tracker records which relays each event was seen on, which is what lets
|
||||||
space content be keyed by relay.
|
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`
|
- `one(idOrAddress, relays)` (loads when nothing local matches, keeps deleted events), `byId`,
|
||||||
- relay-scoped: `deriveEventsForUrl`, `deriveEventsByIdForUrl`, `deriveEventsByIdByUrl`,
|
`all`, `asc`, `desc`, `isDeleted`
|
||||||
`getEventsForUrl`
|
- relay-scoped through the tracker: `forUrl`, `byIdForUrl`, `byIdByUrl`, and
|
||||||
- `deriveLatestEvent`
|
`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
|
Components bind `$events.forUrl(url, filters).$`. A `derive*` function called from gated code
|
||||||
projections, and flotilla does not use it. Plugin reads (`get`, `one`, `load`, `index`) are
|
binds `events.get().forUrl(...).$` at call time, and a module-scope store wraps it in
|
||||||
documented in welshman-app.
|
`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
|
### Free functions in an app module
|
||||||
|
|
||||||
|
|
@ -196,7 +199,7 @@ projections and repository derivations:
|
||||||
export const deriveSpaceActionItems = (url: string) =>
|
export const deriveSpaceActionItems = (url: string) =>
|
||||||
derived(
|
derived(
|
||||||
[
|
[
|
||||||
deriveEventsForUrl(url, [{kinds: [REPORT]}]),
|
events.get().forUrl(url, [{kinds: [REPORT]}]).$,
|
||||||
rooms.get().pendingJoins(url).$,
|
rooms.get().pendingJoins(url).$,
|
||||||
deriveSpacePermissions(url),
|
deriveSpacePermissions(url),
|
||||||
],
|
],
|
||||||
|
|
@ -424,7 +427,7 @@ store, consumed in components with `$store`.
|
||||||
Take the first answer that fits:
|
Take the first answer that fits:
|
||||||
|
|
||||||
1. **It is an event, or derived from events.** It is already in the repository, or should be.
|
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
|
`derive*` function in the owning app module (`deriveUserRooms`). Don't copy it into a
|
||||||
writable.
|
writable.
|
||||||
2. **It is a keyed collection of one kind, loaded by key.** Write a plugin. A generic kind goes
|
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`.
|
`$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
|
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
|
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
|
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
|
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
|
## Reading state in a component
|
||||||
|
|
||||||
Components read plugins through the `usePlugin` stores exported from `src/app/core.ts`
|
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`,
|
`$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.
|
`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">
|
<script lang="ts">
|
||||||
const room = $rooms.forRoom(url, h) // Readable: one, forRoom
|
const room = $rooms.forRoom(url, h) // Readable: one, forRoom
|
||||||
const display = $profiles.display(pubkey, removeUndefined([url])).$ // Projection: take .$
|
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
|
const shouldProtect = $relays.hasNip(url, 70) // Promise: load, hasNip
|
||||||
</script>
|
</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*`
|
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
|
`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
|
`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
|
`$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
|
`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`.
|
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:
|
empty, seven pages show a spinner that turns into a failure message:
|
||||||
|
|
||||||
```svelte
|
```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
|
**Related events:** request them, abort on teardown, and read them back from the repository with
|
||||||
`deriveEventsAsc(deriveEventsById(filters))`.
|
`$events.asc(filters).$`.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
onMount(() => {
|
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-architecture`: layer rules and exceptions, the `src/app` modules, boot, placement
|
||||||
- `flotilla-state`: plugin stores, `derive*` stores, drafts, settings, thunks and commands
|
- `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
|
- `flotilla-model`: spaces, rooms, NIP-43/29/86, content kinds, and where events are published
|
||||||
- `welshman-app`: plugins, projections, `Command`, thunks, `Feeds`
|
- `welshman-app`: plugins, projections, `Command`, thunks, `Events`, `Feeds`
|
||||||
- `welshman-store`: `deriveEventsById`, `deriveEventsAsc`, the other repository stores
|
- `welshman-store`: `deriveEventsById`, `deriveEventsAsc`, the repository stores under `Events`
|
||||||
- `welshman-domain`: the readers and writers behind `reader` and `writer`
|
- `welshman-domain`: the readers and writers behind `reader` and `writer`
|
||||||
- `welshman-feeds`: `FeedController`, still used by `ProfileFeed`
|
- `welshman-feeds`: `FeedController`, still used by `ProfileFeed`
|
||||||
- `welshman-editor`: the composer behind `makeEditor`
|
- `welshman-editor`: the composer behind `makeEditor`
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import {derived} from "svelte/store"
|
import {derived} from "svelte/store"
|
||||||
import {REPORT, sortEventsDesc} from "@welshman/util"
|
import {REPORT, sortEventsDesc} from "@welshman/util"
|
||||||
import {rooms} from "@app/core"
|
import {events, rooms} from "@app/core"
|
||||||
import {deriveSpacePermissions} from "@app/management"
|
import {deriveSpacePermissions} from "@app/management"
|
||||||
import {deriveEventsForUrl} from "@app/repository"
|
|
||||||
|
|
||||||
// Action items (admin review queue)
|
// Action items (admin review queue)
|
||||||
|
|
||||||
|
|
@ -10,7 +9,7 @@ import {deriveEventsForUrl} from "@app/repository"
|
||||||
export const deriveSpaceActionItems = (url: string) =>
|
export const deriveSpaceActionItems = (url: string) =>
|
||||||
derived(
|
derived(
|
||||||
[
|
[
|
||||||
deriveEventsForUrl(url, [{kinds: [REPORT]}]),
|
events.get().forUrl(url, [{kinds: [REPORT]}]).$,
|
||||||
rooms.get().pendingJoins(url).$,
|
rooms.get().pendingJoins(url).$,
|
||||||
deriveSpacePermissions(url),
|
deriveSpacePermissions(url),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,7 @@ import type {TrustedEvent} from "@welshman/util"
|
||||||
import {CalendarRsvp, TimeEvent} from "@welshman/domain"
|
import {CalendarRsvp, TimeEvent} from "@welshman/domain"
|
||||||
import type {RsvpStatus} from "@welshman/domain"
|
import type {RsvpStatus} from "@welshman/domain"
|
||||||
import {synced} from "@welshman/store"
|
import {synced} from "@welshman/store"
|
||||||
import {deletes, reader, relays, thunks, writer} from "@app/core"
|
import {deletes, events, reader, relays, thunks, writer} from "@app/core"
|
||||||
import {deriveEvents} from "@app/repository"
|
|
||||||
import {toSpace} from "@app/rooms"
|
import {toSpace} from "@app/rooms"
|
||||||
import {kv} from "@app/storage"
|
import {kv} from "@app/storage"
|
||||||
|
|
||||||
|
|
@ -237,7 +236,7 @@ export const makeRsvpFilter = (event: TrustedEvent) => ({
|
||||||
"#a": [getAddress(event)],
|
"#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"
|
export const isAttending = (status?: RsvpStatus) => status === "accepted" || status === "tentative"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,7 @@ import {deriveDeduplicated} from "@welshman/store"
|
||||||
import {makeRoomKey} from "@welshman/app"
|
import {makeRoomKey} from "@welshman/app"
|
||||||
import type {Room} from "@welshman/app"
|
import type {Room} from "@welshman/app"
|
||||||
import type {Room as LiveKitRoom} from "livekit-client"
|
import type {Room as LiveKitRoom} from "livekit-client"
|
||||||
import {network} from "@app/core"
|
import {events, network} from "@app/core"
|
||||||
import {deriveEventsForUrl} from "@app/repository"
|
|
||||||
|
|
||||||
export const LIVEKIT_PARTICIPANTS = 39004
|
export const LIVEKIT_PARTICIPANTS = 39004
|
||||||
|
|
||||||
|
|
@ -304,7 +303,7 @@ export const deriveCallParticipants = (url: string, h: string) =>
|
||||||
participantMediaState,
|
participantMediaState,
|
||||||
callTargetRoom,
|
callTargetRoom,
|
||||||
deriveDeduplicated(
|
deriveDeduplicated(
|
||||||
deriveEventsForUrl(url, [{kinds: [LIVEKIT_PARTICIPANTS], "#d": [h]}]),
|
events.get().forUrl(url, [{kinds: [LIVEKIT_PARTICIPANTS], "#d": [h]}]).$,
|
||||||
events => first(sortEventsDesc(events)),
|
events => first(sortEventsDesc(events)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,7 @@
|
||||||
import EventActivity from "@app/components/EventActivity.svelte"
|
import EventActivity from "@app/components/EventActivity.svelte"
|
||||||
import EventActions from "@app/components/EventActions.svelte"
|
import EventActions from "@app/components/EventActions.svelte"
|
||||||
import EventActionBar from "@app/components/EventActionBar.svelte"
|
import EventActionBar from "@app/components/EventActionBar.svelte"
|
||||||
import {reader} from "@app/core"
|
import {events, reader} from "@app/core"
|
||||||
import {deriveIsDeleted} from "@app/repository"
|
|
||||||
import {makeSpacePath} from "@app/routes"
|
import {makeSpacePath} from "@app/routes"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
@ -30,7 +29,7 @@
|
||||||
const article = $derived(reader(Article)(event))
|
const article = $derived(reader(Article)(event))
|
||||||
const h = $derived(article.room())
|
const h = $derived(article.room())
|
||||||
const topics = $derived(article.topics())
|
const topics = $derived(article.topics())
|
||||||
const deleted = $derived(deriveIsDeleted(event))
|
const deleted = $derived($events.isDeleted(event).$)
|
||||||
|
|
||||||
const deleteReaction = (reaction: TrustedEvent) => retractReaction(reaction, {url, h})
|
const deleteReaction = (reaction: TrustedEvent) => retractReaction(reaction, {url, h})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,7 @@
|
||||||
import Profile from "@app/components/Profile.svelte"
|
import Profile from "@app/components/Profile.svelte"
|
||||||
import ProfileName from "@app/components/ProfileName.svelte"
|
import ProfileName from "@app/components/ProfileName.svelte"
|
||||||
import ProfileAbout from "@app/components/ProfileAbout.svelte"
|
import ProfileAbout from "@app/components/ProfileAbout.svelte"
|
||||||
import {network, reader} from "@app/core"
|
import {events, network, reader} from "@app/core"
|
||||||
import {deriveEventsForUrl} from "@app/repository"
|
|
||||||
import {displayReadingTime} from "@app/articles"
|
import {displayReadingTime} from "@app/articles"
|
||||||
import {makeArticlePath} from "@app/routes"
|
import {makeArticlePath} from "@app/routes"
|
||||||
|
|
||||||
|
|
@ -24,15 +23,15 @@
|
||||||
const MAX_ARTICLES = 6
|
const MAX_ARTICLES = 6
|
||||||
|
|
||||||
const filters = [{kinds: [LONG_FORM], authors: [event.pubkey], limit: 20}]
|
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 address = getAddress(event)
|
||||||
|
|
||||||
const articleCount = $derived($events.length)
|
const articleCount = $derived($articles.length)
|
||||||
|
|
||||||
const others = $derived(
|
const others = $derived(
|
||||||
sortBy(
|
sortBy(
|
||||||
e => -reader(Article)(e).publishedAt(),
|
e => -reader(Article)(e).publishedAt(),
|
||||||
$events.filter(e => getAddress(e) !== address),
|
$articles.filter(e => getAddress(e) !== address),
|
||||||
).slice(0, MAX_ARTICLES),
|
).slice(0, MAX_ARTICLES),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,7 @@
|
||||||
import NoteCard from "@app/components/NoteCard.svelte"
|
import NoteCard from "@app/components/NoteCard.svelte"
|
||||||
import NoteContent from "@app/components/NoteContent.svelte"
|
import NoteContent from "@app/components/NoteContent.svelte"
|
||||||
import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte"
|
import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte"
|
||||||
import {network, router} from "@app/core"
|
import {events, network, router} from "@app/core"
|
||||||
import {deriveEvent} from "@app/repository"
|
|
||||||
import {entityLink} from "@app/env"
|
import {entityLink} from "@app/env"
|
||||||
import {goToEvent} from "@app/routes"
|
import {goToEvent} from "@app/routes"
|
||||||
|
|
||||||
|
|
@ -39,7 +38,7 @@
|
||||||
|
|
||||||
const mergedRelays = writable(hints)
|
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.
|
// Whoever quoted the event must have seen it, so the quoting event's relays are asked too.
|
||||||
$router.resolver
|
$router.resolver
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,13 @@
|
||||||
import {removeUndefined} from "@welshman/lib"
|
import {removeUndefined} from "@welshman/lib"
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import {getCommentFiltersForRoot} from "@welshman/util"
|
import {getCommentFiltersForRoot} from "@welshman/util"
|
||||||
import {deriveEventsAsc} from "@welshman/store"
|
|
||||||
import Reply from "@assets/icons/reply-2.svg?dataurl"
|
import Reply from "@assets/icons/reply-2.svg?dataurl"
|
||||||
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"
|
||||||
import CommentTree from "@app/components/CommentTree.svelte"
|
import CommentTree from "@app/components/CommentTree.svelte"
|
||||||
import type {FeedContext} from "@app/feeds"
|
import type {FeedContext} from "@app/feeds"
|
||||||
import CommentCompose from "@app/components/CommentCompose.svelte"
|
import CommentCompose from "@app/components/CommentCompose.svelte"
|
||||||
import {network} from "@app/core"
|
import {events, network} from "@app/core"
|
||||||
import {deriveEventsById} from "@app/repository"
|
|
||||||
import {buildCommentTree} from "@app/social"
|
import {buildCommentTree} from "@app/social"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
@ -24,7 +22,7 @@
|
||||||
|
|
||||||
const relays = removeUndefined([url])
|
const relays = removeUndefined([url])
|
||||||
const filters = getCommentFiltersForRoot([event])
|
const filters = getCommentFiltersForRoot([event])
|
||||||
const comments = deriveEventsAsc(deriveEventsById(filters))
|
const comments = $events.asc(filters).$
|
||||||
|
|
||||||
const nodes = $derived(buildCommentTree(event, $comments))
|
const nodes = $derived(buildCommentTree(event, $comments))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,11 @@
|
||||||
import {POLL_RESPONSE} from "@welshman/util"
|
import {POLL_RESPONSE} from "@welshman/util"
|
||||||
import {Poll} from "@welshman/domain"
|
import {Poll} from "@welshman/domain"
|
||||||
import ContentMinimal from "@app/components/ContentMinimal.svelte"
|
import ContentMinimal from "@app/components/ContentMinimal.svelte"
|
||||||
import {reader} from "@app/core"
|
import {events, reader} from "@app/core"
|
||||||
import {deriveEvents} from "@app/repository"
|
|
||||||
|
|
||||||
const props: ComponentProps<typeof ContentMinimal> = $props()
|
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)
|
const voters = $derived(reader(Poll)(props.event).results($responses).voters)
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
import {onDestroy} from "svelte"
|
import {onDestroy} from "svelte"
|
||||||
import Spinner from "@lib/components/Spinner.svelte"
|
import Spinner from "@lib/components/Spinner.svelte"
|
||||||
import NoteItem from "@app/components/NoteItem.svelte"
|
import NoteItem from "@app/components/NoteItem.svelte"
|
||||||
|
import {events} from "@app/core"
|
||||||
import {makeFeedContext} from "@app/feeds"
|
import {makeFeedContext} from "@app/feeds"
|
||||||
import {deriveEvent} from "@app/repository"
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url?: string
|
url?: string
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
const {url, value, relays}: Props = $props()
|
const {url, value, relays}: Props = $props()
|
||||||
|
|
||||||
const event = deriveEvent(value, relays)
|
const event = $events.one(value, relays).$
|
||||||
const context = makeFeedContext({relays})
|
const context = makeFeedContext({relays})
|
||||||
|
|
||||||
onDestroy(context.cleanup)
|
onDestroy(context.cleanup)
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,8 @@
|
||||||
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
|
import ModalSubtitle from "@lib/components/ModalSubtitle.svelte"
|
||||||
import RelayName from "@app/components/RelayName.svelte"
|
import RelayName from "@app/components/RelayName.svelte"
|
||||||
import PinAdd from "@app/components/PinAdd.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 {eventToReference} from "@app/pinboards"
|
||||||
import {deriveEventsForUrl} from "@app/repository"
|
|
||||||
import {makeSpacePath} from "@app/routes"
|
import {makeSpacePath} from "@app/routes"
|
||||||
import {pushModal} from "@app/modal"
|
import {pushModal} from "@app/modal"
|
||||||
|
|
||||||
|
|
@ -28,8 +27,8 @@
|
||||||
|
|
||||||
const {url, event}: Props = $props()
|
const {url, event}: Props = $props()
|
||||||
|
|
||||||
const boards = derived(deriveEventsForUrl(url, [{kinds: [PINBOARD]}]), $events =>
|
const boards = derived($events.forUrl(url, [{kinds: [PINBOARD]}]).$, $pinboards =>
|
||||||
$events.map(reader(Pinboard)),
|
$pinboards.map(reader(Pinboard)),
|
||||||
)
|
)
|
||||||
|
|
||||||
const reference = eventToReference(event)
|
const reference = eventToReference(event)
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,7 @@
|
||||||
import {Poll, PollResponse} from "@welshman/domain"
|
import {Poll, PollResponse} from "@welshman/domain"
|
||||||
import type {Thunk} from "@welshman/app"
|
import type {Thunk} from "@welshman/app"
|
||||||
import PollOption from "@app/components/PollOption.svelte"
|
import PollOption from "@app/components/PollOption.svelte"
|
||||||
import {command, reader, thunks, user, writer} from "@app/core"
|
import {command, events, reader, thunks, user, writer} from "@app/core"
|
||||||
import {deriveEvents} from "@app/repository"
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url: string
|
url: string
|
||||||
|
|
@ -16,7 +15,7 @@
|
||||||
|
|
||||||
const {url, event}: Props = $props()
|
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[]) => {
|
const getOwnResponse = (responses: TrustedEvent[]) => {
|
||||||
let latest: TrustedEvent | undefined
|
let latest: TrustedEvent | undefined
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@
|
||||||
import ModalBody from "@lib/components/ModalBody.svelte"
|
import ModalBody from "@lib/components/ModalBody.svelte"
|
||||||
import Button from "@lib/components/Button.svelte"
|
import Button from "@lib/components/Button.svelte"
|
||||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||||
import {deriveEventsById} from "@app/repository"
|
|
||||||
import ReportItem from "@app/components/ReportItem.svelte"
|
import ReportItem from "@app/components/ReportItem.svelte"
|
||||||
|
import {events} from "@app/core"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url: string
|
url: string
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
const {url, event}: Props = $props()
|
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()
|
const back = () => history.back()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,11 @@
|
||||||
import RoomItemMenuButton from "@app/components/RoomItemMenuButton.svelte"
|
import RoomItemMenuButton from "@app/components/RoomItemMenuButton.svelte"
|
||||||
import RoomItemMenuMobile from "@app/components/RoomItemMenuMobile.svelte"
|
import RoomItemMenuMobile from "@app/components/RoomItemMenuMobile.svelte"
|
||||||
import RoomItemContent from "@app/components/RoomItemContent.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 {noThunks, thunksByEventId} from "@app/thunks"
|
||||||
import {colorFor} from "@app/theme"
|
import {colorFor} from "@app/theme"
|
||||||
import {ENABLE_ZAPS} from "@app/env"
|
import {ENABLE_ZAPS} from "@app/env"
|
||||||
import type {FeedContext} from "@app/feeds"
|
import type {FeedContext} from "@app/feeds"
|
||||||
import {deriveEvent, deriveEventsForUrl} from "@app/repository"
|
|
||||||
import {highlightedEvent, makeContentPath, makeThreadPath} from "@app/routes"
|
import {highlightedEvent, makeContentPath, makeThreadPath} from "@app/routes"
|
||||||
import {pushModal} from "@app/modal"
|
import {pushModal} from "@app/modal"
|
||||||
|
|
||||||
|
|
@ -70,16 +69,16 @@
|
||||||
// A message that is nothing but a reference renders as the event it quotes.
|
// A message that is nothing but a reference renders as the event it quotes.
|
||||||
const isQuoteOnly = event.content.trim().split(/\s/).length === 1
|
const isQuoteOnly = event.content.trim().split(/\s/).length === 1
|
||||||
const quote = isQuoteOnly ? getContentQuote(event.content) : undefined
|
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(
|
const innerComments = $derived(
|
||||||
$innerEvent ? deriveEventsForUrl(url, getCommentFiltersForParent([$innerEvent])) : readable([]),
|
$innerEvent ? $events.forUrl(url, getCommentFiltersForParent([$innerEvent])).$ : readable([]),
|
||||||
)
|
)
|
||||||
|
|
||||||
const path = $derived(
|
const path = $derived(
|
||||||
$innerEvent && makeContentPath(url, $innerEvent.kind, getIdOrAddress($innerEvent)),
|
$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(
|
const commenterDisplays = $derived(
|
||||||
deriveDisplaysByPubkey(uniq($innerComments.map(e => e.pubkey)), url),
|
deriveDisplaysByPubkey(uniq($innerComments.map(e => e.pubkey)), url),
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,7 @@
|
||||||
import PeopleItem from "@app/components/PeopleItem.svelte"
|
import PeopleItem from "@app/components/PeopleItem.svelte"
|
||||||
import NoteCard from "@app/components/NoteCard.svelte"
|
import NoteCard from "@app/components/NoteCard.svelte"
|
||||||
import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte"
|
import NoteContentMinimal from "@app/components/NoteContentMinimal.svelte"
|
||||||
import {getEventsForUrl} from "@app/repository"
|
import {events, network, profiles} from "@app/core"
|
||||||
import {network, profiles} from "@app/core"
|
|
||||||
import {popModal} from "@app/modal"
|
import {popModal} from "@app/modal"
|
||||||
import {pushToast} from "@app/toast"
|
import {pushToast} from "@app/toast"
|
||||||
import {goToEvent} from "@app/routes"
|
import {goToEvent} from "@app/routes"
|
||||||
|
|
@ -52,7 +51,7 @@
|
||||||
results = sortEventsDesc(
|
results = sortEventsDesc(
|
||||||
uniqBy(
|
uniqBy(
|
||||||
(e: TrustedEvent) => e.id,
|
(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 Icon from "@lib/components/Icon.svelte"
|
||||||
import Link from "@lib/components/Link.svelte"
|
import Link from "@lib/components/Link.svelte"
|
||||||
import Profile from "@app/components/Profile.svelte"
|
import Profile from "@app/components/Profile.svelte"
|
||||||
import {relayMemberLists, relays} from "@app/core"
|
import {events, relayMemberLists, relays} from "@app/core"
|
||||||
import {deriveEventsForUrl} from "@app/repository"
|
|
||||||
import {makeSpacePath} from "@app/routes"
|
import {makeSpacePath} from "@app/routes"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
@ -18,7 +17,7 @@
|
||||||
|
|
||||||
const relay = $relays.one(url)
|
const relay = $relays.one(url)
|
||||||
const members = $relayMemberLists.forUrl(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] : [])
|
const admins = $derived($relay?.pubkey ? [$relay.pubkey] : [])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,9 @@
|
||||||
import Icon from "@lib/components/Icon.svelte"
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
import SecondaryNavItem from "@lib/components/SecondaryNavItem.svelte"
|
import SecondaryNavItem from "@lib/components/SecondaryNavItem.svelte"
|
||||||
import SpaceSearch from "@app/components/SpaceSearch.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 {ENABLE_ZAPS} from "@app/env"
|
||||||
import {CONTENT_KINDS} from "@app/content"
|
import {CONTENT_KINDS} from "@app/content"
|
||||||
import {deriveEventsForUrl} from "@app/repository"
|
|
||||||
import {makeSpacePath} from "@app/routes"
|
import {makeSpacePath} from "@app/routes"
|
||||||
import {allNotifications, notifications} from "@app/notifications"
|
import {allNotifications, notifications} from "@app/notifications"
|
||||||
import {pushModal} from "@app/modal"
|
import {pushModal} from "@app/modal"
|
||||||
|
|
@ -46,8 +45,8 @@
|
||||||
const cachedKinds: number[] = getJson(spaceKindsKey) ?? []
|
const cachedKinds: number[] = getJson(spaceKindsKey) ?? []
|
||||||
|
|
||||||
const spaceKinds = deriveDeduplicatedByValue(
|
const spaceKinds = deriveDeduplicatedByValue(
|
||||||
deriveEventsForUrl(url, [{kinds: CONTENT_KINDS}]),
|
$events.forUrl(url, [{kinds: CONTENT_KINDS}]).$,
|
||||||
$events => new Set([...cachedKinds, ...$events.map(e => e.kind)]),
|
$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.
|
// 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 ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||||
import ReportItem from "@app/components/ReportItem.svelte"
|
import ReportItem from "@app/components/ReportItem.svelte"
|
||||||
import RelayName from "@app/components/RelayName.svelte"
|
import RelayName from "@app/components/RelayName.svelte"
|
||||||
import {deriveEventsForUrl} from "@app/repository"
|
import {events} from "@app/core"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
url: string
|
url: string
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
const {url}: Props = $props()
|
const {url}: Props = $props()
|
||||||
|
|
||||||
const reports = deriveEventsForUrl(url, [{kinds: [REPORT]}])
|
const reports = $events.forUrl(url, [{kinds: [REPORT]}]).$
|
||||||
|
|
||||||
const back = () => history.back()
|
const back = () => history.back()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import {
|
||||||
BlossomServerLists,
|
BlossomServerLists,
|
||||||
Deletes,
|
Deletes,
|
||||||
Domain,
|
Domain,
|
||||||
|
Events,
|
||||||
FollowLists,
|
FollowLists,
|
||||||
Handles,
|
Handles,
|
||||||
Logger,
|
Logger,
|
||||||
|
|
@ -130,6 +131,7 @@ export const blockedRelayLists = usePlugin(BlockedRelayLists)
|
||||||
export const blossomServerLists = usePlugin(BlossomServerLists)
|
export const blossomServerLists = usePlugin(BlossomServerLists)
|
||||||
export const deletes = usePlugin(Deletes)
|
export const deletes = usePlugin(Deletes)
|
||||||
export const domain = usePlugin(Domain)
|
export const domain = usePlugin(Domain)
|
||||||
|
export const events = usePlugin(Events)
|
||||||
export const followLists = usePlugin(FollowLists)
|
export const followLists = usePlugin(FollowLists)
|
||||||
export const handles = usePlugin(Handles)
|
export const handles = usePlugin(Handles)
|
||||||
export const logger = usePlugin(Logger)
|
export const logger = usePlugin(Logger)
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@ import {derived} from "svelte/store"
|
||||||
import {APP_DATA, sortEventsDesc, tagSpec, tagValues} from "@welshman/util"
|
import {APP_DATA, sortEventsDesc, tagSpec, tagValues} from "@welshman/util"
|
||||||
import {AppData} from "@welshman/domain"
|
import {AppData} from "@welshman/domain"
|
||||||
import {Relays, publish} from "@welshman/app"
|
import {Relays, publish} from "@welshman/app"
|
||||||
import {command, fromApp, writer} from "@app/core"
|
import {command, events, fromApp, writer} from "@app/core"
|
||||||
import {deriveEventsForUrl} from "@app/repository"
|
|
||||||
import {toSpace} from "@app/rooms"
|
import {toSpace} from "@app/rooms"
|
||||||
|
|
||||||
// NIP-78 app data from the pubkey the space's NIP-11 names, one ["content", <value>] tag per entry.
|
// 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(
|
derived(
|
||||||
[
|
[
|
||||||
fromApp($app => $app.use(Relays).one(url)),
|
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]) => {
|
([$relay, $events]) => {
|
||||||
const [event] = sortEventsDesc($events.filter(e => e.pubkey === $relay?.pubkey))
|
const [event] = sortEventsDesc($events.filter(e => e.pubkey === $relay?.pubkey))
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import {
|
||||||
tagValues,
|
tagValues,
|
||||||
} from "@welshman/util"
|
} from "@welshman/util"
|
||||||
import {Comment, TimeEvent} from "@welshman/domain"
|
import {Comment, TimeEvent} from "@welshman/domain"
|
||||||
|
import {Events} from "@welshman/app"
|
||||||
import type {Maybe} from "@welshman/lib"
|
import type {Maybe} from "@welshman/lib"
|
||||||
import type {Filter, TrustedEvent} from "@welshman/util"
|
import type {Filter, TrustedEvent} from "@welshman/util"
|
||||||
import {mergeRepositoryUpdates} from "@welshman/net"
|
import {mergeRepositoryUpdates} from "@welshman/net"
|
||||||
|
|
@ -39,7 +40,6 @@ import type {ScrollerOpts} from "@lib/html"
|
||||||
import {daysBetween} from "@lib/util"
|
import {daysBetween} from "@lib/util"
|
||||||
import {EVENT_CONTEXT_KINDS, REACTION_KINDS} from "@app/content"
|
import {EVENT_CONTEXT_KINDS, REACTION_KINDS} from "@app/content"
|
||||||
import {app, network, reader} from "@app/core"
|
import {app, network, reader} from "@app/core"
|
||||||
import {getEventsForUrl} from "@app/repository"
|
|
||||||
|
|
||||||
const noEvents: TrustedEvent[] = []
|
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.
|
// What the repository already holds is an answer too, so a page of it renders before any relay replies.
|
||||||
const stored = relays.map(url =>
|
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)) {
|
if (stored.every(page => page.length > 0)) {
|
||||||
|
|
@ -712,7 +712,7 @@ export const makeCalendarFeed = ({
|
||||||
const events = writable(
|
const events = writable(
|
||||||
uniqBy(
|
uniqBy(
|
||||||
e => e.id,
|
e => e.id,
|
||||||
relays.flatMap(url => Array.from(getEventsForUrl(url, filters))),
|
relays.flatMap(url => app.get().use(Events).forUrl(url, filters).get()),
|
||||||
).sort(compareByStart),
|
).sort(compareByStart),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,7 @@ import {ago, MINUTE, now, simpleCache} from "@welshman/lib"
|
||||||
import {ROOM_CREATE_PERMISSION, hexTags, tagValues} from "@welshman/util"
|
import {ROOM_CREATE_PERMISSION, hexTags, tagValues} from "@welshman/util"
|
||||||
import {RelayManagement, Relays} from "@welshman/app"
|
import {RelayManagement, Relays} from "@welshman/app"
|
||||||
import type {IApp} from "@welshman/app"
|
import type {IApp} from "@welshman/app"
|
||||||
import {fromApp, usePlugin, user} from "@app/core"
|
import {events, fromApp, usePlugin, user} from "@app/core"
|
||||||
import {deriveEventsForUrl} from "@app/repository"
|
|
||||||
|
|
||||||
// `supportedmethods` answers for the pubkey that signed the request, so this catalog is the client's.
|
// `supportedmethods` answers for the pubkey that signed the request, so this catalog is the client's.
|
||||||
export const MANAGEMENT_METHOD_GROUPS = [
|
export const MANAGEMENT_METHOD_GROUPS = [
|
||||||
|
|
@ -221,7 +220,7 @@ export const deriveUserCanCreateRoom = (url: string) =>
|
||||||
derived(
|
derived(
|
||||||
[
|
[
|
||||||
user,
|
user,
|
||||||
deriveEventsForUrl(url, [{kinds: [ROOM_CREATE_PERMISSION]}]),
|
events.get().forUrl(url, [{kinds: [ROOM_CREATE_PERMISSION]}]).$,
|
||||||
deriveUserIsSpaceStaff(url),
|
deriveUserIsSpaceStaff(url),
|
||||||
],
|
],
|
||||||
([$user, $events, $isStaff]) =>
|
([$user, $events, $isStaff]) =>
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,7 @@ import {
|
||||||
} from "@welshman/util"
|
} from "@welshman/util"
|
||||||
import {Comment} from "@welshman/domain"
|
import {Comment} from "@welshman/domain"
|
||||||
import {synced, throttled, withGetter} from "@welshman/store"
|
import {synced, throttled, withGetter} from "@welshman/store"
|
||||||
import {Relays, RoomLists} from "@welshman/app"
|
import {Events, Relays, RoomLists} from "@welshman/app"
|
||||||
import {deriveEventsByIdByUrl} from "@app/repository"
|
|
||||||
import {app, fromApp, reader} from "@app/core"
|
import {app, fromApp, reader} from "@app/core"
|
||||||
import {makeRoomPath, makeSpaceChatPath, makeChatPath, makeContentPath} from "@app/routes"
|
import {makeRoomPath, makeSpaceChatPath, makeChatPath, makeContentPath} from "@app/routes"
|
||||||
import {CONTENT_KINDS, makeCommentFilter} from "@app/content"
|
import {CONTENT_KINDS, makeCommentFilter} from "@app/content"
|
||||||
|
|
@ -236,10 +235,13 @@ export const latestActivityByPath = derived(
|
||||||
chatsById,
|
chatsById,
|
||||||
fromApp($app => $app.use(Relays).index.$),
|
fromApp($app => $app.use(Relays).index.$),
|
||||||
fromApp($app => $app.use(RoomLists).index.$),
|
fromApp($app => $app.use(RoomLists).index.$),
|
||||||
deriveEventsByIdByUrl([
|
fromApp(
|
||||||
{kinds: [MESSAGE, ...CONTENT_KINDS]},
|
$app =>
|
||||||
makeCommentFilter(CONTENT_KINDS),
|
$app
|
||||||
]),
|
.use(Events)
|
||||||
|
.byIdByUrl([{kinds: [MESSAGE, ...CONTENT_KINDS]}, makeCommentFilter(CONTENT_KINDS)])
|
||||||
|
.$,
|
||||||
|
),
|
||||||
userSettingsValues,
|
userSettingsValues,
|
||||||
],
|
],
|
||||||
identity,
|
identity,
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@ import {derived} from "svelte/store"
|
||||||
import type {Readable} from "svelte/store"
|
import type {Readable} from "svelte/store"
|
||||||
import {getIdFilters, outbox} from "@welshman/util"
|
import {getIdFilters, outbox} from "@welshman/util"
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import {network, pinLists, router} from "@app/core"
|
import {events, network, pinLists, router} from "@app/core"
|
||||||
import {deriveEvents} from "@app/repository"
|
|
||||||
|
|
||||||
export const derivePinnedEvents = (pubkey: string): Readable<TrustedEvent[]> =>
|
export const derivePinnedEvents = (pubkey: string): Readable<TrustedEvent[]> =>
|
||||||
derived(
|
derived(
|
||||||
|
|
@ -22,7 +21,7 @@ export const derivePinnedEvents = (pubkey: string): Readable<TrustedEvent[]> =>
|
||||||
network.get().loadLenient({relays: $relays, filters, signal: controller.signal}),
|
network.get().loadLenient({relays: $relays, filters, signal: controller.signal}),
|
||||||
)
|
)
|
||||||
|
|
||||||
const unsubscribe = deriveEvents(filters).subscribe(set)
|
const unsubscribe = events.get().desc(filters).$.subscribe(set)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
controller.abort()
|
controller.abort()
|
||||||
|
|
|
||||||
|
|
@ -3,61 +3,8 @@ import type {Unsubscriber} from "svelte/store"
|
||||||
import {first, on} from "@welshman/lib"
|
import {first, on} from "@welshman/lib"
|
||||||
import type {Maybe} from "@welshman/lib"
|
import type {Maybe} from "@welshman/lib"
|
||||||
import {sortEventsDesc} from "@welshman/util"
|
import {sortEventsDesc} from "@welshman/util"
|
||||||
import type {Filter, TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import * as store from "@welshman/store"
|
import {app} from "@app/core"
|
||||||
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}),
|
|
||||||
)
|
|
||||||
|
|
||||||
// The most recent event held from one author.
|
// 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 type {Readable} from "svelte/store"
|
||||||
import {getIdFilters, getIdOrAddress} from "@welshman/util"
|
import {getIdFilters, getIdOrAddress} from "@welshman/util"
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import {network, roomPinLists} from "@app/core"
|
import {events, network, roomPinLists} from "@app/core"
|
||||||
import {deriveEventsForUrl} from "@app/repository"
|
|
||||||
|
|
||||||
export const deriveRoomPinnedEvents = (url: string, h: string): Readable<TrustedEvent[]> =>
|
export const deriveRoomPinnedEvents = (url: string, h: string): Readable<TrustedEvent[]> =>
|
||||||
readable<TrustedEvent[]>([], set => {
|
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})
|
network.get().loadLenient({relays: [url], filters, signal: controller.signal})
|
||||||
|
|
||||||
return deriveEventsForUrl(url, filters).subscribe($events => {
|
return events
|
||||||
const byPin = new Map(
|
.get()
|
||||||
$events.flatMap(event => [
|
.forUrl(url, filters)
|
||||||
[event.id, event],
|
.$.subscribe($events => {
|
||||||
[getIdOrAddress(event), event],
|
const byPin = new Map(
|
||||||
]),
|
$events.flatMap(event => [
|
||||||
)
|
[event.id, event],
|
||||||
|
[getIdOrAddress(event), event],
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
|
||||||
setEvents(
|
setEvents(
|
||||||
$pins.flatMap(pin => {
|
$pins.flatMap(pin => {
|
||||||
const event = byPin.get(pin)
|
const event = byPin.get(pin)
|
||||||
|
|
||||||
return event ? [event] : []
|
return event ? [event] : []
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
).subscribe(set)
|
).subscribe(set)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@
|
||||||
import EventComments from "@app/components/EventComments.svelte"
|
import EventComments from "@app/components/EventComments.svelte"
|
||||||
import EventMenu from "@app/components/EventMenu.svelte"
|
import EventMenu from "@app/components/EventMenu.svelte"
|
||||||
import ReadingProgress from "@app/components/ReadingProgress.svelte"
|
import ReadingProgress from "@app/components/ReadingProgress.svelte"
|
||||||
import {reader} from "@app/core"
|
import {events, reader} from "@app/core"
|
||||||
import {deriveEvent} from "@app/repository"
|
|
||||||
import {makeFeedContext} from "@app/feeds"
|
import {makeFeedContext} from "@app/feeds"
|
||||||
import {decodeRelay} from "@app/relays"
|
import {decodeRelay} from "@app/relays"
|
||||||
import {displayReadingTime} from "@app/articles"
|
import {displayReadingTime} from "@app/articles"
|
||||||
|
|
@ -29,7 +28,7 @@
|
||||||
const {relay, address} = params
|
const {relay, address} = params
|
||||||
const url = decodeRelay(relay)
|
const url = decodeRelay(relay)
|
||||||
const context = makeFeedContext({relays: [url]})
|
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 article = derived(event, $event => ($event ? reader(Article)($event) : undefined))
|
||||||
const h = $derived($article?.room())
|
const h = $derived($article?.room())
|
||||||
const topics = $derived(uniq($article?.topics() ?? []))
|
const topics = $derived(uniq($article?.topics() ?? []))
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,7 @@
|
||||||
import CalendarEventPeople from "@app/components/CalendarEventPeople.svelte"
|
import CalendarEventPeople from "@app/components/CalendarEventPeople.svelte"
|
||||||
import CalendarRsvp from "@app/components/CalendarRsvp.svelte"
|
import CalendarRsvp from "@app/components/CalendarRsvp.svelte"
|
||||||
import {deriveRsvps, getRsvpsByStatus, makeRsvpFilter} from "@app/calendar"
|
import {deriveRsvps, getRsvpsByStatus, makeRsvpFilter} from "@app/calendar"
|
||||||
import {network, reader} from "@app/core"
|
import {events, network, reader} from "@app/core"
|
||||||
import {deriveEvent, deriveEvents} from "@app/repository"
|
|
||||||
import {makeFeedContext} from "@app/feeds"
|
import {makeFeedContext} from "@app/feeds"
|
||||||
import {decodeRelay} from "@app/relays"
|
import {decodeRelay} from "@app/relays"
|
||||||
import type {PageProps} from "./$types"
|
import type {PageProps} from "./$types"
|
||||||
|
|
@ -34,10 +33,10 @@
|
||||||
const {relay, address} = params
|
const {relay, address} = params
|
||||||
const url = decodeRelay(relay)
|
const url = decodeRelay(relay)
|
||||||
const context = makeFeedContext({relays: [url]})
|
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 timeEvent = derived(event, $event => ($event ? reader(TimeEvent)($event) : undefined))
|
||||||
const filters = $derived($event ? getCommentFiltersForRoot([$event]) : [])
|
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 rsvps = $derived($event ? deriveRsvps($event) : readable<TrustedEvent[]>([]))
|
||||||
const people = $derived(getRsvpsByStatus($rsvps))
|
const people = $derived(getRsvpsByStatus($rsvps))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,7 @@
|
||||||
import NoteCard from "@app/components/NoteCard.svelte"
|
import NoteCard from "@app/components/NoteCard.svelte"
|
||||||
import ClassifiedActions from "@app/components/ClassifiedActions.svelte"
|
import ClassifiedActions from "@app/components/ClassifiedActions.svelte"
|
||||||
import EventComments from "@app/components/EventComments.svelte"
|
import EventComments from "@app/components/EventComments.svelte"
|
||||||
import {reader} from "@app/core"
|
import {events, reader} from "@app/core"
|
||||||
import {deriveEvent} from "@app/repository"
|
|
||||||
import {makeFeedContext} from "@app/feeds"
|
import {makeFeedContext} from "@app/feeds"
|
||||||
import {decodeRelay} from "@app/relays"
|
import {decodeRelay} from "@app/relays"
|
||||||
import type {PageProps} from "./$types"
|
import type {PageProps} from "./$types"
|
||||||
|
|
@ -21,7 +20,7 @@
|
||||||
const {relay, address} = params
|
const {relay, address} = params
|
||||||
const url = decodeRelay(relay)
|
const url = decodeRelay(relay)
|
||||||
const context = makeFeedContext({relays: [url]})
|
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 classified = derived(event, $event => ($event ? reader(Classified)($event) : undefined))
|
||||||
|
|
||||||
const back = () => history.back()
|
const back = () => history.back()
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,9 @@
|
||||||
import GoalStatus from "@app/components/GoalStatus.svelte"
|
import GoalStatus from "@app/components/GoalStatus.svelte"
|
||||||
import GoalSupporters from "@app/components/GoalSupporters.svelte"
|
import GoalSupporters from "@app/components/GoalSupporters.svelte"
|
||||||
import EventComments from "@app/components/EventComments.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 {ENABLE_ZAPS} from "@app/env"
|
||||||
import {deriveGoalProgress} from "@app/goals"
|
import {deriveGoalProgress} from "@app/goals"
|
||||||
import {deriveEvent} from "@app/repository"
|
|
||||||
import {makeFeedContext} from "@app/feeds"
|
import {makeFeedContext} from "@app/feeds"
|
||||||
import {decodeRelay} from "@app/relays"
|
import {decodeRelay} from "@app/relays"
|
||||||
import type {PageProps} from "./$types"
|
import type {PageProps} from "./$types"
|
||||||
|
|
@ -31,7 +30,7 @@
|
||||||
const {relay, id} = params
|
const {relay, id} = params
|
||||||
const url = decodeRelay(relay)
|
const url = decodeRelay(relay)
|
||||||
const context = makeFeedContext({relays: [url]})
|
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 goal = derived(event, $event => ($event ? reader(ZapGoal)($event) : undefined))
|
||||||
const progress = $derived($event ? deriveGoalProgress($event, url) : undefined)
|
const progress = $derived($event ? deriveGoalProgress($event, url) : undefined)
|
||||||
const remaining = $derived($progress ? Math.max(0, $progress.target - $progress.raised) : 0)
|
const remaining = $derived($progress ? Math.max(0, $progress.target - $progress.raised) : 0)
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,8 @@
|
||||||
import PinAdd from "@app/components/PinAdd.svelte"
|
import PinAdd from "@app/components/PinAdd.svelte"
|
||||||
import PinboardItem from "@app/components/PinboardItem.svelte"
|
import PinboardItem from "@app/components/PinboardItem.svelte"
|
||||||
import PinboardEdit from "@app/components/PinboardEdit.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 {decodeRelay} from "@app/relays"
|
||||||
import {deriveEventsForUrl} from "@app/repository"
|
|
||||||
import {makeLibraryPath} from "@app/routes"
|
import {makeLibraryPath} from "@app/routes"
|
||||||
import {pushModal} from "@app/modal"
|
import {pushModal} from "@app/modal"
|
||||||
import type {PageProps} from "./$types"
|
import type {PageProps} from "./$types"
|
||||||
|
|
@ -36,8 +35,8 @@
|
||||||
let loading = $state(true)
|
let loading = $state(true)
|
||||||
|
|
||||||
// A shelf belongs to the space it was published to rather than to the pubkey that signed it.
|
// 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 =>
|
const boards = derived($events.forUrl(url, [{kinds: [PINBOARD]}]).$, $pinboards =>
|
||||||
$events.map(reader(Pinboard)),
|
$pinboards.map(reader(Pinboard)),
|
||||||
)
|
)
|
||||||
|
|
||||||
const address = $derived($page.url.searchParams.get("board") ?? "")
|
const address = $derived($page.url.searchParams.get("board") ?? "")
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
import {onDestroy, onMount} from "svelte"
|
import {onDestroy, onMount} from "svelte"
|
||||||
import {sleep} from "@welshman/lib"
|
import {sleep} from "@welshman/lib"
|
||||||
import {POLL, POLL_RESPONSE, getCommentFiltersForRoot} from "@welshman/util"
|
import {POLL, POLL_RESPONSE, getCommentFiltersForRoot} from "@welshman/util"
|
||||||
import {deriveEventsAsc} from "@welshman/store"
|
|
||||||
import SortVertical from "@assets/icons/sort-vertical.svg?dataurl"
|
import SortVertical from "@assets/icons/sort-vertical.svg?dataurl"
|
||||||
import Icon from "@lib/components/Icon.svelte"
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
import PageContent from "@lib/components/PageContent.svelte"
|
import PageContent from "@lib/components/PageContent.svelte"
|
||||||
|
|
@ -13,8 +12,7 @@
|
||||||
import NoteContent from "@app/components/NoteContent.svelte"
|
import NoteContent from "@app/components/NoteContent.svelte"
|
||||||
import CommentActions from "@app/components/CommentActions.svelte"
|
import CommentActions from "@app/components/CommentActions.svelte"
|
||||||
import EventReply from "@app/components/EventReply.svelte"
|
import EventReply from "@app/components/EventReply.svelte"
|
||||||
import {network} from "@app/core"
|
import {events, network} from "@app/core"
|
||||||
import {deriveEvent, deriveEventsById} from "@app/repository"
|
|
||||||
import {makeFeedContext} from "@app/feeds"
|
import {makeFeedContext} from "@app/feeds"
|
||||||
import {decodeRelay} from "@app/relays"
|
import {decodeRelay} from "@app/relays"
|
||||||
import type {PageProps} from "./$types"
|
import type {PageProps} from "./$types"
|
||||||
|
|
@ -24,9 +22,9 @@
|
||||||
const {relay, id} = params
|
const {relay, id} = params
|
||||||
const url = decodeRelay(relay)
|
const url = decodeRelay(relay)
|
||||||
const context = makeFeedContext({relays: [url]})
|
const context = makeFeedContext({relays: [url]})
|
||||||
const event = deriveEvent(id, [url])
|
const event = $events.one(id, [url]).$
|
||||||
const filters = $derived($event ? getCommentFiltersForRoot([$event]) : [])
|
const filters = $derived($event ? getCommentFiltersForRoot([$event]) : [])
|
||||||
const comments = $derived(deriveEventsAsc(deriveEventsById(filters)))
|
const comments = $derived($events.asc(filters).$)
|
||||||
|
|
||||||
const back = () => history.back()
|
const back = () => history.back()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
import {page} from "$app/state"
|
import {page} from "$app/state"
|
||||||
import {sleep, spec} from "@welshman/lib"
|
import {sleep, spec} from "@welshman/lib"
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import {deriveEventsAsc} from "@welshman/store"
|
|
||||||
import {getCommentFiltersForRoot} from "@welshman/util"
|
import {getCommentFiltersForRoot} from "@welshman/util"
|
||||||
import Reply from "@assets/icons/reply-2.svg?dataurl"
|
import Reply from "@assets/icons/reply-2.svg?dataurl"
|
||||||
import AltArrowDown from "@assets/icons/alt-arrow-down.svg?dataurl"
|
import AltArrowDown from "@assets/icons/alt-arrow-down.svg?dataurl"
|
||||||
|
|
@ -15,8 +14,7 @@
|
||||||
import ThreadPost from "@app/components/ThreadPost.svelte"
|
import ThreadPost from "@app/components/ThreadPost.svelte"
|
||||||
import ThreadSummaryBar from "@app/components/ThreadSummaryBar.svelte"
|
import ThreadSummaryBar from "@app/components/ThreadSummaryBar.svelte"
|
||||||
import EventReply from "@app/components/EventReply.svelte"
|
import EventReply from "@app/components/EventReply.svelte"
|
||||||
import {deriveEvent, deriveEventsById} from "@app/repository"
|
import {events, network} from "@app/core"
|
||||||
import {network} from "@app/core"
|
|
||||||
import {makeFeedContext} from "@app/feeds"
|
import {makeFeedContext} from "@app/feeds"
|
||||||
import {getChecked} from "@app/notifications"
|
import {getChecked} from "@app/notifications"
|
||||||
import {decodeRelay} from "@app/relays"
|
import {decodeRelay} from "@app/relays"
|
||||||
|
|
@ -29,11 +27,11 @@
|
||||||
|
|
||||||
const {relay, id} = params
|
const {relay, id} = params
|
||||||
const url = decodeRelay(relay)
|
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
|
// Rows register themselves with `related`, so the whole page's reactions load in one batch
|
||||||
const context = makeFeedContext({relays: [url]})
|
const context = makeFeedContext({relays: [url]})
|
||||||
const filters = $derived($event ? getCommentFiltersForRoot([$event]) : [])
|
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"})
|
const scrollToTop = () => element?.scrollTo({top: 0, behavior: "smooth"})
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue