fix: stabilize list loading and show correct list count
This commit is contained in:
@@ -1,6 +1,18 @@
|
||||
<script lang="ts">
|
||||
import type {Snippet} from "svelte"
|
||||
import {userProfile} from "@welshman/app"
|
||||
import {onMount} from "svelte"
|
||||
import {uniqBy} from "@welshman/lib"
|
||||
import type {TrustedEvent} from "@welshman/util"
|
||||
import {
|
||||
Address,
|
||||
DELETE,
|
||||
getAddress,
|
||||
getTagValue,
|
||||
getTagValues,
|
||||
sortEventsDesc,
|
||||
} from "@welshman/util"
|
||||
import {load} from "@welshman/net"
|
||||
import {pubkey, userProfile} from "@welshman/app"
|
||||
import Letter from "@assets/icons/letter.svg?dataurl"
|
||||
import Bookmark from "@assets/icons/bookmark.svg?dataurl"
|
||||
import Magnifier from "@assets/icons/magnifier.svg?dataurl"
|
||||
@@ -8,11 +20,19 @@
|
||||
import UserRounded from "@assets/icons/user-rounded.svg?dataurl"
|
||||
import Settings from "@assets/icons/settings.svg?dataurl"
|
||||
import ImageIcon from "@lib/components/ImageIcon.svelte"
|
||||
import Divider from "@lib/components/Divider.svelte"
|
||||
import MenuSettings from "@app/components/MenuSettings.svelte"
|
||||
import PrimaryNavItem from "@lib/components/PrimaryNavItem.svelte"
|
||||
import PrimaryNavSpaces from "@app/components/PrimaryNavSpaces.svelte"
|
||||
import {userSpaceUrls, PLATFORM_RELAYS} from "@app/core/state"
|
||||
import {
|
||||
BOOKMARKS,
|
||||
BOOKMARK_LISTS,
|
||||
deriveEvents,
|
||||
INDEXER_RELAYS,
|
||||
loadUserBookmarkCollections,
|
||||
loadUserBookmarkList,
|
||||
userSpaceUrls,
|
||||
PLATFORM_RELAYS,
|
||||
} from "@app/core/state"
|
||||
import {pushModal} from "@app/util/modal"
|
||||
import {notifications} from "@app/util/notifications"
|
||||
import {goToChat, makeSpacePath} from "@app/util/routes"
|
||||
@@ -30,18 +50,90 @@
|
||||
const anySpaceNotifications = $derived(
|
||||
$userSpaceUrls.some(p => $notifications.has(makeSpacePath(p))),
|
||||
)
|
||||
|
||||
const bookmarkListEvents = deriveEvents([{kinds: [BOOKMARKS, BOOKMARK_LISTS, DELETE]}])
|
||||
let loadedBookmarkCountPubkey: string | undefined = $state()
|
||||
|
||||
const getListKey = (event: TrustedEvent) =>
|
||||
event.kind === BOOKMARKS
|
||||
? new Address(BOOKMARKS, event.pubkey, "").toString()
|
||||
: getAddress(event)
|
||||
|
||||
const isDeletedList = (event: TrustedEvent, deleteEvents: TrustedEvent[]) => {
|
||||
const address =
|
||||
event.kind === BOOKMARKS
|
||||
? new Address(BOOKMARKS, event.pubkey, "").toString()
|
||||
: `${event.kind}:${event.pubkey}:${getTagValue("d", event.tags) || ""}`
|
||||
|
||||
return deleteEvents.some(deleteEvent => {
|
||||
if (deleteEvent.created_at < event.created_at) {
|
||||
return false
|
||||
}
|
||||
|
||||
return (
|
||||
getTagValues("e", deleteEvent.tags).includes(event.id) ||
|
||||
getTagValues("a", deleteEvent.tags).includes(address)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const bookmarkListCount = $derived.by(() => {
|
||||
if (!$pubkey) {
|
||||
return 0
|
||||
}
|
||||
|
||||
const ownEvents = sortEventsDesc($bookmarkListEvents).filter(event => event.pubkey === $pubkey)
|
||||
const deleteEvents = ownEvents.filter(event => event.kind === DELETE)
|
||||
const listEvents = ownEvents.filter(
|
||||
event => event.kind === BOOKMARKS || event.kind === BOOKMARK_LISTS,
|
||||
)
|
||||
const visibleLists = uniqBy(getListKey, listEvents).filter(
|
||||
event => !isDeletedList(event, deleteEvents),
|
||||
)
|
||||
const hasSavedItems = visibleLists.some(event => event.kind === BOOKMARKS)
|
||||
|
||||
return visibleLists.length + (hasSavedItems ? 0 : 1)
|
||||
})
|
||||
|
||||
const loadBookmarkCountData = async () => {
|
||||
if (!$pubkey || loadedBookmarkCountPubkey === $pubkey) {
|
||||
return
|
||||
}
|
||||
|
||||
loadedBookmarkCountPubkey = $pubkey
|
||||
|
||||
await Promise.all([
|
||||
loadUserBookmarkList(),
|
||||
loadUserBookmarkCollections(),
|
||||
load({
|
||||
relays: INDEXER_RELAYS,
|
||||
filters: [{kinds: [DELETE], authors: [$pubkey]}],
|
||||
}),
|
||||
])
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
void loadBookmarkCountData()
|
||||
})
|
||||
|
||||
$effect(() => {
|
||||
if ($pubkey && loadedBookmarkCountPubkey !== $pubkey) {
|
||||
void loadBookmarkCountData()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="ml-sai mt-sai mb-sai relative z-popover isolate hidden w-14 shrink-0 bg-base-200 pt-2 md:block">
|
||||
<div class="flex h-full flex-col" class:justify-between={PLATFORM_RELAYS.length === 0}>
|
||||
<PrimaryNavSpaces />
|
||||
{#if PLATFORM_RELAYS.length > 0}
|
||||
<Divider />
|
||||
{/if}
|
||||
<div class="flex flex-col">
|
||||
<PrimaryNavItem title="Bookmarks" href="/bookmarks" prefix="/bookmarks">
|
||||
<ImageIcon alt="Bookmarks" src={Bookmark} size={8} />
|
||||
<div class="relative">
|
||||
<ImageIcon alt="Bookmarks" src={Bookmark} size={8} />
|
||||
<span class="badge badge-xs badge-neutral absolute -right-2 -top-2"
|
||||
>{bookmarkListCount}</span>
|
||||
</div>
|
||||
</PrimaryNavItem>
|
||||
<PrimaryNavItem title="Settings" href="/settings/profile" prefix="/settings">
|
||||
{#if $userProfile?.picture}
|
||||
@@ -83,7 +175,11 @@
|
||||
<ImageIcon alt="Messages" src={Letter} size={8} />
|
||||
</PrimaryNavItem>
|
||||
<PrimaryNavItem title="Bookmarks" href="/bookmarks" prefix="/bookmarks">
|
||||
<ImageIcon alt="Bookmarks" src={Bookmark} size={8} />
|
||||
<div class="relative">
|
||||
<ImageIcon alt="Bookmarks" src={Bookmark} size={8} />
|
||||
<span class="badge badge-xs badge-neutral absolute -right-2 -top-2"
|
||||
>{bookmarkListCount}</span>
|
||||
</div>
|
||||
</PrimaryNavItem>
|
||||
{#if PLATFORM_RELAYS.length !== 1}
|
||||
<PrimaryNavItem title="Spaces" href="/spaces" notification={anySpaceNotifications}>
|
||||
|
||||
Reference in New Issue
Block a user