flotilla/src/app/util/routes.ts

162 lines
4 KiB
TypeScript
Raw Normal View History

2024-08-16 17:50:38 +00:00
import type {Page} from "@sveltejs/kit"
import {get} from "svelte/store"
2025-06-05 20:37:50 +00:00
import * as nip19 from "nostr-tools/nip19"
2025-06-05 17:55:16 +00:00
import {goto} from "$app/navigation"
import {nthEq, sleep} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util"
2025-10-06 18:23:19 +00:00
import {tracker, relaysByUrl} from "@welshman/app"
2025-06-05 17:55:16 +00:00
import {scrollToEvent} from "@lib/html"
2025-02-06 17:29:30 +00:00
import {identity} from "@welshman/lib"
2025-06-05 17:55:16 +00:00
import {
getTagValue,
DIRECT_MESSAGE,
DIRECT_MESSAGE_FILE,
MESSAGE,
THREAD,
2025-07-07 22:28:36 +00:00
ZAP_GOAL,
2025-06-05 17:55:16 +00:00
EVENT_TIME,
getPubkeyTagValues,
2025-06-05 17:55:16 +00:00
} from "@welshman/util"
import {
makeChatId,
entityLink,
decodeRelay,
encodeRelay,
userSpaceUrls,
2025-10-06 18:23:19 +00:00
hasNip29,
ROOM,
} from "@app/core/state"
2025-02-06 17:29:30 +00:00
export const makeSpacePath = (url: string, ...extra: (string | undefined)[]) => {
2024-10-21 17:30:12 +00:00
let path = `/spaces/${encodeRelay(url)}`
2024-10-31 19:24:40 +00:00
if (extra.length > 0) {
2025-02-06 17:29:30 +00:00
path +=
"/" +
extra
.filter(identity)
.map(s => encodeURIComponent(s as string))
.join("/")
2025-10-06 18:23:19 +00:00
} else {
const relay = relaysByUrl.get().get(url)
if (hasNip29(relay)) {
path += "/recent"
} else {
path += "/chat"
}
}
return path
}
2024-08-15 19:08:07 +00:00
export const makeChatPath = (pubkeys: string[]) => `/chat/${makeChatId(pubkeys)}`
2024-10-03 22:28:06 +00:00
2025-10-30 22:33:34 +00:00
export const makeRoomPath = (url: string, h: string) => `/spaces/${encodeRelay(url)}/${h}`
2024-10-23 23:41:11 +00:00
2025-06-25 00:36:14 +00:00
export const makeSpaceChatPath = (url: string) => makeRoomPath(url, "chat")
2025-07-07 22:28:36 +00:00
export const makeGoalPath = (url: string, eventId?: string) => makeSpacePath(url, "goals", eventId)
2025-02-06 17:29:30 +00:00
export const makeThreadPath = (url: string, eventId?: string) =>
makeSpacePath(url, "threads", eventId)
2024-12-16 18:30:42 +00:00
2025-02-06 17:29:30 +00:00
export const makeCalendarPath = (url: string, eventId?: string) =>
makeSpacePath(url, "calendar", eventId)
2024-10-23 21:20:24 +00:00
2024-08-16 18:12:14 +00:00
export const getPrimaryNavItem = ($page: Page) => $page.route?.id?.split("/")[1]
export const getPrimaryNavItemIndex = ($page: Page) => {
const urls = get(userSpaceUrls)
switch (getPrimaryNavItem($page)) {
2024-08-16 17:50:38 +00:00
case "discover":
return urls.length + 2
2024-09-11 18:09:25 +00:00
case "spaces": {
2025-10-13 20:35:02 +00:00
const routeUrl = decodeRelay($page.params.relay || "")
return urls.findIndex(url => url === routeUrl) + 1
2024-09-11 18:09:25 +00:00
}
2024-08-16 17:50:38 +00:00
case "settings":
return urls.length + 3
default:
return 0
}
}
2025-06-05 17:55:16 +00:00
2025-06-19 17:22:17 +00:00
export const goToEvent = async (event: TrustedEvent, options: Record<string, any> = {}) => {
const urls = Array.from(tracker.getRelays(event.id))
const path = await getEventPath(event, urls)
2025-06-05 17:55:16 +00:00
if (path.includes("://")) {
window.open(path)
} else {
goto(path, options)
2025-06-19 17:22:17 +00:00
await sleep(300)
await scrollToEvent(event.id)
2025-06-19 17:22:17 +00:00
}
}
export const getEventPath = async (event: TrustedEvent, urls: string[]) => {
if (event.kind === DIRECT_MESSAGE || event.kind === DIRECT_MESSAGE_FILE) {
return makeChatPath([event.pubkey, ...getPubkeyTagValues(event.tags)])
}
2025-10-30 22:33:34 +00:00
const h = getTagValue(ROOM, event.tags)
2025-06-05 17:55:16 +00:00
2025-06-05 20:37:50 +00:00
if (urls.length > 0) {
const url = urls[0]
2025-07-07 22:28:36 +00:00
if (event.kind === ZAP_GOAL) {
return makeGoalPath(url, event.id)
}
2025-06-05 17:55:16 +00:00
if (event.kind === THREAD) {
2025-06-19 17:22:17 +00:00
return makeThreadPath(url, event.id)
2025-06-05 17:55:16 +00:00
}
if (event.kind === EVENT_TIME) {
2025-06-19 17:22:17 +00:00
return makeCalendarPath(url, event.id)
2025-06-05 17:55:16 +00:00
}
if (event.kind === MESSAGE) {
2025-10-30 22:33:34 +00:00
return h ? makeRoomPath(url, h) : makeSpacePath(url, "chat")
2025-06-05 17:55:16 +00:00
}
const kind = event.tags.find(nthEq(0, "K"))?.[1]
const id = event.tags.find(nthEq(0, "E"))?.[1]
if (id && kind) {
2025-07-07 22:28:36 +00:00
if (parseInt(kind) === ZAP_GOAL) {
return makeGoalPath(url, id)
}
2025-06-05 17:55:16 +00:00
if (parseInt(kind) === THREAD) {
2025-06-19 17:22:17 +00:00
return makeThreadPath(url, id)
2025-06-05 17:55:16 +00:00
}
if (parseInt(kind) === EVENT_TIME) {
2025-06-19 17:22:17 +00:00
return makeCalendarPath(url, id)
2025-06-05 17:55:16 +00:00
}
if (parseInt(kind) === MESSAGE) {
2025-10-30 22:33:34 +00:00
return h ? makeRoomPath(url, h) : makeSpacePath(url, "chat")
2025-06-05 17:55:16 +00:00
}
}
}
2025-06-05 20:37:50 +00:00
2025-06-19 17:22:17 +00:00
return entityLink(nip19.neventEncode({id: event.id, relays: urls}))
2025-06-05 17:55:16 +00:00
}
2025-10-06 18:23:19 +00:00
export const getChannelItemPath = (url: string, event: TrustedEvent) => {
switch (event.kind) {
case THREAD:
return makeThreadPath(url, event.id)
case ZAP_GOAL:
return makeGoalPath(url, event.id)
case EVENT_TIME:
return makeCalendarPath(url, event.id)
}
}