2024-08-16 17:50:38 +00:00
|
|
|
import type {Page} from "@sveltejs/kit"
|
2025-10-15 16:04:17 +00:00
|
|
|
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"
|
2026-01-06 22:52:13 +00:00
|
|
|
import {nthEq, sleep} from "@welshman/lib"
|
2025-06-05 17:55:16 +00:00
|
|
|
import type {TrustedEvent} from "@welshman/util"
|
2026-02-04 01:09:30 +00:00
|
|
|
import {getAddress} from "@welshman/util"
|
2026-01-06 22:52:13 +00:00
|
|
|
import {tracker, loadRelay} 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,
|
|
|
|
|
MESSAGE,
|
|
|
|
|
THREAD,
|
2026-02-03 19:00:13 +00:00
|
|
|
CLASSIFIED,
|
2025-07-07 22:28:36 +00:00
|
|
|
ZAP_GOAL,
|
2025-06-05 17:55:16 +00:00
|
|
|
EVENT_TIME,
|
2025-09-09 16:54:08 +00:00
|
|
|
getPubkeyTagValues,
|
2025-06-05 17:55:16 +00:00
|
|
|
} from "@welshman/util"
|
2025-08-21 22:01:31 +00:00
|
|
|
import {
|
|
|
|
|
makeChatId,
|
|
|
|
|
entityLink,
|
|
|
|
|
decodeRelay,
|
|
|
|
|
encodeRelay,
|
2025-10-15 16:04:17 +00:00
|
|
|
userSpaceUrls,
|
2025-10-06 18:23:19 +00:00
|
|
|
hasNip29,
|
2026-02-13 23:37:17 +00:00
|
|
|
DM_KINDS,
|
2025-08-21 22:01:31 +00:00
|
|
|
ROOM,
|
|
|
|
|
} from "@app/core/state"
|
2025-11-05 00:14:32 +00:00
|
|
|
import {lastPageBySpaceUrl} from "@app/util/history"
|
2024-08-14 20:38:55 +00:00
|
|
|
|
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-09-11 17:48:34 +00:00
|
|
|
|
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("/")
|
2024-09-11 17:48:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return path
|
|
|
|
|
}
|
2024-08-15 19:08:07 +00:00
|
|
|
|
2025-11-05 00:14:32 +00:00
|
|
|
export const goToSpace = async (url: string) => {
|
|
|
|
|
const prevPath = lastPageBySpaceUrl.get(encodeRelay(url))
|
|
|
|
|
|
|
|
|
|
if (prevPath) {
|
|
|
|
|
goto(prevPath)
|
|
|
|
|
} else if (hasNip29(await loadRelay(url))) {
|
|
|
|
|
goto(makeSpacePath(url, "recent"))
|
|
|
|
|
} else {
|
2025-11-05 01:25:50 +00:00
|
|
|
goto(makeSpacePath(url, "chat"))
|
2025-11-05 00:14:32 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-06 22:52:13 +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")
|
|
|
|
|
|
2026-02-04 00:19:14 +00:00
|
|
|
export const makeGoalPath = (url: string, id?: string) => makeSpacePath(url, "goals", id)
|
2025-07-07 22:28:36 +00:00
|
|
|
|
2026-02-04 00:19:14 +00:00
|
|
|
export const makeThreadPath = (url: string, id?: string) => makeSpacePath(url, "threads", id)
|
2024-12-16 18:30:42 +00:00
|
|
|
|
2026-02-04 01:09:30 +00:00
|
|
|
export const makeClassifiedPath = (url: string, address?: string) =>
|
|
|
|
|
makeSpacePath(url, "classifieds", address)
|
2026-02-03 19:00:13 +00:00
|
|
|
|
2026-02-04 01:09:30 +00:00
|
|
|
export const makeCalendarPath = (url: string, address?: string) =>
|
|
|
|
|
makeSpacePath(url, "calendar", address)
|
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]
|
2024-08-14 20:38:55 +00:00
|
|
|
|
|
|
|
|
export const getPrimaryNavItemIndex = ($page: Page) => {
|
2025-10-15 16:04:17 +00:00
|
|
|
const urls = get(userSpaceUrls)
|
2024-09-11 17:48:34 +00:00
|
|
|
|
2024-08-14 20:38:55 +00:00
|
|
|
switch (getPrimaryNavItem($page)) {
|
2024-08-16 17:50:38 +00:00
|
|
|
case "discover":
|
2024-09-11 17:48:34 +00:00
|
|
|
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 || "")
|
2024-09-11 17:48:34 +00:00
|
|
|
|
|
|
|
|
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":
|
2024-09-11 17:48:34 +00:00
|
|
|
return urls.length + 3
|
2024-08-14 20:38:55 +00:00
|
|
|
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> = {}) => {
|
2025-10-17 17:19:21 +00:00
|
|
|
const urls = Array.from(tracker.getRelays(event.id))
|
|
|
|
|
const path = await getEventPath(event, urls)
|
2025-06-05 17:55:16 +00:00
|
|
|
|
2025-10-17 17:19:21 +00:00
|
|
|
if (path.includes("://")) {
|
|
|
|
|
window.open(path)
|
|
|
|
|
} else {
|
|
|
|
|
goto(path, options)
|
2025-06-19 17:22:17 +00:00
|
|
|
|
2025-10-17 17:19:21 +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[]) => {
|
2026-02-13 23:37:17 +00:00
|
|
|
if (DM_KINDS.includes(event.kind)) {
|
2025-09-09 16:54:08 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2026-02-03 19:00:13 +00:00
|
|
|
if (event.kind === CLASSIFIED) {
|
2026-02-04 00:19:14 +00:00
|
|
|
return makeClassifiedPath(url, getAddress(event))
|
2026-02-03 19:00:13 +00:00
|
|
|
}
|
|
|
|
|
|
2025-06-05 17:55:16 +00:00
|
|
|
if (event.kind === EVENT_TIME) {
|
2026-02-04 00:19:14 +00:00
|
|
|
return makeCalendarPath(url, getAddress(event))
|
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
|
|
|
}
|
|
|
|
|
|
2026-02-04 00:19:14 +00:00
|
|
|
const address = event.tags.find(nthEq(0, "A"))?.[1]
|
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
|
|
|
}
|
|
|
|
|
|
2026-02-04 00:19:14 +00:00
|
|
|
if (parseInt(kind) === MESSAGE) {
|
|
|
|
|
return h ? makeRoomPath(url, h) : makeSpacePath(url, "chat")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (address && kind) {
|
2026-02-03 19:00:13 +00:00
|
|
|
if (parseInt(kind) === CLASSIFIED) {
|
2026-02-04 00:19:14 +00:00
|
|
|
return makeClassifiedPath(url, address)
|
2026-02-03 19:00:13 +00:00
|
|
|
}
|
|
|
|
|
|
2025-06-05 17:55:16 +00:00
|
|
|
if (parseInt(kind) === EVENT_TIME) {
|
2026-02-04 00:19:14 +00:00
|
|
|
return makeCalendarPath(url, address)
|
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
|
|
|
|
2025-10-30 22:36:14 +00:00
|
|
|
export const getRoomItemPath = (url: string, event: TrustedEvent) => {
|
2025-10-06 18:23:19 +00:00
|
|
|
switch (event.kind) {
|
|
|
|
|
case THREAD:
|
|
|
|
|
return makeThreadPath(url, event.id)
|
2026-02-03 19:00:13 +00:00
|
|
|
case CLASSIFIED:
|
2026-02-04 00:19:14 +00:00
|
|
|
return makeClassifiedPath(url, getAddress(event))
|
2025-10-06 18:23:19 +00:00
|
|
|
case ZAP_GOAL:
|
|
|
|
|
return makeGoalPath(url, event.id)
|
|
|
|
|
case EVENT_TIME:
|
2026-02-04 00:19:14 +00:00
|
|
|
return makeCalendarPath(url, getAddress(event))
|
2025-10-06 18:23:19 +00:00
|
|
|
}
|
|
|
|
|
}
|