Simplify and optimize notifications

This commit is contained in:
Jon Staab
2024-12-16 11:24:10 -08:00
parent 85e5413951
commit 3d3ffaf406
12 changed files with 120 additions and 151 deletions
+3 -4
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import {onMount} from "svelte"
import {page} from "$app/stores"
import {remove, assoc} from "@welshman/lib"
import {remove} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util"
import {pubkey, loadInboxRelaySelections} from "@welshman/app"
import {fade} from "@lib/transition"
@@ -10,7 +10,7 @@
import ProfileCircle from "@app/components/ProfileCircle.svelte"
import ProfileCircles from "@app/components/ProfileCircles.svelte"
import {makeChatPath} from "@app/routes"
import {CHAT_FILTERS, deriveNotification} from "@app/notifications"
import {notifications} from "@app/notifications"
export let id: string
export let pubkeys: string[]
@@ -19,7 +19,6 @@
const others = remove($pubkey!, pubkeys)
const active = $page.params.chat === id
const path = makeChatPath(pubkeys)
const notification = deriveNotification(path, CHAT_FILTERS.map(assoc("authors", pubkeys)))
onMount(() => {
for (const pk of others) {
@@ -47,7 +46,7 @@
</p>
{/if}
</div>
{#if !active && $notification}
{#if !active && $notifications.has(path)}
<div class="h-2 w-2 rounded-full bg-primary" transition:fade />
{/if}
</div>
+2 -3
View File
@@ -22,7 +22,7 @@
deriveUserRooms,
deriveOtherRooms,
} from "@app/state"
import {deriveNotification, THREAD_FILTERS} from "@app/notifications"
import {notifications} from "@app/notifications"
import {pullConservatively} from "@app/requests"
import {pushModal} from "@app/modal"
import {makeSpacePath} from "@app/routes"
@@ -30,7 +30,6 @@
export let url
const threadsPath = makeSpacePath(url, "threads")
const threadsNotification = deriveNotification(threadsPath, THREAD_FILTERS, url)
const userRooms = deriveUserRooms(url)
const otherRooms = deriveOtherRooms(url)
@@ -114,7 +113,7 @@
<SecondaryNavItem href={makeSpacePath(url)}>
<Icon icon="home-smile" /> Home
</SecondaryNavItem>
<SecondaryNavItem href={threadsPath} notification={$threadsNotification}>
<SecondaryNavItem href={threadsPath} notification={$notifications.has(threadsPath)}>
<Icon icon="notes-minimalistic" /> Threads
</SecondaryNavItem>
<div class="h-2" />
+5 -32
View File
@@ -1,48 +1,21 @@
<script lang="ts">
import {page} from "$app/stores"
import {derived} from "svelte/store"
import {max} from "@welshman/lib"
import {matchFilter, MESSAGE} from "@welshman/util"
import {pubkey} from "@welshman/app"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import MenuSpace from "@app/components/MenuSpace.svelte"
import {checked, getNotification, deriveNotification, THREAD_FILTERS} from "@app/notifications"
import {userMembership, getMembershipRoomsByUrl, deriveEventsForUrl, GENERAL} from "@app/state"
import {makeRoomPath, makeSpacePath} from "@app/routes"
import {notifications} from "@app/notifications"
import {makeSpacePath} from "@app/routes"
import {pushDrawer} from "@app/modal"
export let url
const path = makeSpacePath(url)
const openMenu = () => pushDrawer(MenuSpace, {url})
const events = deriveEventsForUrl(url, [{kinds: [MESSAGE]}])
const threadsPath = makeSpacePath(url, "threads")
const threadsNotification = deriveNotification(threadsPath, THREAD_FILTERS, url)
const notification = derived(
[page, events, checked, userMembership],
([$page, $events, $checked, $userMembership]) =>
getMembershipRoomsByUrl(url, $userMembership)
.concat(GENERAL)
.some(room => {
const path = makeRoomPath(url, room)
if ($page.url.pathname === path) return false
const lastChecked = max([$checked["*"], $checked[path]])
const roomEvents = $events.filter(e => matchFilter({"#h": [room]}, e))
return getNotification($pubkey, lastChecked, roomEvents)
}),
)
</script>
<Button on:click={openMenu} class="btn btn-neutral btn-sm relative md:hidden">
<Icon icon="menu-dots" />
{#if $threadsNotification || $notification}
{#if $notifications.has(path)}
<div class="absolute right-0 top-0 -mr-1 -mt-1 h-2 w-2 rounded-full bg-primary" />
{/if}
</Button>
+2 -6
View File
@@ -1,11 +1,10 @@
<script lang="ts">
import {readable} from "svelte/store"
import Icon from "@lib/components/Icon.svelte"
import SecondaryNavItem from "@lib/components/SecondaryNavItem.svelte"
import ChannelName from "@app/components/ChannelName.svelte"
import {makeSpacePath} from "@app/routes"
import {deriveChannel, channelIsLocked} from "@app/state"
import {deriveNotification, getRoomFilters} from "@app/notifications"
import {notifications} from "@app/notifications"
export let url
export let room
@@ -13,12 +12,9 @@
const path = makeSpacePath(url, room)
const channel = deriveChannel(url, room)
const notification = notify
? deriveNotification(path, getRoomFilters(room), url)
: readable(false)
</script>
<SecondaryNavItem href={path} notification={$notification}>
<SecondaryNavItem href={path} notification={notify ? $notifications.has(path) : false}>
{#if channelIsLocked($channel)}
<Icon icon="lock" size={4} />
{:else}
+2 -2
View File
@@ -5,7 +5,7 @@
import RelayName from "@app/components/RelayName.svelte"
import RelayDescription from "@app/components/RelayDescription.svelte"
import {makeSpacePath} from "@app/routes"
import {inactiveSpacesNotifications} from "@app/notifications"
import {inactiveNotifications} from "@app/notifications"
export let url
@@ -17,7 +17,7 @@
<div slot="icon"><SpaceAvatar {url} /></div>
<div slot="title" class="flex gap-1">
<RelayName {url} />
{#if $inactiveSpacesNotifications.includes(path)}
{#if $inactiveNotifications.has(path)}
<div class="relative top-1 h-2 w-2 rounded-full bg-primary" />
{/if}
</div>
+14 -12
View File
@@ -17,20 +17,22 @@
PLATFORM_LOGO,
} from "@app/state"
import {pushModal} from "@app/modal"
import {deriveNotification, inactiveSpacesNotifications, CHAT_FILTERS} from "@app/notifications"
const chatNotification = deriveNotification("/chat", CHAT_FILTERS)
import {makeSpacePath} from "@app/routes"
import {notifications, inactiveNotifications} from "@app/notifications"
const addSpace = () => pushModal(SpaceAdd)
const showSpacesMenu = () =>
getMembershipUrls($userMembership).length > 0 ? pushModal(MenuSpaces) : pushModal(SpaceAdd)
const showSpacesMenu = () => (spacePaths.length > 0 ? pushModal(MenuSpaces) : pushModal(SpaceAdd))
const showSettingsMenu = () => pushModal(MenuSettings)
const openNotes = () => ($canDecrypt ? goto("/notes") : pushModal(ChatEnable, {next: "/notes"}))
const openChat = () => ($canDecrypt ? goto("/chat") : pushModal(ChatEnable, {next: "/chat"}))
$: spaceUrls = getMembershipUrls($userMembership)
$: spacePaths = spaceUrls.map(url => makeSpacePath(url))
$: anySpaceNotifications = spacePaths.some(path => $inactiveNotifications.has(path))
</script>
<div class="relative z-nav hidden w-14 flex-shrink-0 bg-base-200 pt-4 md:block">
@@ -43,7 +45,7 @@
<Avatar src={PLATFORM_LOGO} class="!h-10 !w-10" />
</PrimaryNavItem>
<Divider />
{#each getMembershipUrls($userMembership) as url (url)}
{#each spaceUrls as url (url)}
<PrimaryNavItemSpace {url} />
{/each}
<PrimaryNavItem title="Add Space" on:click={addSpace} class="tooltip-right">
@@ -66,7 +68,7 @@
title="Messages"
on:click={openChat}
class="tooltip-right"
notification={$chatNotification}>
notification={$notifications.has("/chat")}>
<Avatar icon="letter" class="!h-10 !w-10" />
</PrimaryNavItem>
<PrimaryNavItem title="Search" href="/people" class="tooltip-right">
@@ -88,13 +90,13 @@
<PrimaryNavItem title="Notes" href="/notes">
<Avatar icon="notes-minimalistic" class="!h-10 !w-10" />
</PrimaryNavItem>
<PrimaryNavItem title="Messages" on:click={openChat} notification={$chatNotification}>
<PrimaryNavItem
title="Messages"
on:click={openChat}
notification={$notifications.has("/chat")}>
<Avatar icon="letter" class="!h-10 !w-10" />
</PrimaryNavItem>
<PrimaryNavItem
title="Spaces"
on:click={showSpacesMenu}
notification={$inactiveSpacesNotifications.length > 0}>
<PrimaryNavItem title="Spaces" on:click={showSpacesMenu} notification={anySpaceNotifications}>
<Avatar icon="settings-minimalistic" class="!h-10 !w-10" />
</PrimaryNavItem>
</div>
@@ -3,7 +3,7 @@
import PrimaryNavItem from "@lib/components/PrimaryNavItem.svelte"
import SpaceAvatar from "@app/components/SpaceAvatar.svelte"
import {makeSpacePath} from "@app/routes"
import {spacesNotifications} from "@app/notifications"
import {notifications} from "@app/notifications"
export let url
@@ -14,6 +14,6 @@
title={displayRelayUrl(url)}
href={path}
class="tooltip-right"
notification={$spacesNotifications.includes(path)}>
notification={$notifications.has(path)}>
<SpaceAvatar {url} />
</PrimaryNavItem>
+2 -3
View File
@@ -15,7 +15,7 @@
import ThunkStatus from "@app/components/ThunkStatus.svelte"
import ThreadMenu from "@app/components/ThreadMenu.svelte"
import {publishDelete, publishReaction} from "@app/commands"
import {deriveNotification} from "@app/notifications"
import {notifications} from "@app/notifications"
import {makeSpacePath} from "@app/routes"
import {PROTECTED} from "@app/state"
@@ -28,7 +28,6 @@
const path = makeSpacePath(url, "threads", event.id)
const filters = [{kinds: [COMMENT], "#E": [event.id]}]
const replies = deriveEvents(repository, {filters})
const notification = deriveNotification(path, filters, url)
const showPopover = () => popover.show()
@@ -70,7 +69,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 $notification}
{#if $notifications.has(path)}
<div class="h-2 w-2 rounded-full bg-primary" />
{/if}
Active {formatTimestampRelative(lastActive)}