mirror of
https://github.com/coracle-social/flotilla.git
synced 2025-12-10 02:47:06 +00:00
Switch to pnpm, use new welshman stuff
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
npm run lint
|
||||
npm run check
|
||||
pnpm run lint
|
||||
pnpm run check
|
||||
|
||||
10
README.md
10
README.md
@@ -8,8 +8,8 @@ If you would like to be interoperable with Flotilla, please check out this draft
|
||||
|
||||
To run your own Flotilla, it's as simple as:
|
||||
|
||||
- `npm install`
|
||||
- `npm run build`
|
||||
- `pnpm install`
|
||||
- `pnpm run build`
|
||||
- `npx serve build`
|
||||
|
||||
## Environment
|
||||
@@ -65,12 +65,12 @@ git clone https://github.com/coracle-social/flotilla.git
|
||||
cd ~/flotilla
|
||||
nvm install
|
||||
nvm use
|
||||
npm i
|
||||
pnpm i
|
||||
|
||||
# Optionally create and populate .env.local to suit your use case
|
||||
|
||||
# Build the app
|
||||
NODE_OPTIONS=--max_old_space_size=16384 npm run build
|
||||
NODE_OPTIONS=--max_old_space_size=16384 pnpm run build
|
||||
|
||||
# Exit back to root
|
||||
exit
|
||||
@@ -108,4 +108,4 @@ Now, visit your domain. You should be all set up!
|
||||
|
||||
# Development
|
||||
|
||||
Run `npm run dev` to get a dev server, and `npm run check:watch` to watch for typescript errors. When you're ready to commit, run `npm run format && npm run lint` and fix any errors that come up.
|
||||
Run `pnpm run dev` to get a dev server, and `pnpm run check:watch` to watch for typescript errors. When you're ready to commit, run `pnpm run format && pnpm run lint` and fix any errors that come up.
|
||||
|
||||
15449
package-lock.json
generated
15449
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
36
package.json
36
package.json
@@ -51,16 +51,17 @@
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@vite-pwa/assets-generator": "^0.2.6",
|
||||
"@vite-pwa/sveltekit": "^0.6.6",
|
||||
"@welshman/app": "^0.0.44",
|
||||
"@welshman/content": "^0.1.1",
|
||||
"@welshman/dvm": "^0.0.15",
|
||||
"@welshman/editor": "^0.1.0",
|
||||
"@welshman/feeds": "^0.1.0",
|
||||
"@welshman/lib": "^0.1.0",
|
||||
"@welshman/net": "^0.0.49",
|
||||
"@welshman/signer": "^0.1.1",
|
||||
"@welshman/store": "^0.1.0",
|
||||
"@welshman/util": "^0.1.0",
|
||||
"@welshman/app": "^0.1.2",
|
||||
"@welshman/content": "^0.1.3",
|
||||
"@welshman/dvm": "^0.1.2",
|
||||
"@welshman/editor": "^0.1.2",
|
||||
"@welshman/feeds": "^0.1.2",
|
||||
"@welshman/lib": "^0.1.2",
|
||||
"@welshman/net": "^0.1.2",
|
||||
"@welshman/relay": "^0.1.2",
|
||||
"@welshman/signer": "^0.1.4",
|
||||
"@welshman/store": "^0.1.3",
|
||||
"@welshman/util": "^0.1.3",
|
||||
"daisyui": "^4.12.10",
|
||||
"date-picker-svelte": "^2.13.0",
|
||||
"dotenv": "^16.4.5",
|
||||
@@ -72,5 +73,20 @@
|
||||
"nostr-tools": "^2.7.2",
|
||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||
"qrcode": "^1.5.4"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"@welshman/lib": "link:../welshman/packages/lib",
|
||||
"@welshman/util": "link:../welshman/packages/util",
|
||||
"@welshman/app": "link:../welshman/packages/app",
|
||||
"@welshman/content": "link:../welshman/packages/content",
|
||||
"@welshman/dvm": "link:../welshman/packages/dvm",
|
||||
"@welshman/feeds": "link:../welshman/packages/feeds",
|
||||
"@welshman/net": "link:../welshman/packages/net",
|
||||
"@welshman/relay": "link:../welshman/packages/relay",
|
||||
"@welshman/signer": "link:../welshman/packages/signer",
|
||||
"@welshman/store": "link:../welshman/packages/store",
|
||||
"@welshman/editor": "link:../welshman/packages/editor"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
pnpm-lock.yaml
generated
Normal file
BIN
pnpm-lock.yaml
generated
Normal file
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
import * as nip19 from "nostr-tools/nip19"
|
||||
import {get} from "svelte/store"
|
||||
import {ctx, randomId, uniq, equals} from "@welshman/lib"
|
||||
import {randomId, poll, uniq, equals} from "@welshman/lib"
|
||||
import {
|
||||
DELETE,
|
||||
REPORT,
|
||||
@@ -31,7 +31,7 @@ import {
|
||||
unionFilters,
|
||||
} from "@welshman/util"
|
||||
import type {TrustedEvent, Filter, EventContent, EventTemplate} from "@welshman/util"
|
||||
import {PublishStatus, AuthStatus, SocketStatus} from "@welshman/net"
|
||||
import {Pool, PublishStatus, AuthStatus, SocketStatus} from "@welshman/net"
|
||||
import {Nip59, makeSecret, stamp, Nip46Broker} from "@welshman/signer"
|
||||
import {
|
||||
pubkey,
|
||||
@@ -54,6 +54,7 @@ import {
|
||||
dropSession,
|
||||
tagEventForComment,
|
||||
tagEventForQuote,
|
||||
Router,
|
||||
} from "@welshman/app"
|
||||
import type {Thunk} from "@welshman/app"
|
||||
import {
|
||||
@@ -101,7 +102,7 @@ export const prependParent = (parent: TrustedEvent | undefined, {content, tags}:
|
||||
id: parent.id,
|
||||
kind: parent.kind,
|
||||
author: parent.pubkey,
|
||||
relays: ctx.app.router.Event(parent).limit(3).getUrls(),
|
||||
relays: Router.get().Event(parent).limit(3).getUrls(),
|
||||
})
|
||||
|
||||
tags = [...tags, tagEventForQuote(parent)]
|
||||
@@ -203,7 +204,7 @@ export const nip29 = {
|
||||
export const addSpaceMembership = async (url: string) => {
|
||||
const list = get(userMembership) || makeList({kind: GROUPS})
|
||||
const event = await addToListPublicly(list, ["r", url]).reconcile(nip44EncryptToSelf)
|
||||
const relays = uniq([...ctx.app.router.FromUser().getUrls(), ...getRelayTagValues(event.tags)])
|
||||
const relays = uniq([...Router.get().FromUser().getUrls(), ...getRelayTagValues(event.tags)])
|
||||
|
||||
return publishThunk({event, relays})
|
||||
}
|
||||
@@ -212,11 +213,7 @@ export const removeSpaceMembership = async (url: string) => {
|
||||
const list = get(userMembership) || makeList({kind: GROUPS})
|
||||
const pred = (t: string[]) => t[t[0] === "r" ? 1 : 2] === url
|
||||
const event = await removeFromListByPredicate(list, pred).reconcile(nip44EncryptToSelf)
|
||||
const relays = uniq([
|
||||
url,
|
||||
...ctx.app.router.FromUser().getUrls(),
|
||||
...getRelayTagValues(event.tags),
|
||||
])
|
||||
const relays = uniq([url, ...Router.get().FromUser().getUrls(), ...getRelayTagValues(event.tags)])
|
||||
|
||||
return publishThunk({event, relays})
|
||||
}
|
||||
@@ -228,7 +225,7 @@ export const addRoomMembership = async (url: string, room: string, name: string)
|
||||
["group", room, url, name],
|
||||
]
|
||||
const event = await addToListPublicly(list, ...newTags).reconcile(nip44EncryptToSelf)
|
||||
const relays = uniq([...ctx.app.router.FromUser().getUrls(), ...getRelayTagValues(event.tags)])
|
||||
const relays = uniq([...Router.get().FromUser().getUrls(), ...getRelayTagValues(event.tags)])
|
||||
|
||||
return publishThunk({event, relays})
|
||||
}
|
||||
@@ -237,11 +234,7 @@ export const removeRoomMembership = async (url: string, room: string) => {
|
||||
const list = get(userMembership) || makeList({kind: GROUPS})
|
||||
const pred = (t: string[]) => equals(["group", room, url], t.slice(0, 3))
|
||||
const event = await removeFromListByPredicate(list, pred).reconcile(nip44EncryptToSelf)
|
||||
const relays = uniq([
|
||||
url,
|
||||
...ctx.app.router.FromUser().getUrls(),
|
||||
...getRelayTagValues(event.tags),
|
||||
])
|
||||
const relays = uniq([url, ...Router.get().FromUser().getUrls(), ...getRelayTagValues(event.tags)])
|
||||
|
||||
return publishThunk({event, relays})
|
||||
}
|
||||
@@ -263,7 +256,7 @@ export const setRelayPolicy = (url: string, read: boolean, write: boolean) => {
|
||||
relays: [
|
||||
url,
|
||||
...INDEXER_RELAYS,
|
||||
...ctx.app.router.FromUser().getUrls(),
|
||||
...Router.get().FromUser().getUrls(),
|
||||
...userRoomsByUrl.get().keys(),
|
||||
],
|
||||
})
|
||||
@@ -284,7 +277,7 @@ export const setInboxRelayPolicy = (url: string, enabled: boolean) => {
|
||||
event: createEvent(list.kind, {tags}),
|
||||
relays: [
|
||||
...INDEXER_RELAYS,
|
||||
...ctx.app.router.FromUser().getUrls(),
|
||||
...Router.get().FromUser().getUrls(),
|
||||
...userRoomsByUrl.get().keys(),
|
||||
],
|
||||
})
|
||||
@@ -294,9 +287,9 @@ export const setInboxRelayPolicy = (url: string, enabled: boolean) => {
|
||||
// Relay access
|
||||
|
||||
export const checkRelayAccess = async (url: string, claim = "") => {
|
||||
const connection = ctx.net.pool.get(url)
|
||||
const socket = Pool.getSingleton().get(url)
|
||||
|
||||
await connection.auth.attempt(5000)
|
||||
await socket.auth.attemptAuth(signer.get().sign)
|
||||
|
||||
const thunk = publishThunk({
|
||||
event: createEvent(AUTH_JOIN, {tags: [["claim", claim]]}),
|
||||
@@ -307,7 +300,7 @@ export const checkRelayAccess = async (url: string, claim = "") => {
|
||||
|
||||
if (result[url].status === PublishStatus.Failure) {
|
||||
const message =
|
||||
connection.auth.message?.replace(/^.*: /, "") ||
|
||||
socket.auth.details?.replace(/^.*: /, "") ||
|
||||
result[url].message?.replace(/^.*: /, "") ||
|
||||
"join request rejected"
|
||||
|
||||
@@ -328,26 +321,30 @@ export const checkRelayProfile = async (url: string) => {
|
||||
}
|
||||
|
||||
export const checkRelayConnection = async (url: string) => {
|
||||
const connection = ctx.net.pool.get(url)
|
||||
const socket = Pool.getSingleton().get(url)
|
||||
|
||||
await connection.socket.open()
|
||||
await connection.socket.wait(3000)
|
||||
socket.attemptToOpen()
|
||||
|
||||
if (connection.socket.status !== SocketStatus.Open) {
|
||||
await poll({
|
||||
signal: AbortSignal.timeout(3000),
|
||||
condition: () => socket.status === SocketStatus.Open,
|
||||
})
|
||||
|
||||
if (socket.status !== SocketStatus.Open) {
|
||||
return `Failed to connect`
|
||||
}
|
||||
}
|
||||
|
||||
export const checkRelayAuth = async (url: string, timeout = 3000) => {
|
||||
const connection = ctx.net.pool.get(url)
|
||||
const socket = Pool.getSingleton().get(url)
|
||||
const okStatuses = [AuthStatus.None, AuthStatus.Ok]
|
||||
|
||||
await connection.auth.attempt(timeout)
|
||||
await socket.auth.attemptAuth(signer.get().sign)
|
||||
|
||||
// Only raise an error if it's not a timeout.
|
||||
// If it is, odds are the problem is with our signer, not the relay
|
||||
if (!okStatuses.includes(connection.auth.status) && connection.auth.message) {
|
||||
return `Failed to authenticate (${connection.auth.message})`
|
||||
if (!okStatuses.includes(socket.auth.status) && socket.auth.details) {
|
||||
return `Failed to authenticate (${socket.auth.details})`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,7 +381,7 @@ export const sendWrapped = async ({
|
||||
await Promise.all(
|
||||
uniq(pubkeys).map(async recipient => ({
|
||||
event: await nip59.wrap(recipient, stamp(template)),
|
||||
relays: ctx.app.router.PubkeyInbox(recipient).getUrls(),
|
||||
relays: Router.get().PubkeyInbox(recipient).getUrls(),
|
||||
delay,
|
||||
})),
|
||||
),
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
import type {Snippet} from "svelte"
|
||||
import {onMount} from "svelte"
|
||||
import {int, nthNe, MINUTE, sortBy, remove} from "@welshman/lib"
|
||||
import {load} from "@welshman/net"
|
||||
import type {TrustedEvent, EventContent} from "@welshman/util"
|
||||
import {createEvent, DIRECT_MESSAGE, INBOX_RELAYS} from "@welshman/util"
|
||||
import {
|
||||
pubkey,
|
||||
Router,
|
||||
tagPubkey,
|
||||
formatTimestampAsDate,
|
||||
inboxRelaySelectionsByPubkey,
|
||||
load,
|
||||
} from "@welshman/app"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
@@ -106,7 +107,10 @@
|
||||
|
||||
onMount(() => {
|
||||
// Don't use loadInboxRelaySelection because we want to force reload
|
||||
load({filters: [{kinds: [INBOX_RELAYS], authors: others}]})
|
||||
load({
|
||||
relays: Router.get().FromPubkeys(others).getUrls(),
|
||||
filters: [{kinds: [INBOX_RELAYS], authors: others}],
|
||||
})
|
||||
|
||||
const observer = new ResizeObserver(() => {
|
||||
dynamicPadding!.style.minHeight = `${chatCompose!.offsetHeight}px`
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import {nip19} from "nostr-tools"
|
||||
import * as nip19 from "nostr-tools/nip19"
|
||||
import {goto} from "$app/navigation"
|
||||
import {ctx, nthEq} from "@welshman/lib"
|
||||
import {tracker, repository} from "@welshman/app"
|
||||
import {nthEq} from "@welshman/lib"
|
||||
import {Router, tracker, repository} from "@welshman/app"
|
||||
import {Address, DIRECT_MESSAGE, MESSAGE, THREAD, EVENT_TIME} from "@welshman/util"
|
||||
import {scrollToEvent} from "@lib/html"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
@@ -16,10 +16,7 @@
|
||||
|
||||
const {id, identifier, kind, pubkey, relays: relayHints = []} = value
|
||||
const idOrAddress = id || new Address(kind, pubkey, identifier).toString()
|
||||
const mergedRelays = [
|
||||
...relays,
|
||||
...ctx.app.router.Quote(event, idOrAddress, relayHints).getUrls(),
|
||||
]
|
||||
const mergedRelays = [...relays, ...Router.get().Quote(event, idOrAddress, relayHints).getUrls()]
|
||||
const quote = deriveEvent(idOrAddress, mergedRelays)
|
||||
const entity = id
|
||||
? nip19.neventEncode({id, relays: mergedRelays})
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
import {onMount} from "svelte"
|
||||
import {max} from "@welshman/lib"
|
||||
import {COMMENT} from "@welshman/util"
|
||||
import {load} from "@welshman/net"
|
||||
import {deriveEvents} from "@welshman/store"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {formatTimestampRelative, repository, load} from "@welshman/app"
|
||||
import {formatTimestampRelative, repository} from "@welshman/app"
|
||||
import {notifications} from "@app/notifications"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {nip19} from "nostr-tools"
|
||||
import {ctx} from "@welshman/lib"
|
||||
import * as nip19 from "nostr-tools/nip19"
|
||||
import {Router} from "@welshman/app"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import FieldInline from "@lib/components/FieldInline.svelte"
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
const {url, event}: Props = $props()
|
||||
|
||||
const relays = url ? [url] : ctx.app.router.Event(event).getUrls()
|
||||
const relays = url ? [url] : Router.get().Event(event).getUrls()
|
||||
const nevent1 = nip19.neventEncode({...event, relays})
|
||||
const npub1 = nip19.npubEncode(event.pubkey)
|
||||
const json = JSON.stringify(event, null, 2)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
const signUp = () => pushModal(SignUp)
|
||||
|
||||
const onSuccess = async (session: Session, relays: string[] = []) => {
|
||||
await loadUserData(session.pubkey, {relays})
|
||||
await loadUserData(session.pubkey, relays)
|
||||
|
||||
addSession(session)
|
||||
pushToast({message: "Successfully logged in!"})
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import type {Snippet} from "svelte"
|
||||
import {nip19} from "nostr-tools"
|
||||
import {ctx} from "@welshman/lib"
|
||||
import * as nip19 from "nostr-tools/nip19"
|
||||
import {getListTags, getPubkeyTagValues} from "@welshman/util"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {formatTimestamp, userMutes} from "@welshman/app"
|
||||
import {formatTimestamp, Router, userMutes} from "@welshman/app"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
@@ -27,7 +26,7 @@
|
||||
class?: string
|
||||
} = $props()
|
||||
|
||||
const relays = ctx.app.router.Event(event).getUrls()
|
||||
const relays = Router.get().Event(event).getUrls()
|
||||
const nevent = nip19.neventEncode({id: event.id, relays})
|
||||
|
||||
const ignoreMute = () => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte"
|
||||
import {ctx} from "@welshman/lib"
|
||||
import type {Filter} from "@welshman/util"
|
||||
import {deriveEvents} from "@welshman/store"
|
||||
import {repository, load, loadRelaySelections, formatTimestampRelative} from "@welshman/app"
|
||||
import {load} from "@welshman/net"
|
||||
import {Router, repository, loadRelaySelections, formatTimestampRelative} from "@welshman/app"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import Profile from "@app/components/Profile.svelte"
|
||||
@@ -22,7 +22,7 @@
|
||||
// Load at least one note, regardless of time frame
|
||||
load({
|
||||
filters: [{authors: [pubkey], limit: 1}],
|
||||
relays: ctx.app.router.FromPubkeys([pubkey]).getUrls(),
|
||||
relays: Router.get().FromPubkeys([pubkey]).getUrls(),
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
import {ctx} from "@welshman/lib"
|
||||
import type {Profile} from "@welshman/util"
|
||||
import {
|
||||
createEvent,
|
||||
@@ -8,7 +7,7 @@
|
||||
createProfile,
|
||||
isPublishedProfile,
|
||||
} from "@welshman/util"
|
||||
import {pubkey, profilesByPubkey, publishThunk} from "@welshman/app"
|
||||
import {Router, pubkey, profilesByPubkey, publishThunk} from "@welshman/app"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import ProfileEditForm from "@app/components/ProfileEditForm.svelte"
|
||||
import {clearModals} from "@app/modal"
|
||||
@@ -19,7 +18,7 @@
|
||||
const back = () => history.back()
|
||||
|
||||
const onsubmit = (profile: Profile) => {
|
||||
const relays = ctx.app.router.FromUser().getUrls()
|
||||
const relays = Router.get().FromUser().getUrls()
|
||||
const template = isPublishedProfile(profile) ? editProfile(profile) : createProfile(profile)
|
||||
const event = createEvent(template.kind, template)
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
import {REACTION, getTag, REPORT, DELETE} from "@welshman/util"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {deriveEvents} from "@welshman/store"
|
||||
import {pubkey, repository, load, displayProfileByPubkey} from "@welshman/app"
|
||||
import type {MultiRequest} from "@welshman/net"
|
||||
import {load, request, RequestEvent} from "@welshman/net"
|
||||
import {pubkey, repository, displayProfileByPubkey} from "@welshman/app"
|
||||
import {displayList} from "@lib/util"
|
||||
import {isMobile, preventDefault, stopPropagation} from "@lib/html"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
@@ -51,17 +53,27 @@
|
||||
)
|
||||
|
||||
onMount(() => {
|
||||
let req: MultiRequest
|
||||
|
||||
if (url) {
|
||||
load({
|
||||
req = request({
|
||||
relays: [url],
|
||||
filters: [{kinds: [REACTION, REPORT, DELETE], "#e": [event.id]}],
|
||||
onEvent: batch(300, (events: TrustedEvent[]) => {
|
||||
})
|
||||
|
||||
req.on(
|
||||
RequestEvent.Event,
|
||||
batch(300, (events: TrustedEvent[]) => {
|
||||
load({
|
||||
relays: [url],
|
||||
filters: [{kinds: [DELETE], "#e": events.map(e => e.id)}],
|
||||
})
|
||||
}),
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
return () => {
|
||||
req?.close()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte"
|
||||
import {ctx, sleep} from "@welshman/lib"
|
||||
import {sleep} from "@welshman/lib"
|
||||
import {Pool, AuthStatus} from "@welshman/net"
|
||||
import {displayRelayUrl} from "@welshman/util"
|
||||
import {preventDefault} from "@lib/html"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
@@ -17,7 +18,7 @@
|
||||
const back = () => history.back()
|
||||
|
||||
const next = () => {
|
||||
if (!error && ctx.net.pool.get(url).stats.lastAuth === 0) {
|
||||
if (!error && Pool.getSingleton().get(url).auth.status === AuthStatus.None) {
|
||||
pushModal(SpaceVisitConfirm, {url}, {replaceState: true})
|
||||
} else {
|
||||
confirmSpaceVisit(url)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte"
|
||||
import {sleep, identity, nthEq} from "@welshman/lib"
|
||||
import {load} from "@welshman/app"
|
||||
import {load} from "@welshman/net"
|
||||
import {displayRelayUrl, AUTH_INVITE} from "@welshman/util"
|
||||
import {slide} from "@lib/transition"
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {ctx, tryCatch} from "@welshman/lib"
|
||||
import {tryCatch} from "@welshman/lib"
|
||||
import {isRelayUrl, normalizeRelayUrl} from "@welshman/util"
|
||||
import {Pool, AuthStatus} from "@welshman/net"
|
||||
import {preventDefault} from "@lib/html"
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
@@ -25,9 +26,9 @@
|
||||
return pushToast({theme: "error", message: error})
|
||||
}
|
||||
|
||||
const connection = ctx.net.pool.get(url)
|
||||
const socket = Pool.getSingleton().get(url)
|
||||
|
||||
if (connection.stats.lastAuth === 0) {
|
||||
if (socket.auth.status === AuthStatus.None) {
|
||||
pushModal(SpaceJoinConfirm, {url}, {replaceState: true})
|
||||
} else {
|
||||
await confirmSpaceJoin(url)
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import {mount} from "svelte"
|
||||
import type {Writable} from "svelte/store"
|
||||
import {get} from "svelte/store"
|
||||
import {Editor} from "@tiptap/core"
|
||||
import {ctx} from "@welshman/lib"
|
||||
import type {StampedEvent} from "@welshman/util"
|
||||
import {signer, profileSearch} from "@welshman/app"
|
||||
import {MentionSuggestion, WelshmanExtension} from "@welshman/editor"
|
||||
import {Router, signer, profileSearch} from "@welshman/app"
|
||||
import {Editor, MentionSuggestion, WelshmanExtension} from "@welshman/editor"
|
||||
import {getSetting, userSettingValues} from "@app/state"
|
||||
import {MentionNodeView} from "./MentionNodeView"
|
||||
import ProfileSuggestion from "./ProfileSuggestion.svelte"
|
||||
@@ -84,7 +82,7 @@ export const makeEditor = ({
|
||||
MentionSuggestion({
|
||||
editor: (this as any).editor,
|
||||
search: (term: string) => get(profileSearch).searchValues(term),
|
||||
getRelays: (pubkey: string) => ctx.app.router.FromPubkeys([pubkey]).getUrls(),
|
||||
getRelays: (pubkey: string) => Router.get().FromPubkeys([pubkey]).getUrls(),
|
||||
createSuggestion: (value: string) => {
|
||||
const target = document.createElement("div")
|
||||
|
||||
|
||||
@@ -28,15 +28,14 @@ import {
|
||||
} from "@welshman/util"
|
||||
import type {TrustedEvent, Filter, List} from "@welshman/util"
|
||||
import {feedFromFilters, makeRelayFeed, makeIntersectionFeed} from "@welshman/feeds"
|
||||
import type {Subscription, SubscribeRequestWithHandlers} from "@welshman/net"
|
||||
import {load, request, RequestEvent} from "@welshman/net"
|
||||
import type {MultiRequest} from "@welshman/net"
|
||||
import type {AppSyncOpts, Thunk} from "@welshman/app"
|
||||
import {
|
||||
subscribe,
|
||||
load,
|
||||
repository,
|
||||
pull,
|
||||
hasNegentropy,
|
||||
thunkWorker,
|
||||
thunkQueue,
|
||||
createFeedController,
|
||||
loadRelay,
|
||||
loadMutes,
|
||||
@@ -152,13 +151,11 @@ export const makeFeed = ({
|
||||
onExhausted,
|
||||
})
|
||||
|
||||
const sub = subscribe({
|
||||
relays,
|
||||
filters: subscriptionFilters,
|
||||
onEvent: (e: TrustedEvent) => {
|
||||
if (matchFilters(feedFilters, e)) insertEvent(e)
|
||||
if (e.kind === DELETE) handleDelete(e)
|
||||
},
|
||||
const req = request({relays, filters: subscriptionFilters})
|
||||
|
||||
req.on(RequestEvent.Event, (e: TrustedEvent) => {
|
||||
if (matchFilters(feedFilters, e)) insertEvent(e)
|
||||
if (e.kind === DELETE) handleDelete(e)
|
||||
})
|
||||
|
||||
const scroller = createScroller({
|
||||
@@ -176,14 +173,14 @@ export const makeFeed = ({
|
||||
},
|
||||
})
|
||||
|
||||
thunkWorker.addGlobalHandler(onThunk)
|
||||
const unsubscribe = thunkQueue.subscribe(onThunk)
|
||||
|
||||
return {
|
||||
events,
|
||||
cleanup: () => {
|
||||
sub.close()
|
||||
req.close()
|
||||
unsubscribe()
|
||||
scroller.stop()
|
||||
thunkWorker.removeGlobalHandler(onThunk)
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -245,22 +242,22 @@ export const makeCalendarFeed = ({
|
||||
}
|
||||
}
|
||||
|
||||
const sub = subscribe({
|
||||
relays,
|
||||
filters: subscriptionFilters,
|
||||
onEvent: (e: TrustedEvent) => {
|
||||
if (matchFilters(feedFilters, e)) insertEvent(e)
|
||||
},
|
||||
const req = request({relays, filters: subscriptionFilters})
|
||||
|
||||
req.on(RequestEvent.Event, (e: TrustedEvent) => {
|
||||
if (matchFilters(feedFilters, e)) insertEvent(e)
|
||||
})
|
||||
|
||||
const loadTimeframe = (since: number, until: number) => {
|
||||
const hashes = daysBetween(since, until).map(String)
|
||||
|
||||
load({
|
||||
const req = request({
|
||||
relays,
|
||||
autoClose: true,
|
||||
filters: [{kinds: [EVENT_TIME], "#D": hashes}],
|
||||
onEvent: insertEvent,
|
||||
})
|
||||
|
||||
req.on(RequestEvent.Event, insertEvent)
|
||||
}
|
||||
|
||||
const maybeExhausted = () => {
|
||||
@@ -302,15 +299,15 @@ export const makeCalendarFeed = ({
|
||||
},
|
||||
})
|
||||
|
||||
thunkWorker.addGlobalHandler(onThunk)
|
||||
const unsubscribe = thunkQueue.subscribe(onThunk)
|
||||
|
||||
return {
|
||||
events,
|
||||
cleanup: () => {
|
||||
thunkWorker.removeGlobalHandler(onThunk)
|
||||
backwardScroller.stop()
|
||||
forwardScroller.stop()
|
||||
sub.close()
|
||||
unsubscribe()
|
||||
req.close()
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -332,7 +329,7 @@ export const loadAlertStatuses = (pubkey: string) =>
|
||||
// Application requests
|
||||
|
||||
export const listenForNotifications = () => {
|
||||
const subs: Subscription[] = []
|
||||
const reqs: MultiRequest[] = []
|
||||
|
||||
for (const [url, allRooms] of userRoomsByUrl.get()) {
|
||||
// Limit how many rooms we load at a time, since we have to send a separate filter
|
||||
@@ -350,8 +347,8 @@ export const listenForNotifications = () => {
|
||||
],
|
||||
})
|
||||
|
||||
subs.push(
|
||||
subscribe({
|
||||
reqs.push(
|
||||
request({
|
||||
relays: [url],
|
||||
filters: [
|
||||
{kinds: [THREAD, EVENT_TIME], since: now()},
|
||||
@@ -363,25 +360,22 @@ export const listenForNotifications = () => {
|
||||
}
|
||||
|
||||
return () => {
|
||||
for (const sub of subs) {
|
||||
sub.close()
|
||||
for (const req of reqs) {
|
||||
req.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const loadUserData = (
|
||||
pubkey: string,
|
||||
request: Partial<SubscribeRequestWithHandlers> = {},
|
||||
) => {
|
||||
export const loadUserData = (pubkey: string, relays: string[] = []) => {
|
||||
const promise = Promise.race([
|
||||
sleep(3000),
|
||||
Promise.all([
|
||||
loadInboxRelaySelections(pubkey, request),
|
||||
loadMembership(pubkey, request),
|
||||
loadSettings(pubkey, request),
|
||||
loadProfile(pubkey, request),
|
||||
loadFollows(pubkey, request),
|
||||
loadMutes(pubkey, request),
|
||||
loadInboxRelaySelections(pubkey, relays),
|
||||
loadMembership(pubkey, relays),
|
||||
loadSettings(pubkey, relays),
|
||||
loadProfile(pubkey, relays),
|
||||
loadFollows(pubkey, relays),
|
||||
loadMutes(pubkey, relays),
|
||||
loadAlertStatuses(pubkey),
|
||||
loadAlerts(pubkey),
|
||||
]),
|
||||
@@ -396,10 +390,10 @@ export const loadUserData = (
|
||||
await sleep(1000)
|
||||
|
||||
for (const pubkey of pubkeys) {
|
||||
loadMembership(pubkey, {relays})
|
||||
loadProfile(pubkey, {relays})
|
||||
loadFollows(pubkey, {relays})
|
||||
loadMutes(pubkey, {relays})
|
||||
loadMembership(pubkey, relays)
|
||||
loadProfile(pubkey, relays)
|
||||
loadFollows(pubkey, relays)
|
||||
loadMutes(pubkey, relays)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -408,4 +402,8 @@ export const loadUserData = (
|
||||
}
|
||||
|
||||
export const discoverRelays = (lists: List[]) =>
|
||||
Promise.all(uniq(lists.flatMap(getRelayUrls)).filter(isShareableRelayUrl).map(loadRelay))
|
||||
Promise.all(
|
||||
uniq(lists.flatMap(getRelayUrls))
|
||||
.filter(isShareableRelayUrl)
|
||||
.map(url => loadRelay(url)),
|
||||
)
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import twColors from "tailwindcss/colors"
|
||||
import {get, derived} from "svelte/store"
|
||||
import {nip19} from "nostr-tools"
|
||||
import * as nip19 from "nostr-tools/nip19"
|
||||
import {
|
||||
ctx,
|
||||
setContext,
|
||||
remove,
|
||||
sortBy,
|
||||
sort,
|
||||
@@ -17,7 +15,9 @@ import {
|
||||
memoize,
|
||||
addToMapKey,
|
||||
identity,
|
||||
always,
|
||||
} from "@welshman/lib"
|
||||
import {load} from "@welshman/net"
|
||||
import {
|
||||
getIdFilters,
|
||||
WRAP,
|
||||
@@ -46,12 +46,8 @@ import {Nip59, decrypt} from "@welshman/signer"
|
||||
import {
|
||||
pubkey,
|
||||
repository,
|
||||
load,
|
||||
collection,
|
||||
profilesByPubkey,
|
||||
getDefaultAppContext,
|
||||
getDefaultNetContext,
|
||||
makeRouter,
|
||||
tracker,
|
||||
makeTrackerStore,
|
||||
makeRepositoryStore,
|
||||
@@ -64,9 +60,12 @@ import {
|
||||
thunks,
|
||||
walkThunks,
|
||||
signer,
|
||||
Router,
|
||||
loadWithAsapMetaRelayUrls,
|
||||
routerContext,
|
||||
appContext,
|
||||
} from "@welshman/app"
|
||||
import type {Thunk, Relay} from "@welshman/app"
|
||||
import type {SubscribeRequestWithHandlers} from "@welshman/net"
|
||||
import {deriveEvents, deriveEventsMapped, withGetter, synced} from "@welshman/store"
|
||||
|
||||
export const fromCsv = (s: string) => (s || "").split(",").filter(identity)
|
||||
@@ -162,10 +161,8 @@ export const imgproxy = (url: string, {w = 640, h = 1024} = {}) => {
|
||||
|
||||
export const entityLink = (entity: string) => `https://coracle.social/${entity}`
|
||||
|
||||
export const pubkeyLink = (
|
||||
pubkey: string,
|
||||
relays = ctx.app.router.FromPubkeys([pubkey]).getUrls(),
|
||||
) => entityLink(nip19.nprofileEncode({pubkey, relays}))
|
||||
export const pubkeyLink = (pubkey: string, relays = Router.get().FromPubkeys([pubkey]).getUrls()) =>
|
||||
entityLink(nip19.nprofileEncode({pubkey, relays}))
|
||||
|
||||
export const tagRoom = (room: string, url: string) => [ROOM, room]
|
||||
|
||||
@@ -283,15 +280,9 @@ export const deriveEventsForUrl = (url: string, filters: Filter[]) =>
|
||||
|
||||
// Context
|
||||
|
||||
setContext({
|
||||
net: getDefaultNetContext(),
|
||||
app: getDefaultAppContext({
|
||||
dufflepudUrl: DUFFLEPUD_URL,
|
||||
indexerRelays: INDEXER_RELAYS,
|
||||
requestTimeout: 5000,
|
||||
router: makeRouter(),
|
||||
}),
|
||||
})
|
||||
appContext.dufflepudUrl = DUFFLEPUD_URL
|
||||
|
||||
routerContext.getIndexerRelays = always(INDEXER_RELAYS)
|
||||
|
||||
// Settings
|
||||
|
||||
@@ -341,8 +332,8 @@ export const {
|
||||
name: "settings",
|
||||
store: settings,
|
||||
getKey: settings => settings.event.pubkey,
|
||||
load: (pubkey: string, request: Partial<SubscribeRequestWithHandlers> = {}) =>
|
||||
load({...request, filters: [{kinds: [SETTINGS], authors: [pubkey]}]}),
|
||||
load: (pubkey: string, relays: string[]) =>
|
||||
loadWithAsapMetaRelayUrls(pubkey, relays, [{kinds: [SETTINGS], authors: [pubkey]}]),
|
||||
})
|
||||
|
||||
// Alerts
|
||||
@@ -419,8 +410,8 @@ export const {
|
||||
name: "memberships",
|
||||
store: memberships,
|
||||
getKey: list => list.event.pubkey,
|
||||
load: (pubkey: string, request: Partial<SubscribeRequestWithHandlers> = {}) =>
|
||||
load({...request, filters: [{kinds: [GROUPS], authors: [pubkey]}]}),
|
||||
load: (pubkey: string, relays: string[]) =>
|
||||
loadWithAsapMetaRelayUrls(pubkey, relays, [{kinds: [GROUPS], authors: [pubkey]}]),
|
||||
})
|
||||
|
||||
// Chats
|
||||
|
||||
@@ -7,51 +7,23 @@
|
||||
import {dev} from "$app/environment"
|
||||
import {goto} from "$app/navigation"
|
||||
import {bytesToHex, hexToBytes} from "@noble/hashes/utils"
|
||||
import {
|
||||
identity,
|
||||
sleep,
|
||||
take,
|
||||
sortBy,
|
||||
defer,
|
||||
ago,
|
||||
now,
|
||||
HOUR,
|
||||
WEEK,
|
||||
MONTH,
|
||||
Worker,
|
||||
} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {
|
||||
MESSAGE,
|
||||
PROFILE,
|
||||
DELETE,
|
||||
REACTION,
|
||||
ZAP_RESPONSE,
|
||||
FOLLOWS,
|
||||
RELAYS,
|
||||
INBOX_RELAYS,
|
||||
WRAP,
|
||||
getPubkeyTagValues,
|
||||
getListTags,
|
||||
} from "@welshman/util"
|
||||
import {identity, sleep, defer, ago, WEEK, TaskQueue} from "@welshman/lib"
|
||||
import type {TrustedEvent, StampedEvent} from "@welshman/util"
|
||||
import {WRAP} from "@welshman/util"
|
||||
import {Nip46Broker, getPubkey, makeSecret} from "@welshman/signer"
|
||||
import type {Socket} from "@welshman/net"
|
||||
import {request, defaultSocketPolicies, makeSocketPolicyAuth} from "@welshman/net"
|
||||
import {
|
||||
relays,
|
||||
handles,
|
||||
loadRelay,
|
||||
db,
|
||||
initStorage,
|
||||
repository,
|
||||
pubkey,
|
||||
plaintext,
|
||||
freshness,
|
||||
storageAdapters,
|
||||
tracker,
|
||||
defaultStorageAdapters,
|
||||
session,
|
||||
signer,
|
||||
dropSession,
|
||||
getRelayUrls,
|
||||
subscribe,
|
||||
userInboxRelaySelections,
|
||||
addSession,
|
||||
} from "@welshman/app"
|
||||
@@ -140,78 +112,20 @@
|
||||
}
|
||||
})
|
||||
|
||||
initStorage("flotilla", 5, {
|
||||
relays: storageAdapters.fromCollectionStore("url", relays, {throttle: 3000}),
|
||||
handles: storageAdapters.fromCollectionStore("nip05", handles, {throttle: 3000}),
|
||||
freshness: storageAdapters.fromObjectStore(freshness, {
|
||||
throttle: 3000,
|
||||
migrate: (data: {key: string; value: number}[]) => {
|
||||
const cutoff = ago(HOUR)
|
||||
|
||||
return data.filter(({value}) => value > cutoff)
|
||||
},
|
||||
}),
|
||||
plaintext: storageAdapters.fromObjectStore(plaintext, {
|
||||
throttle: 3000,
|
||||
migrate: (data: {key: string; value: number}[]) => data.slice(0, 10_000),
|
||||
}),
|
||||
events2: storageAdapters.fromRepositoryAndTracker(repository, tracker, {
|
||||
throttle: 3000,
|
||||
migrate: (events: TrustedEvent[]) => {
|
||||
if (events.length < 15_000) {
|
||||
return events
|
||||
}
|
||||
|
||||
const NEVER_KEEP = 0
|
||||
const ALWAYS_KEEP = Infinity
|
||||
const reactionKinds = [REACTION, ZAP_RESPONSE, DELETE]
|
||||
const metaKinds = [PROFILE, FOLLOWS, RELAYS, INBOX_RELAYS]
|
||||
const sessionKeys = new Set(Object.keys(app.sessions.get()))
|
||||
const userFollows = new Set(getPubkeyTagValues(getListTags(get(app.userFollows))))
|
||||
const maxWot = get(app.maxWot)
|
||||
|
||||
const scoreEvent = (e: TrustedEvent) => {
|
||||
const isFollowing = userFollows.has(e.pubkey)
|
||||
|
||||
// No need to keep a record of everyone who follows the current user
|
||||
if (e.kind === FOLLOWS && !isFollowing) return NEVER_KEEP
|
||||
|
||||
// Drop room messages after a month, re-load on demand
|
||||
if (e.kind === MESSAGE && e.created_at < ago(MONTH)) return NEVER_KEEP
|
||||
|
||||
// Always keep stuff by or tagging a signed in user
|
||||
if (sessionKeys.has(e.pubkey)) return ALWAYS_KEEP
|
||||
if (e.tags.some(t => sessionKeys.has(t[1]))) return ALWAYS_KEEP
|
||||
|
||||
// Get rid of irrelevant messages, reactions, and likes
|
||||
if (e.wrap || e.kind === 4 || e.kind === WRAP) return NEVER_KEEP
|
||||
if (reactionKinds.includes(e.kind)) return NEVER_KEEP
|
||||
|
||||
// If the user follows this person, use max wot score
|
||||
let score = isFollowing ? maxWot : app.getUserWotScore(e.pubkey)
|
||||
|
||||
// Inflate the score for profiles/relays/follows to avoid redundant fetches
|
||||
// Demote non-metadata type events, and introduce recency bias
|
||||
score *= metaKinds.includes(e.kind) ? 2 : e.created_at / now()
|
||||
|
||||
return score
|
||||
}
|
||||
|
||||
return take(
|
||||
10_000,
|
||||
sortBy(e => -scoreEvent(e), events),
|
||||
)
|
||||
},
|
||||
}),
|
||||
}).then(async () => {
|
||||
initStorage("flotilla", 6, defaultStorageAdapters).then(async () => {
|
||||
await sleep(300)
|
||||
ready.resolve()
|
||||
})
|
||||
|
||||
// Unwrap gift wraps as they come in, but throttled
|
||||
const unwrapper = new Worker<TrustedEvent>({chunkSize: 10})
|
||||
defaultSocketPolicies.push(
|
||||
makeSocketPolicyAuth({
|
||||
sign: (event: StampedEvent) => signer.get()?.sign(event),
|
||||
shouldAuth: (socket: Socket) => true,
|
||||
}),
|
||||
)
|
||||
|
||||
unwrapper.addGlobalHandler(ensureUnwrapped)
|
||||
// Unwrap gift wraps as they come in, but throttled
|
||||
const unwrapper = new TaskQueue<TrustedEvent>({batchSize: 10, processItem: ensureUnwrapped})
|
||||
|
||||
repository.on("update", ({added}) => {
|
||||
if (!$canDecrypt) {
|
||||
@@ -244,14 +158,14 @@
|
||||
})
|
||||
|
||||
// Listen for chats, populate chat-based notifications
|
||||
let chatsSub: any
|
||||
let chatsReq: any
|
||||
|
||||
derived([pubkey, canDecrypt, userInboxRelaySelections], identity).subscribe(
|
||||
([$pubkey, $canDecrypt, $userInboxRelaySelections]) => {
|
||||
chatsSub?.close()
|
||||
chatsReq?.close()
|
||||
|
||||
if ($pubkey && $canDecrypt) {
|
||||
chatsSub = subscribe({
|
||||
chatsReq = request({
|
||||
filters: [
|
||||
{kinds: [WRAP], "#p": [$pubkey], since: ago(WEEK, 2)},
|
||||
{kinds: [WRAP], "#p": [$pubkey], limit: 100},
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import * as nip19 from "nostr-tools/nip19"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {Address, getIdFilters, getTagValue} from "@welshman/util"
|
||||
import {load} from "@welshman/app"
|
||||
import {request, RequestEvent} from "@welshman/net"
|
||||
import {page} from "$app/stores"
|
||||
import {goto} from "$app/navigation"
|
||||
import {scrollToEvent} from "@lib/html"
|
||||
@@ -21,26 +21,29 @@
|
||||
|
||||
let found = false
|
||||
|
||||
load({
|
||||
const req = request({
|
||||
autoClose: true,
|
||||
filters: getIdFilters([type === "nevent" ? data.id : Address.fromNaddr(bech32).toString()]),
|
||||
relays: data.relays,
|
||||
onEvent: (event: TrustedEvent) => {
|
||||
found = true
|
||||
})
|
||||
|
||||
if (event.kind === 9) {
|
||||
goto(makeRoomPath(data.relays[0], getTagValue("h", event.tags)!), {replaceState: true})
|
||||
scrollToEvent(event.id)
|
||||
} else if (event.kind === 11) {
|
||||
goto(makeThreadPath(data.relays[0], event.id), {replaceState: true})
|
||||
} else {
|
||||
goto("/", {replaceState: true})
|
||||
}
|
||||
},
|
||||
onComplete: () => {
|
||||
if (!found) {
|
||||
goto("/", {replaceState: true})
|
||||
}
|
||||
},
|
||||
req.on(RequestEvent.Event, (event: TrustedEvent) => {
|
||||
found = true
|
||||
|
||||
if (event.kind === 9) {
|
||||
goto(makeRoomPath(data.relays[0], getTagValue("h", event.tags)!), {replaceState: true})
|
||||
scrollToEvent(event.id)
|
||||
} else if (event.kind === 11) {
|
||||
goto(makeThreadPath(data.relays[0], event.id), {replaceState: true})
|
||||
} else {
|
||||
goto("/", {replaceState: true})
|
||||
}
|
||||
})
|
||||
|
||||
req.on(RequestEvent.Close, () => {
|
||||
if (!found) {
|
||||
goto("/", {replaceState: true})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {page} from "$app/stores"
|
||||
import {ctx} from "@welshman/lib"
|
||||
import {WRAP} from "@welshman/util"
|
||||
import {pubkey} from "@welshman/app"
|
||||
import {pubkey, Router} from "@welshman/app"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Page from "@lib/components/Page.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
@@ -25,7 +24,7 @@
|
||||
|
||||
const promise = pullConservatively({
|
||||
filters: [{kinds: [WRAP], "#p": [$pubkey!]}],
|
||||
relays: ctx.app.router.UserInbox().getUrls(),
|
||||
relays: Router.get().UserInbox().getUrls(),
|
||||
})
|
||||
|
||||
let term = $state("")
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {ctx} from "@welshman/lib"
|
||||
import {getListTags, createEvent, getPubkeyTagValues, MUTES} from "@welshman/util"
|
||||
import {pubkey, signer, userMutes, tagPubkey, publishThunk} from "@welshman/app"
|
||||
import {pubkey, Router, signer, userMutes, tagPubkey, publishThunk} from "@welshman/app"
|
||||
import {preventDefault} from "@lib/html"
|
||||
import Field from "@lib/components/Field.svelte"
|
||||
import FieldInline from "@lib/components/FieldInline.svelte"
|
||||
@@ -22,12 +21,12 @@
|
||||
|
||||
publishThunk({
|
||||
event: createEvent(SETTINGS, {content}),
|
||||
relays: ctx.app.router.FromUser().getUrls(),
|
||||
relays: Router.get().FromUser().getUrls(),
|
||||
})
|
||||
|
||||
publishThunk({
|
||||
event: createEvent(MUTES, {tags: mutedPubkeys.map(tagPubkey)}),
|
||||
relays: ctx.app.router.FromUser().getUrls(),
|
||||
relays: Router.get().FromUser().getUrls(),
|
||||
})
|
||||
|
||||
pushToast({message: "Your settings have been saved!"})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {nip19} from "nostr-tools"
|
||||
import * as nip19 from "nostr-tools/nip19"
|
||||
import {hexToBytes} from "@noble/hashes/utils"
|
||||
import {displayPubkey, displayProfile} from "@welshman/util"
|
||||
import {pubkey, session, displayNip05, deriveProfile} from "@welshman/app"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import {page} from "$app/stores"
|
||||
import {ago, MONTH} from "@welshman/lib"
|
||||
import {GROUPS, THREAD, COMMENT, MESSAGE, DELETE} from "@welshman/util"
|
||||
import {subscribe, load} from "@welshman/app"
|
||||
import {request, load} from "@welshman/net"
|
||||
import Page from "@lib/components/Page.svelte"
|
||||
import SecondaryNav from "@lib/components/SecondaryNav.svelte"
|
||||
import MenuSpace from "@app/components/MenuSpace.svelte"
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
// Load all groups for this space to populate navigation. It would be nice to sync, but relay29
|
||||
// is too picky about how requests are built.
|
||||
load({relays, filters: [{kinds: [GROUPS]}], delay: 0})
|
||||
load({relays, filters: [{kinds: [GROUPS]}]})
|
||||
|
||||
// Load threads, comments, and recent messages for user rooms to help with a quick page transition
|
||||
pullConservatively({
|
||||
@@ -69,10 +69,10 @@
|
||||
})
|
||||
|
||||
// Listen for deletes that would apply to messages we already have, and new groups
|
||||
const sub = subscribe({relays, filters: [{kinds: [DELETE, GROUPS], since}]})
|
||||
const req = request({relays, filters: [{kinds: [DELETE, GROUPS], since}]})
|
||||
|
||||
return () => {
|
||||
sub.close()
|
||||
req.close()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
import {page} from "$app/stores"
|
||||
import {sortBy, sleep} from "@welshman/lib"
|
||||
import {COMMENT, getTagValue} from "@welshman/util"
|
||||
import {repository, subscribe} from "@welshman/app"
|
||||
import {request} from "@welshman/net"
|
||||
import {repository} from "@welshman/app"
|
||||
import {deriveEvents} from "@welshman/store"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import PageBar from "@lib/components/PageBar.svelte"
|
||||
@@ -45,10 +46,10 @@
|
||||
let showReply = $state(false)
|
||||
|
||||
onMount(() => {
|
||||
const sub = subscribe({relays: [url], filters})
|
||||
const req = request({relays: [url], filters})
|
||||
|
||||
return () => {
|
||||
sub.close()
|
||||
req.close()
|
||||
setChecked($page.url.pathname)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
import {page} from "$app/stores"
|
||||
import {sortBy, sleep} from "@welshman/lib"
|
||||
import {COMMENT, getTagValue} from "@welshman/util"
|
||||
import {repository, subscribe} from "@welshman/app"
|
||||
import {repository} from "@welshman/app"
|
||||
import {request} from "@welshman/net"
|
||||
import {deriveEvents} from "@welshman/store"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import PageBar from "@lib/components/PageBar.svelte"
|
||||
@@ -42,10 +43,10 @@
|
||||
let showReply = $state(false)
|
||||
|
||||
onMount(() => {
|
||||
const sub = subscribe({relays: [url], filters})
|
||||
const req = request({relays: [url], filters})
|
||||
|
||||
return () => {
|
||||
sub.close()
|
||||
req.close()
|
||||
setChecked($page.url.pathname)
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user