mirror of
https://github.com/coracle-social/coracle.git
synced 2024-10-18 09:33:33 +00:00
Use welshman dvms
This commit is contained in:
parent
ab7a28ae34
commit
b318cc6808
12
README.md
12
README.md
@ -19,7 +19,9 @@ If you like Coracle and want to support its development, you can donate sats via
|
|||||||
- [x] NIP 87 closed groups
|
- [x] NIP 87 closed groups
|
||||||
- [x] NIP 72 communities
|
- [x] NIP 72 communities
|
||||||
- [x] NIP 89 client tag support
|
- [x] NIP 89 client tag support
|
||||||
|
- [x] NIP 89 handler integration
|
||||||
- [x] NIP 32 labeling and collections
|
- [x] NIP 32 labeling and collections
|
||||||
|
- [x] NIP 17 DMs
|
||||||
- [x] Private group calendars and listings
|
- [x] Private group calendars and listings
|
||||||
- [x] Cross-posting between communities and main feed
|
- [x] Cross-posting between communities and main feed
|
||||||
- [x] Bech32 entity search and scan
|
- [x] Bech32 entity search and scan
|
||||||
@ -46,6 +48,12 @@ If you like Coracle and want to support its development, you can donate sats via
|
|||||||
- [x] Onboarding workflow
|
- [x] Onboarding workflow
|
||||||
- [x] Multi-account support
|
- [x] Multi-account support
|
||||||
- [x] Notifications view
|
- [x] Notifications view
|
||||||
|
- [x] Web of trust scores for less spam and better group/feed suggestions
|
||||||
|
- [x] Customizable and shareable feeds and lists
|
||||||
|
- [x] Customizable invite links
|
||||||
|
- [x] Reporting via tagr-bot
|
||||||
|
- [x] Nostr Wallet Connect support
|
||||||
|
- [x] Date/time localization
|
||||||
|
|
||||||
You can find a more complete changelog [here](./CHANGELOG.md).
|
You can find a more complete changelog [here](./CHANGELOG.md).
|
||||||
|
|
||||||
@ -53,9 +61,9 @@ You can find a more complete changelog [here](./CHANGELOG.md).
|
|||||||
|
|
||||||
- Clone the project repository: `git clone https://github.com/coracle-social/coracle.git`
|
- Clone the project repository: `git clone https://github.com/coracle-social/coracle.git`
|
||||||
- Navigate to the project directory: `cd coracle`
|
- Navigate to the project directory: `cd coracle`
|
||||||
- Install dependencies: `yarn`
|
- Install dependencies: `npm i`
|
||||||
- Customize configuration in `.env` (optional, see below)
|
- Customize configuration in `.env` (optional, see below)
|
||||||
- Start the development server: `yarn dev`
|
- Start the development server: `npm run dev`
|
||||||
|
|
||||||
# Customization
|
# Customization
|
||||||
|
|
||||||
|
BIN
package-lock.json
generated
BIN
package-lock.json
generated
Binary file not shown.
@ -9,7 +9,7 @@
|
|||||||
"check:es": "eslint 'src/**/*.{js,ts,svelte}' --quiet",
|
"check:es": "eslint 'src/**/*.{js,ts,svelte}' --quiet",
|
||||||
"check:ts": "svelte-check --tsconfig ./tsconfig.json --threshold error",
|
"check:ts": "svelte-check --tsconfig ./tsconfig.json --threshold error",
|
||||||
"check:fmt": "prettier --check $(git diff head --name-only --diff-filter d | grep -E '(js|ts|svelte)$' | xargs)",
|
"check:fmt": "prettier --check $(git diff head --name-only --diff-filter d | grep -E '(js|ts|svelte)$' | xargs)",
|
||||||
"check:errors": "run-p check:es check:ts check:cycles",
|
"check:errors": "run-p check:es check:ts",
|
||||||
"check": "run-p check:errors check:fmt",
|
"check": "run-p check:errors check:fmt",
|
||||||
"format": "prettier --write $(git diff head --name-only --diff-filter d | grep -E '(js|ts|svelte)$' | xargs)",
|
"format": "prettier --write $(git diff head --name-only --diff-filter d | grep -E '(js|ts|svelte)$' | xargs)",
|
||||||
"watch": "find src -type f | entr -r"
|
"watch": "find src -type f | entr -r"
|
||||||
@ -57,7 +57,8 @@
|
|||||||
"@welshman/feeds": "^0.0.12",
|
"@welshman/feeds": "^0.0.12",
|
||||||
"@welshman/lib": "^0.0.11",
|
"@welshman/lib": "^0.0.11",
|
||||||
"@welshman/net": "^0.0.14",
|
"@welshman/net": "^0.0.14",
|
||||||
"@welshman/util": "^0.0.17",
|
"@welshman/util": "^0.0.18",
|
||||||
|
"@welshman/dvm": "^0.0.2",
|
||||||
"bowser": "^2.11.0",
|
"bowser": "^2.11.0",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"compressorjs": "^1.2.1",
|
"compressorjs": "^1.2.1",
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {append} from "ramda"
|
import {append} from "@welshman/lib"
|
||||||
import {updateIn} from "src/util/misc"
|
import {updateIn} from "src/util/misc"
|
||||||
import {slide} from "src/util/transition"
|
import {slide} from "src/util/transition"
|
||||||
import Card from "src/partials/Card.svelte"
|
import Card from "src/partials/Card.svelte"
|
||||||
@ -9,7 +9,9 @@
|
|||||||
export let task
|
export let task
|
||||||
|
|
||||||
const hideTask = () =>
|
const hideTask = () =>
|
||||||
updateCurrentSession(updateIn("onboarding_tasks_completed", append(task)))
|
updateCurrentSession(
|
||||||
|
updateIn("onboarding_tasks_completed", (tasks: string[]) => append(task, tasks)),
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if !$session.onboarding_tasks_completed.includes(task)}
|
{#if !$session.onboarding_tasks_completed.includes(task)}
|
||||||
@ -19,9 +21,7 @@
|
|||||||
<FlexColumn>
|
<FlexColumn>
|
||||||
<slot />
|
<slot />
|
||||||
</FlexColumn>
|
</FlexColumn>
|
||||||
<i
|
<i class="fa fa-times absolute right-0 top-0 cursor-pointer p-2" on:click={hideTask} />
|
||||||
class="fa fa-times absolute right-0 top-0 cursor-pointer p-2"
|
|
||||||
on:click={hideTask} />
|
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import cx from "classnames"
|
||||||
import Anchor from "src/partials/Anchor.svelte"
|
import Anchor from "src/partials/Anchor.svelte"
|
||||||
import {router} from "src/app/util/router"
|
import {router} from "src/app/util/router"
|
||||||
import {deriveProfileDisplay, loadPubkeys} from "src/engine"
|
import {deriveProfileDisplay, loadPubkeys} from "src/engine"
|
||||||
@ -11,6 +12,6 @@
|
|||||||
loadPubkeys([pubkey])
|
loadPubkeys([pubkey])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Anchor modal stopPropagation class={$$props.class} href={path}>
|
<Anchor modal stopPropagation class={cx("!no-underline", $$props.class)} href={path}>
|
||||||
@<span class="underline">{$display}</span>
|
@<span class="underline">{$display}</span>
|
||||||
</Anchor>
|
</Anchor>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {makeRelayFeed} from "@welshman/feeds"
|
import {makeRelayFeed, makeScopeFeed, Scope} from "@welshman/feeds"
|
||||||
import Anchor from "src/partials/Anchor.svelte"
|
import Anchor from "src/partials/Anchor.svelte"
|
||||||
import Feed from "src/app/shared/Feed.svelte"
|
import Feed from "src/app/shared/Feed.svelte"
|
||||||
import {router} from "src/app/util/router"
|
import {router} from "src/app/util/router"
|
||||||
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
if (isPlatformFeed) {
|
if (isPlatformFeed) {
|
||||||
globalFeed.set(makeFeed({definition: makeRelayFeed(...$env.PLATFORM_RELAYS)}))
|
globalFeed.set(makeFeed({definition: makeRelayFeed(...$env.PLATFORM_RELAYS)}))
|
||||||
|
} else {
|
||||||
|
globalFeed.set(makeFeed({definition: makeScopeFeed(Scope.Follows)}))
|
||||||
}
|
}
|
||||||
|
|
||||||
document.title = "Feeds"
|
document.title = "Feeds"
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
userIsGroupMember,
|
userIsGroupMember,
|
||||||
updateCurrentSession,
|
updateCurrentSession,
|
||||||
communityListsByAddress,
|
communityListsByAddress,
|
||||||
searchGroupMeta,
|
groupMetaSearch,
|
||||||
groupMeta,
|
groupMeta,
|
||||||
} from "src/engine"
|
} from "src/engine"
|
||||||
|
|
||||||
@ -34,7 +34,7 @@
|
|||||||
let limit = 20
|
let limit = 20
|
||||||
let element = null
|
let element = null
|
||||||
|
|
||||||
$: otherGroupMeta = reject(userIsMember, $searchGroupMeta(q)).slice(0, limit)
|
$: otherGroupMeta = reject(userIsMember, $groupMetaSearch.searchOptions(q)).slice(0, limit)
|
||||||
|
|
||||||
document.title = "Groups"
|
document.title = "Groups"
|
||||||
|
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
import GroupCircle from "src/app/shared/GroupCircle.svelte"
|
import GroupCircle from "src/app/shared/GroupCircle.svelte"
|
||||||
import PersonSelect from "src/app/shared/PersonSelect.svelte"
|
import PersonSelect from "src/app/shared/PersonSelect.svelte"
|
||||||
import {router} from "src/app/util/router"
|
import {router} from "src/app/util/router"
|
||||||
import {displayRelayUrl, displayGroupMeta} from "src/domain"
|
import {displayRelayUrl} from "src/domain"
|
||||||
import {hints, relaySearch, searchGroupMeta, groupMetaByAddress} from "src/engine"
|
import {hints, relaySearch, groupMetaSearch, displayGroupByAddress} from "src/engine"
|
||||||
|
|
||||||
export let initialPubkey = null
|
export let initialPubkey = null
|
||||||
export let initialGroupAddress = null
|
export let initialGroupAddress = null
|
||||||
@ -70,8 +70,6 @@
|
|||||||
groups = toSpliced(groups, i, 1)
|
groups = toSpliced(groups, i, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const displayGroupFromAddress = a => displayGroupMeta($groupMetaByAddress.get(a))
|
|
||||||
|
|
||||||
let relayInput, groupInput
|
let relayInput, groupInput
|
||||||
let sections = []
|
let sections = []
|
||||||
let pubkeys = []
|
let pubkeys = []
|
||||||
@ -185,7 +183,7 @@
|
|||||||
</p>
|
</p>
|
||||||
{#each groups as group, i (group.address + i)}
|
{#each groups as group, i (group.address + i)}
|
||||||
<ListItem on:remove={() => removeGroup(i)}>
|
<ListItem on:remove={() => removeGroup(i)}>
|
||||||
<span slot="label">{displayGroupFromAddress(group.address)}</span>
|
<span slot="label">{displayGroupByAddress(group.address)}</span>
|
||||||
<span slot="data">
|
<span slot="data">
|
||||||
<Input bind:value={group.claim} placeholder="Invite code (optional)" />
|
<Input bind:value={group.claim} placeholder="Invite code (optional)" />
|
||||||
</span>
|
</span>
|
||||||
@ -194,8 +192,8 @@
|
|||||||
<SearchSelect
|
<SearchSelect
|
||||||
value={null}
|
value={null}
|
||||||
bind:this={groupInput}
|
bind:this={groupInput}
|
||||||
search={$searchGroupMeta}
|
search={$groupMetaSearch.searchOptions}
|
||||||
displayItem={displayGroupMeta}
|
displayItem={$groupMetaSearch.displayOption}
|
||||||
getKey={groupMeta => getAddress(groupMeta.event)}
|
getKey={groupMeta => getAddress(groupMeta.event)}
|
||||||
onChange={groupMeta => groupMeta && addGroup(getAddress(groupMeta.event))}>
|
onChange={groupMeta => groupMeta && addGroup(getAddress(groupMeta.event))}>
|
||||||
<i slot="before" class="fa fa-search" />
|
<i slot="before" class="fa fa-search" />
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
getIdFilters,
|
getIdFilters,
|
||||||
isGroupAddress,
|
isGroupAddress,
|
||||||
isSignedEvent,
|
isSignedEvent,
|
||||||
|
createEvent,
|
||||||
WRAP,
|
WRAP,
|
||||||
WRAP_NIP04,
|
WRAP_NIP04,
|
||||||
EPOCH,
|
EPOCH,
|
||||||
@ -28,6 +29,7 @@ import {
|
|||||||
HANDLER_INFORMATION,
|
HANDLER_INFORMATION,
|
||||||
HANDLER_RECOMMENDATION,
|
HANDLER_RECOMMENDATION,
|
||||||
} from "@welshman/util"
|
} from "@welshman/util"
|
||||||
|
import {makeDvmRequest} from "@welshman/dvm"
|
||||||
import {updateIn, createBatcher} from "src/util/misc"
|
import {updateIn, createBatcher} from "src/util/misc"
|
||||||
import {giftWrapKinds, noteKinds, reactionKinds, repostKinds} from "src/util/nostr"
|
import {giftWrapKinds, noteKinds, reactionKinds, repostKinds} from "src/util/nostr"
|
||||||
import {always, partition, pluck, uniq, without} from "ramda"
|
import {always, partition, pluck, uniq, without} from "ramda"
|
||||||
@ -38,7 +40,6 @@ import {
|
|||||||
getUserCircles,
|
getUserCircles,
|
||||||
getGroupReqInfo,
|
getGroupReqInfo,
|
||||||
getCommunityReqInfo,
|
getCommunityReqInfo,
|
||||||
dvmRequest,
|
|
||||||
env,
|
env,
|
||||||
getFollows,
|
getFollows,
|
||||||
getFilterSelections,
|
getFilterSelections,
|
||||||
@ -59,9 +60,9 @@ import {
|
|||||||
subscribe,
|
subscribe,
|
||||||
subscribePersistent,
|
subscribePersistent,
|
||||||
dufflepud,
|
dufflepud,
|
||||||
|
signer,
|
||||||
} from "src/engine/state"
|
} from "src/engine/state"
|
||||||
import {updateCurrentSession, updateSession} from "src/engine/commands"
|
import {updateCurrentSession, updateSession} from "src/engine/commands"
|
||||||
import {loadPubkeyRelays} from "src/engine/requests/pubkeys"
|
|
||||||
|
|
||||||
export * from "src/engine/requests/pubkeys"
|
export * from "src/engine/requests/pubkeys"
|
||||||
|
|
||||||
@ -275,22 +276,22 @@ export const feedLoader = new FeedLoader<TrustedEvent>({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
requestDVM: async ({kind, onEvent, tags = [], ...request}) => {
|
requestDVM: async ({kind, onEvent, tags = [], ...request}) => {
|
||||||
let relays
|
tags = [...tags, ["expiration", String(now() + 5)]]
|
||||||
if (request.relays?.length > 0) {
|
|
||||||
relays = hints.fromRelays(request.relays).getUrls()
|
|
||||||
} else {
|
|
||||||
const pubkeys = tags.filter(nthEq(0, "p")).map(nth(1))
|
|
||||||
|
|
||||||
await loadPubkeyRelays(pubkeys)
|
const req = makeDvmRequest({
|
||||||
|
event: await signer.get().signAsUser(createEvent(kind, {tags})),
|
||||||
|
relays:
|
||||||
|
request.relays?.length > 0
|
||||||
|
? hints.fromRelays(request.relays).getUrls()
|
||||||
|
: hints.Messages(tags.filter(nthEq(0, "p")).map(nth(1))).getUrls(),
|
||||||
|
})
|
||||||
|
|
||||||
relays = hints.Messages(pubkeys).getUrls()
|
await new Promise<void>(resolve => {
|
||||||
}
|
req.emitter.on("result", (url, event) => {
|
||||||
|
onEvent(event)
|
||||||
const event = await dvmRequest({kind, tags, relays})
|
resolve()
|
||||||
|
})
|
||||||
if (event) {
|
})
|
||||||
onEvent(event)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
getPubkeysForScope: (scope: string) => {
|
getPubkeysForScope: (scope: string) => {
|
||||||
const $pubkey = pubkey.get()
|
const $pubkey = pubkey.get()
|
||||||
|
@ -54,7 +54,7 @@ const getFiltersForKey = (key: string, authors: string[]) => {
|
|||||||
case "pubkey/relays":
|
case "pubkey/relays":
|
||||||
return [{authors, kinds: [RELAYS, INBOX_RELAYS]}]
|
return [{authors, kinds: [RELAYS, INBOX_RELAYS]}]
|
||||||
case "pubkey/profile":
|
case "pubkey/profile":
|
||||||
return [{authors, kinds: [PROFILE, FOLLOWS, HANDLER_INFORMATION, COMMUNITIES]}]
|
return [{authors, kinds: [PROFILE, FOLLOWS, MUTES, HANDLER_INFORMATION, COMMUNITIES]}]
|
||||||
case "pubkey/user":
|
case "pubkey/user":
|
||||||
return [
|
return [
|
||||||
{authors, kinds: [PROFILE, RELAYS, MUTES, FOLLOWS, COMMUNITIES, FEEDS]},
|
{authors, kinds: [PROFILE, RELAYS, MUTES, FOLLOWS, COMMUNITIES, FEEDS]},
|
||||||
|
@ -92,7 +92,7 @@ import {
|
|||||||
publish as basePublish,
|
publish as basePublish,
|
||||||
subscribe as baseSubscribe,
|
subscribe as baseSubscribe,
|
||||||
} from "@welshman/net"
|
} from "@welshman/net"
|
||||||
import type {Publish, PublishRequest, SubscribeRequest} from "@welshman/net"
|
import type {PublishRequest, SubscribeRequest} from "@welshman/net"
|
||||||
import * as Content from "@welshman/content"
|
import * as Content from "@welshman/content"
|
||||||
import {fuzzy, synced, withGetter, pushToKey, tryJson, fromCsv, SearchHelper} from "src/util/misc"
|
import {fuzzy, synced, withGetter, pushToKey, tryJson, fromCsv, SearchHelper} from "src/util/misc"
|
||||||
import {
|
import {
|
||||||
@ -108,6 +108,7 @@ import {
|
|||||||
} from "src/util/nostr"
|
} from "src/util/nostr"
|
||||||
import logger from "src/util/logger"
|
import logger from "src/util/logger"
|
||||||
import type {
|
import type {
|
||||||
|
GroupMeta,
|
||||||
PublishedFeed,
|
PublishedFeed,
|
||||||
PublishedProfile,
|
PublishedProfile,
|
||||||
PublishedListFeed,
|
PublishedListFeed,
|
||||||
@ -142,6 +143,7 @@ import {
|
|||||||
filterRelaysByNip,
|
filterRelaysByNip,
|
||||||
displayRelayUrl,
|
displayRelayUrl,
|
||||||
readGroupMeta,
|
readGroupMeta,
|
||||||
|
displayGroupMeta,
|
||||||
} from "src/domain"
|
} from "src/domain"
|
||||||
import type {
|
import type {
|
||||||
Channel,
|
Channel,
|
||||||
@ -693,7 +695,32 @@ export const groupMetaByAddress = withGetter(
|
|||||||
export const deriveGroupMeta = (address: string) =>
|
export const deriveGroupMeta = (address: string) =>
|
||||||
derived(groupMetaByAddress, $m => $m.get(address))
|
derived(groupMetaByAddress, $m => $m.get(address))
|
||||||
|
|
||||||
export const searchGroupMeta = derived(
|
export const displayGroupByAddress = a => displayGroupMeta(groupMetaByAddress.get().get(a))
|
||||||
|
|
||||||
|
export class GroupSearch extends SearchHelper<GroupMeta & {score: number}, string> {
|
||||||
|
config = {
|
||||||
|
keys: [{name: "identifier", weight: 0.2}, "name", {name: "about", weight: 0.5}],
|
||||||
|
threshold: 0.3,
|
||||||
|
shouldSort: false,
|
||||||
|
includeScore: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
getSearch = () => {
|
||||||
|
const fuse = new Fuse(this.options, this.config)
|
||||||
|
const sortFn = (r: any) => r.score - Math.pow(Math.max(0, r.item.score), 1 / 100)
|
||||||
|
|
||||||
|
return (term: string) =>
|
||||||
|
term
|
||||||
|
? sortBy(sortFn, fuse.search(term)).map((r: any) => r.item)
|
||||||
|
: sortBy(meta => -meta.score, this.options)
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue = (option: GroupMeta) => getAddress(option.event)
|
||||||
|
|
||||||
|
displayValue = displayGroupByAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
export const groupMetaSearch = derived(
|
||||||
[groupMeta, communityListsByAddress, userFollows],
|
[groupMeta, communityListsByAddress, userFollows],
|
||||||
([$groupMeta, $communityListsByAddress, $userFollows]) => {
|
([$groupMeta, $communityListsByAddress, $userFollows]) => {
|
||||||
const options = $groupMeta.map(meta => {
|
const options = $groupMeta.map(meta => {
|
||||||
@ -704,19 +731,7 @@ export const searchGroupMeta = derived(
|
|||||||
return {...meta, score: followedMembers.length}
|
return {...meta, score: followedMembers.length}
|
||||||
})
|
})
|
||||||
|
|
||||||
const fuse = new Fuse(options, {
|
return new GroupSearch(options)
|
||||||
keys: [{name: "identifier", weight: 0.2}, "name", {name: "about", weight: 0.5}],
|
|
||||||
threshold: 0.3,
|
|
||||||
shouldSort: false,
|
|
||||||
includeScore: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
const sortFn = (r: any) => r.score - Math.pow(Math.max(0, r.item.score), 1 / 100)
|
|
||||||
|
|
||||||
return (term: string) =>
|
|
||||||
term
|
|
||||||
? sortBy(sortFn, fuse.search(term)).map((r: any) => r.item)
|
|
||||||
: sortBy(meta => -meta.score, options)
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1975,75 +1990,6 @@ export const getClientTags = () => {
|
|||||||
return [tag]
|
return [tag]
|
||||||
}
|
}
|
||||||
|
|
||||||
// DVMs
|
|
||||||
|
|
||||||
export type DVMRequestOpts = {
|
|
||||||
kind: number
|
|
||||||
input?: any
|
|
||||||
inputOpts?: string[]
|
|
||||||
tags?: string[][]
|
|
||||||
relays?: string[]
|
|
||||||
timeout?: number
|
|
||||||
onPublish?: (pub: Publish) => void
|
|
||||||
onProgress?: (e: TrustedEvent) => void
|
|
||||||
sk?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export const dvmRequest = async ({
|
|
||||||
kind,
|
|
||||||
tags = [],
|
|
||||||
timeout = 30_000,
|
|
||||||
relays = [],
|
|
||||||
onPublish = null,
|
|
||||||
onProgress = null,
|
|
||||||
sk = null,
|
|
||||||
}: DVMRequestOpts): Promise<TrustedEvent> => {
|
|
||||||
if (!sk && !signer.get().isEnabled()) {
|
|
||||||
sk = generatePrivateKey()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (relays.length === 0) {
|
|
||||||
relays = hints.merge([hints.WriteRelays(), hints.fromRelays(env.get().DVM_RELAYS)]).getUrls()
|
|
||||||
}
|
|
||||||
|
|
||||||
tags = tags.concat([["expiration", String(now() + seconds(1, "hour"))]])
|
|
||||||
|
|
||||||
const pub = await createAndPublish({kind, relays, sk, tags, forcePlatform: false})
|
|
||||||
|
|
||||||
onPublish?.(pub)
|
|
||||||
|
|
||||||
return new Promise(resolve => {
|
|
||||||
const kinds = [kind + 1000]
|
|
||||||
|
|
||||||
if (onProgress) {
|
|
||||||
kinds.push(7000)
|
|
||||||
}
|
|
||||||
|
|
||||||
const sub = subscribe({
|
|
||||||
relays,
|
|
||||||
timeout,
|
|
||||||
filters: [
|
|
||||||
{
|
|
||||||
kinds,
|
|
||||||
since: now() - seconds(1, "minute"),
|
|
||||||
"#e": [pub.request.event.id],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
onEvent: (e: TrustedEvent) => {
|
|
||||||
if (e.kind === 7000) {
|
|
||||||
onProgress?.(e)
|
|
||||||
} else {
|
|
||||||
resolve(e)
|
|
||||||
sub.close()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onComplete: () => {
|
|
||||||
resolve(null)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thread
|
// Thread
|
||||||
|
|
||||||
const getAncestorIds = e => {
|
const getAncestorIds = e => {
|
||||||
@ -2162,19 +2108,19 @@ class IndexedDBAdapter {
|
|||||||
const removedRecords = prev.filter(r => !currentIds.has(r[key]))
|
const removedRecords = prev.filter(r => !currentIds.has(r[key]))
|
||||||
|
|
||||||
if (newRecords.length > 0) {
|
if (newRecords.length > 0) {
|
||||||
console.log("putting", name, newRecords.length, current.length)
|
|
||||||
await storage.bulkPut(name, newRecords)
|
await storage.bulkPut(name, newRecords)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removedRecords.length > 0) {
|
if (removedRecords.length > 0) {
|
||||||
console.trace("deleting", name, removedRecords.length, current.length)
|
if (name === "repository") {
|
||||||
|
console.trace("deleting", removedRecords.length, current.length)
|
||||||
|
}
|
||||||
await storage.bulkDelete(name, removedRecords.map(prop(key)))
|
await storage.bulkDelete(name, removedRecords.map(prop(key)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have much more than our limit, prune our store. This will get persisted
|
// If we have much more than our limit, prune our store. This will get persisted
|
||||||
// the next time around.
|
// the next time around.
|
||||||
if (current.length > limit * 1.5) {
|
if (current.length > limit * 1.5) {
|
||||||
console.log("pruning", name, current.length)
|
|
||||||
set((sort ? sort(current) : current).slice(0, limit))
|
set((sort ? sort(current) : current).slice(0, limit))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user