feat: implement bookmarks page
This commit is contained in:
@@ -33,6 +33,7 @@ import {
|
||||
ROOMS,
|
||||
COMMENT,
|
||||
APP_DATA,
|
||||
asDecryptedEvent,
|
||||
isSignedEvent,
|
||||
makeEvent,
|
||||
normalizeRelayUrl,
|
||||
@@ -41,11 +42,14 @@ import {
|
||||
removeFromListByPredicate,
|
||||
updateList,
|
||||
getTag,
|
||||
getTagValue,
|
||||
getListTags,
|
||||
getRelayTagValues,
|
||||
getEventTagValues,
|
||||
toNostrURI,
|
||||
RelayMode,
|
||||
getTagValues,
|
||||
readList,
|
||||
uploadBlob,
|
||||
canUploadBlob,
|
||||
encryptFile,
|
||||
@@ -167,6 +171,153 @@ export const broadcastUserData = async (relays: string[]) => {
|
||||
|
||||
// List updates
|
||||
|
||||
const BOOKMARKS = 10003
|
||||
const BOOKMARK_LISTS = 30003
|
||||
|
||||
const parseListKey = (key: string) => {
|
||||
const [kind, ...rest] = key.split(":")
|
||||
return {
|
||||
kind: parseInt(kind),
|
||||
d: rest.join(":"),
|
||||
}
|
||||
}
|
||||
|
||||
const getUserBookmarkList = (key = `${BOOKMARKS}:`) => {
|
||||
const author = pubkey.get()
|
||||
const {kind, d} = parseListKey(key)
|
||||
|
||||
if (!author) {
|
||||
return makeList({kind})
|
||||
}
|
||||
|
||||
const latest = first(
|
||||
repository
|
||||
.query([{kinds: [kind], authors: [author]}])
|
||||
.filter(event => getTagValue("d", event.tags) === d),
|
||||
)
|
||||
|
||||
return latest ? readList(asDecryptedEvent(latest)) : makeList({kind})
|
||||
}
|
||||
|
||||
export const createBookmarkList = async (title: string) => {
|
||||
const d = title.trim()
|
||||
|
||||
if (!d) {
|
||||
return
|
||||
}
|
||||
|
||||
const existing = getUserBookmarkList(`${BOOKMARK_LISTS}:${d}`)
|
||||
|
||||
if (existing.event?.id) {
|
||||
return
|
||||
}
|
||||
|
||||
const list = makeList({kind: BOOKMARK_LISTS})
|
||||
const event = await updateList(list, {publicTags: [["d", d]]}).reconcile(nip44EncryptToSelf)
|
||||
const relays = uniq([...Router.get().FromUser().getUrls(), ...getRelayTagValues(event.tags)])
|
||||
|
||||
return publishThunk({event, relays})
|
||||
}
|
||||
|
||||
export const addEventBookmark = async (target: TrustedEvent, key = `${BOOKMARKS}:`) => {
|
||||
const list = getUserBookmarkList(key)
|
||||
const {d} = parseListKey(key)
|
||||
|
||||
if (d && !list.event?.id) {
|
||||
return
|
||||
}
|
||||
|
||||
const existing = new Set(getEventTagValues(getListTags(list)))
|
||||
|
||||
if (existing.has(target.id)) {
|
||||
return
|
||||
}
|
||||
|
||||
const event = await addToListPublicly(list, ["e", target.id]).reconcile(nip44EncryptToSelf)
|
||||
const relays = uniq([
|
||||
...Router.get().FromUser().getUrls(),
|
||||
...Router.get().Event(target).limit(3).getUrls(),
|
||||
...getRelayTagValues(event.tags),
|
||||
])
|
||||
|
||||
return publishThunk({event, relays})
|
||||
}
|
||||
|
||||
export const removeEventBookmark = async (target: TrustedEvent, key = `${BOOKMARKS}:`) => {
|
||||
const list = getUserBookmarkList(key)
|
||||
const {d} = parseListKey(key)
|
||||
|
||||
if (d && !list.event?.id) {
|
||||
return
|
||||
}
|
||||
|
||||
const targetD = getTagValue("d", target.tags)
|
||||
const targetAddress = targetD ? `${target.kind}:${target.pubkey}:${targetD}` : undefined
|
||||
const hasMatch = getListTags(list).some(
|
||||
tag =>
|
||||
(tag[0] === "e" && tag[1] === target.id) ||
|
||||
(targetAddress !== undefined && tag[0] === "a" && tag[1] === targetAddress),
|
||||
)
|
||||
|
||||
if (!hasMatch) {
|
||||
return
|
||||
}
|
||||
|
||||
const event = await removeFromListByPredicate(
|
||||
list,
|
||||
tag =>
|
||||
(tag[0] === "e" && tag[1] === target.id) ||
|
||||
(targetAddress !== undefined && tag[0] === "a" && tag[1] === targetAddress),
|
||||
).reconcile(nip44EncryptToSelf)
|
||||
const relays = uniq([
|
||||
...INDEXER_RELAYS,
|
||||
...getRelayTagValues(event.tags),
|
||||
...Router.get().Event(target).limit(3).getUrls(),
|
||||
])
|
||||
|
||||
return publishThunk({event, relays})
|
||||
}
|
||||
|
||||
export const deleteBookmarkList = async (key: string) => {
|
||||
const list = getUserBookmarkList(key)
|
||||
const {kind, d} = parseListKey(key)
|
||||
|
||||
if (kind !== BOOKMARK_LISTS || !d || !list.event) {
|
||||
return
|
||||
}
|
||||
|
||||
const relays = uniq([...INDEXER_RELAYS, ...getRelayTagValues(list.event.tags)])
|
||||
const address = `${kind}:${list.event.pubkey}:${d}`
|
||||
|
||||
return publishDelete({protect: false, event: list.event, tags: [["a", address]], relays})
|
||||
}
|
||||
|
||||
export const renameBookmarkList = async (key: string, title: string) => {
|
||||
const list = getUserBookmarkList(key)
|
||||
const {kind, d} = parseListKey(key)
|
||||
const nextD = title.trim()
|
||||
|
||||
if (kind !== BOOKMARK_LISTS || !d || !nextD || !list.event) {
|
||||
return
|
||||
}
|
||||
|
||||
if (nextD === d) {
|
||||
return
|
||||
}
|
||||
|
||||
const existing = getUserBookmarkList(`${BOOKMARK_LISTS}:${nextD}`)
|
||||
|
||||
if (existing.event?.id && existing.event.id !== list.event.id) {
|
||||
return
|
||||
}
|
||||
|
||||
const publicTags = [["d", nextD], ...list.publicTags.filter(tag => tag[0] !== "d")]
|
||||
const event = await updateList(list, {publicTags}).reconcile(nip44EncryptToSelf)
|
||||
const relays = uniq([...INDEXER_RELAYS, ...getRelayTagValues(list.event.tags)])
|
||||
|
||||
return publishThunk({event, relays})
|
||||
}
|
||||
|
||||
export const addSpaceMembership = async (url: string) => {
|
||||
const list = get(userGroupList) || makeList({kind: ROOMS})
|
||||
const event = await addToListPublicly(list, ["r", url]).reconcile(nip44EncryptToSelf)
|
||||
|
||||
Reference in New Issue
Block a user