Simplify notification badges, improve performance (#57)

Co-authored-by: Jon Staab <shtaab@gmail.com>
This commit is contained in:
hodlbod
2026-02-09 11:44:32 -08:00
committed by GitHub
parent 8f73fb85e9
commit c4f2f55617
19 changed files with 91 additions and 258 deletions
+4 -3
View File
@@ -1,17 +1,18 @@
<script lang="ts">
import {onMount} from "svelte"
import {max, formatTimestampRelative} from "@welshman/lib"
import {max, gt, formatTimestampRelative} from "@welshman/lib"
import {COMMENT} from "@welshman/util"
import {load} from "@welshman/net"
import {deriveArray, deriveEventsById} from "@welshman/store"
import type {TrustedEvent} from "@welshman/util"
import {repository} from "@welshman/app"
import {notifications} from "@app/util/notifications"
import {deriveChecked} from "@app/util/notifications"
import Reply from "@assets/icons/reply-2.svg?dataurl"
import Icon from "@lib/components/Icon.svelte"
const {url, path, event}: {url: string; path: string; event: TrustedEvent} = $props()
const checked = deriveChecked(path)
const filters = [{kinds: [COMMENT], "#E": [event.id]}]
const replies = deriveArray(deriveEventsById({repository, filters}))
const lastActive = $derived(max([...$replies, event].map(e => e.created_at)))
@@ -26,7 +27,7 @@
<span>{$replies.length} {$replies.length === 1 ? "reply" : "replies"}</span>
</div>
<div class="btn btn-neutral btn-xs relative hidden rounded-full sm:flex">
{#if $notifications.has(path)}
{#if gt(lastActive, $checked)}
<div class="h-2 w-2 rounded-full bg-primary"></div>
{/if}
Active {formatTimestampRelative(lastActive)}
+6 -22
View File
@@ -55,7 +55,6 @@
displayRoom,
} from "@app/core/state"
import {setSpaceNotifications} from "@app/core/commands"
import {notifications} from "@app/util/notifications"
import {pushModal} from "@app/util/modal"
import {makeSpacePath, makeChatPath} from "@app/util/routes"
@@ -227,42 +226,27 @@
<Icon icon={History} /> Recent Activity
</SecondaryNavItem>
{:else}
<SecondaryNavItem
{replaceState}
href={chatPath}
notification={$notifications.has(chatPath)}>
<SecondaryNavItem {replaceState} href={chatPath}>
<Icon icon={ChatRound} /> Chat
</SecondaryNavItem>
{/if}
{#if ENABLE_ZAPS && $spaceKinds.has(ZAP_GOAL)}
<SecondaryNavItem
{replaceState}
href={goalsPath}
notification={$notifications.has(goalsPath)}>
<SecondaryNavItem {replaceState} href={goalsPath}>
<Icon icon={StarFallMinimalistic} /> Goals
</SecondaryNavItem>
{/if}
{#if $spaceKinds.has(THREAD)}
<SecondaryNavItem
{replaceState}
href={threadsPath}
notification={$notifications.has(threadsPath)}>
<SecondaryNavItem {replaceState} href={threadsPath}>
<Icon icon={NotesMinimalistic} /> Threads
</SecondaryNavItem>
{/if}
{#if $spaceKinds.has(CLASSIFIED)}
<SecondaryNavItem
{replaceState}
href={classifiedsPath}
notification={$notifications.has(classifiedsPath)}>
<SecondaryNavItem {replaceState} href={classifiedsPath}>
<Icon icon={CaseMinimalistic} /> Classifieds
</SecondaryNavItem>
{/if}
{#if $spaceKinds.has(EVENT_TIME)}
<SecondaryNavItem
{replaceState}
href={calendarPath}
notification={$notifications.has(calendarPath)}>
<SecondaryNavItem {replaceState} href={calendarPath}>
<Icon icon={CalendarMinimalistic} /> Calendar
</SecondaryNavItem>
{/if}
@@ -272,7 +256,7 @@
<SecondaryNavHeader>Your Rooms</SecondaryNavHeader>
{/if}
{#each $userRooms as h, i (h)}
<SpaceMenuRoomItem {replaceState} notify {url} {h} />
<SpaceMenuRoomItem {replaceState} {url} {h} />
{/each}
{#if $otherRooms.length > 0}
<div class="h-2"></div>
@@ -3,15 +3,11 @@
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import SpaceMenu from "@app/components/SpaceMenu.svelte"
import {notifications} from "@app/util/notifications"
import {makeSpacePath} from "@app/util/routes"
import {pushDrawer} from "@app/util/modal"
import {deriveSocketStatus} from "@app/core/state"
const {url} = $props()
const path = makeSpacePath(url) + ":mobile"
const status = deriveSocketStatus(url)
const openMenu = () => pushDrawer(SpaceMenu, {url})
@@ -21,7 +17,5 @@
<Icon icon={MenuDots} />
{#if $status.theme !== "success"}
<div class="absolute right-0 top-0 -mr-1 -mt-1 h-2 w-2 rounded-full bg-{$status.theme}"></div>
{:else if $notifications.has(path)}
<div class="absolute right-0 top-0 -mr-1 -mt-1 h-2 w-2 rounded-full bg-primary"></div>
{/if}
</Button>
+2 -7
View File
@@ -5,17 +5,15 @@
import SecondaryNavItem from "@lib/components/SecondaryNavItem.svelte"
import RoomNameWithImage from "@app/components/RoomNameWithImage.svelte"
import {makeRoomPath} from "@app/util/routes"
import {notifications} from "@app/util/notifications"
import {deriveShouldNotify} from "@app/core/state"
interface Props {
url: any
h: any
notify?: boolean
replaceState?: boolean
}
const {url, h, notify = false, replaceState = false}: Props = $props()
const {url, h, replaceState = false}: Props = $props()
const path = makeRoomPath(url, h)
const shouldNotifyForSpace = deriveShouldNotify(url)
@@ -23,10 +21,7 @@
const showDifferenceIcon = $derived($shouldNotifyForRoom !== $shouldNotifyForSpace)
</script>
<SecondaryNavItem
href={path}
{replaceState}
notification={notify ? $notifications.has(path) : false}>
<SecondaryNavItem href={path} {replaceState}>
<RoomNameWithImage {url} {h} />
{#if showDifferenceIcon}
<Icon icon={$shouldNotifyForRoom ? VolumeLoud : VolumeCross} size={4} class="opacity-50" />