2026-08-07 21:05:17 +00:00
|
|
|
<script lang="ts">
|
|
|
|
|
import {derived} from "svelte/store"
|
2026-08-17 17:17:12 +00:00
|
|
|
import {getJson, setJson} from "@welshman/lib"
|
2026-08-17 15:42:14 +00:00
|
|
|
import {EVENT_TIME, ZAP_GOAL, THREAD, CLASSIFIED, PINBOARD, POLL, LONG_FORM} from "@welshman/util"
|
2026-08-07 21:05:17 +00:00
|
|
|
import Magnifier from "@assets/icons/magnifier.svg?dataurl"
|
|
|
|
|
import UsersGroup from "@assets/icons/users-group-rounded.svg?dataurl"
|
|
|
|
|
import Home from "@assets/icons/home.svg?dataurl"
|
|
|
|
|
import GalleryWide from "@assets/icons/gallery-wide.svg?dataurl"
|
|
|
|
|
import ChatRound from "@assets/icons/chat-round.svg?dataurl"
|
|
|
|
|
import History from "@assets/icons/history.svg?dataurl"
|
|
|
|
|
import StarFallMinimalistic from "@assets/icons/star-fall-minimalistic-2.svg?dataurl"
|
|
|
|
|
import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl"
|
|
|
|
|
import CalendarMinimalistic from "@assets/icons/calendar-minimalistic.svg?dataurl"
|
|
|
|
|
import CaseMinimalistic from "@assets/icons/case-minimalistic.svg?dataurl"
|
2026-08-17 15:42:14 +00:00
|
|
|
import DocumentText from "@assets/icons/document-text.svg?dataurl"
|
2026-08-07 21:05:17 +00:00
|
|
|
import Revote from "@assets/icons/revote.svg?dataurl"
|
|
|
|
|
import Icon from "@lib/components/Icon.svelte"
|
|
|
|
|
import SecondaryNavItem from "@lib/components/SecondaryNavItem.svelte"
|
|
|
|
|
import SpaceSearch from "@app/components/SpaceSearch.svelte"
|
|
|
|
|
import {relays} from "@app/core"
|
|
|
|
|
import {ENABLE_ZAPS} from "@app/env"
|
|
|
|
|
import {CONTENT_KINDS} from "@app/content"
|
|
|
|
|
import {deriveSpaceSupportedMethods} from "@app/management"
|
|
|
|
|
import {deriveEventsForUrl} from "@app/repository"
|
|
|
|
|
import {makeSpacePath} from "@app/routes"
|
|
|
|
|
import {notifications} from "@app/notifications"
|
|
|
|
|
import {pushModal} from "@app/modal"
|
|
|
|
|
|
|
|
|
|
type Props = {
|
|
|
|
|
url: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const {url}: Props = $props()
|
|
|
|
|
|
|
|
|
|
const relay = $relays.one(url)
|
|
|
|
|
const chatPath = makeSpacePath(url, "chat")
|
|
|
|
|
const goalsPath = makeSpacePath(url, "goals")
|
|
|
|
|
const threadsPath = makeSpacePath(url, "threads")
|
|
|
|
|
const classifiedsPath = makeSpacePath(url, "classifieds")
|
2026-08-17 15:42:14 +00:00
|
|
|
const articlesPath = makeSpacePath(url, "articles")
|
2026-08-07 21:05:17 +00:00
|
|
|
const calendarPath = makeSpacePath(url, "calendar")
|
|
|
|
|
const pollsPath = makeSpacePath(url, "polls")
|
|
|
|
|
|
2026-08-17 17:17:12 +00:00
|
|
|
// Content events aren't retained across page loads, so seed with the kinds seen last time
|
|
|
|
|
// to keep the nav from re-populating as they load in the background.
|
|
|
|
|
const spaceKindsKey = `space-kinds:${url}`
|
|
|
|
|
const cachedKinds: number[] = getJson(spaceKindsKey) ?? []
|
|
|
|
|
|
2026-08-07 21:05:17 +00:00
|
|
|
const spaceKinds = derived(
|
|
|
|
|
deriveEventsForUrl(url, [{kinds: CONTENT_KINDS}]),
|
2026-08-17 17:17:12 +00:00
|
|
|
$events => new Set([...cachedKinds, ...$events.map(e => e.kind)]),
|
2026-08-07 21:05:17 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const hasNip29 = $derived($relay?.hasNip(29) ?? false)
|
|
|
|
|
const supportedMethods = deriveSpaceSupportedMethods(url)
|
2026-08-17 17:17:12 +00:00
|
|
|
const showLibrary = $derived($spaceKinds.has(PINBOARD) || $supportedMethods.includes("signevent"))
|
2026-08-07 21:05:17 +00:00
|
|
|
|
|
|
|
|
const openSearch = () => pushModal(SpaceSearch, {url})
|
2026-08-17 17:17:12 +00:00
|
|
|
|
|
|
|
|
$effect(() => setJson(spaceKindsKey, [...$spaceKinds]))
|
2026-08-07 21:05:17 +00:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<SecondaryNavItem href={makeSpacePath(url, "about")}>
|
|
|
|
|
<Icon icon={Home} /> Space Details
|
|
|
|
|
</SecondaryNavItem>
|
|
|
|
|
{#if hasNip29}
|
|
|
|
|
<SecondaryNavItem href={makeSpacePath(url, "recent")}>
|
|
|
|
|
<Icon icon={History} /> Recent Activity
|
|
|
|
|
</SecondaryNavItem>
|
|
|
|
|
{:else}
|
|
|
|
|
<SecondaryNavItem href={chatPath} notification={$notifications.has(chatPath)}>
|
|
|
|
|
<Icon icon={ChatRound} /> Chat
|
|
|
|
|
</SecondaryNavItem>
|
|
|
|
|
{/if}
|
|
|
|
|
<SecondaryNavItem href={makeSpacePath(url, "directory")}>
|
|
|
|
|
<Icon icon={UsersGroup} /> Directory
|
|
|
|
|
</SecondaryNavItem>
|
|
|
|
|
{#if showLibrary}
|
|
|
|
|
<SecondaryNavItem href={makeSpacePath(url, "library")}>
|
|
|
|
|
<Icon icon={GalleryWide} /> Library
|
|
|
|
|
</SecondaryNavItem>
|
|
|
|
|
{/if}
|
|
|
|
|
{#if ENABLE_ZAPS && $spaceKinds.has(ZAP_GOAL)}
|
2026-08-14 15:37:27 +00:00
|
|
|
<SecondaryNavItem href={goalsPath} notification={$notifications.has(goalsPath)}>
|
2026-08-07 21:05:17 +00:00
|
|
|
<Icon icon={StarFallMinimalistic} /> Goals
|
|
|
|
|
</SecondaryNavItem>
|
|
|
|
|
{/if}
|
|
|
|
|
{#if $spaceKinds.has(THREAD)}
|
2026-08-14 15:37:27 +00:00
|
|
|
<SecondaryNavItem href={threadsPath} notification={$notifications.has(threadsPath)}>
|
2026-08-07 21:05:17 +00:00
|
|
|
<Icon icon={NotesMinimalistic} /> Threads
|
|
|
|
|
</SecondaryNavItem>
|
|
|
|
|
{/if}
|
2026-08-17 15:42:14 +00:00
|
|
|
{#if $spaceKinds.has(LONG_FORM)}
|
|
|
|
|
<SecondaryNavItem href={articlesPath} notification={$notifications.has(articlesPath)}>
|
|
|
|
|
<Icon icon={DocumentText} /> Articles
|
|
|
|
|
</SecondaryNavItem>
|
|
|
|
|
{/if}
|
2026-08-07 21:05:17 +00:00
|
|
|
{#if $spaceKinds.has(CLASSIFIED)}
|
2026-08-14 15:37:27 +00:00
|
|
|
<SecondaryNavItem href={classifiedsPath} notification={$notifications.has(classifiedsPath)}>
|
2026-08-07 21:05:17 +00:00
|
|
|
<Icon icon={CaseMinimalistic} /> Classifieds
|
|
|
|
|
</SecondaryNavItem>
|
|
|
|
|
{/if}
|
|
|
|
|
{#if $spaceKinds.has(EVENT_TIME)}
|
2026-08-14 15:37:27 +00:00
|
|
|
<SecondaryNavItem href={calendarPath} notification={$notifications.has(calendarPath)}>
|
2026-08-07 21:05:17 +00:00
|
|
|
<Icon icon={CalendarMinimalistic} /> Calendar
|
|
|
|
|
</SecondaryNavItem>
|
|
|
|
|
{/if}
|
|
|
|
|
{#if $spaceKinds.has(POLL)}
|
2026-08-14 15:37:27 +00:00
|
|
|
<SecondaryNavItem href={pollsPath} notification={$notifications.has(pollsPath)}>
|
2026-08-07 21:05:17 +00:00
|
|
|
<Icon icon={Revote} /> Polls
|
|
|
|
|
</SecondaryNavItem>
|
|
|
|
|
{/if}
|
|
|
|
|
{#if hasNip29}
|
|
|
|
|
<SecondaryNavItem onclick={openSearch}>
|
|
|
|
|
<Icon icon={Magnifier} /> Search
|
|
|
|
|
</SecondaryNavItem>
|
|
|
|
|
{/if}
|