Read thread, classified, article and goal titles, rooms and reports through their domain readers
This commit is contained in:
parent
945a9649e6
commit
66af2a201e
13 changed files with 51 additions and 52 deletions
|
|
@ -300,8 +300,7 @@ These predate the rule or are waiting on welshman. Don't copy them; fix one when
|
||||||
relay lists in `SignUp.svelte` (`RelayList`, `MessagingRelayList`); deletes in
|
relay lists in `SignUp.svelte` (`RelayList`, `MessagingRelayList`); deletes in
|
||||||
`ProfileDelete.svelte` and the push adapter (`Delete`); the vanish request as a literal `62`
|
`ProfileDelete.svelte` and the push adapter (`Delete`); the vanish request as a literal `62`
|
||||||
(`VANISH`).
|
(`VANISH`).
|
||||||
- **Getter exists but bypassed:** titles in `src/app/title.ts`, `NoteContentThread` and the
|
- **Getter exists but bypassed:** calendar `start`/`end` in `src/app/feeds.ts` and the calendar page; poll `response`
|
||||||
threads pages; calendar `start`/`end` in `src/app/feeds.ts` and the calendar page; poll `response`
|
|
||||||
tags in `PollVotes`; `p` tags of `RELAY_ADD_MEMBER`, `ROOM_ADD_MEMBER` and
|
tags in `PollVotes`; `p` tags of `RELAY_ADD_MEMBER`, `ROOM_ADD_MEMBER` and
|
||||||
`ROOM_CREATE_PERMISSION` (`SpaceMembersSummary`, `RoomItemAddMember`, `src/app/management.ts`);
|
`ROOM_CREATE_PERMISSION` (`SpaceMembersSummary`, `RoomItemAddMember`, `src/app/management.ts`);
|
||||||
comment `E`/`A` tags in the list pages and `src/app/classifieds.ts`; `imeta` unpacking in
|
comment `E`/`A` tags in the list pages and `src/app/classifieds.ts`; `imeta` unpacking in
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import {getAddress, tagValue, tagSpec} from "@welshman/util"
|
import {getAddress} from "@welshman/util"
|
||||||
|
import {TimeEvent} from "@welshman/domain"
|
||||||
import Link from "@lib/components/Link.svelte"
|
import Link from "@lib/components/Link.svelte"
|
||||||
import Cv from "@lib/components/Cv.svelte"
|
import Cv from "@lib/components/Cv.svelte"
|
||||||
import ContentActions from "@app/components/ContentActions.svelte"
|
import ContentActions from "@app/components/ContentActions.svelte"
|
||||||
import CalendarEventEdit from "@app/components/CalendarEventEdit.svelte"
|
import CalendarEventEdit from "@app/components/CalendarEventEdit.svelte"
|
||||||
|
import {reader} from "@app/core"
|
||||||
import type {FeedContext} from "@app/feeds"
|
import type {FeedContext} from "@app/feeds"
|
||||||
import CalendarEventHeader from "@app/components/CalendarEventHeader.svelte"
|
import CalendarEventHeader from "@app/components/CalendarEventHeader.svelte"
|
||||||
import ProfileLink from "@app/components/ProfileLink.svelte"
|
import ProfileLink from "@app/components/ProfileLink.svelte"
|
||||||
|
|
@ -21,7 +23,7 @@
|
||||||
const {url, event, context}: Props = $props()
|
const {url, event, context}: Props = $props()
|
||||||
|
|
||||||
const path = $derived(makeCalendarPath(url, getAddress(event)))
|
const path = $derived(makeCalendarPath(url, getAddress(event)))
|
||||||
const h = $derived(tagValue(tagSpec("h"), event.tags))
|
const h = $derived(reader(TimeEvent)(event).room())
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Cv tag={Link} class="relative flex flex-col gap-3 card card-interactive w-full" href={path}>
|
<Cv tag={Link} class="relative flex flex-col gap-3 card card-interactive w-full" href={path}>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {ComponentProps} from "svelte"
|
import type {ComponentProps} from "svelte"
|
||||||
import {tagSpec, tagValue} from "@welshman/util"
|
import {Thread} from "@welshman/domain"
|
||||||
import ContentMinimal from "@app/components/ContentMinimal.svelte"
|
import ContentMinimal from "@app/components/ContentMinimal.svelte"
|
||||||
|
import {reader} from "@app/core"
|
||||||
|
|
||||||
const props: ComponentProps<typeof ContentMinimal> = $props()
|
const props: ComponentProps<typeof ContentMinimal> = $props()
|
||||||
|
|
||||||
const title = tagValue(tagSpec("title"), props.event.tags)
|
const title = reader(Thread)(props.event).title()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if title}
|
{#if title}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {ComponentProps} from "svelte"
|
import type {ComponentProps} from "svelte"
|
||||||
import {tagSpec, tagValue} from "@welshman/util"
|
import {Thread} from "@welshman/domain"
|
||||||
import Content from "@app/components/Content.svelte"
|
import Content from "@app/components/Content.svelte"
|
||||||
|
import {reader} from "@app/core"
|
||||||
|
|
||||||
const props: ComponentProps<typeof Content> = $props()
|
const props: ComponentProps<typeof Content> = $props()
|
||||||
|
|
||||||
const title = tagValue(tagSpec("title"), props.event.tags)
|
const title = reader(Thread)(props.event).title()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import {tagSpec, tagValue} from "@welshman/util"
|
import {Poll} from "@welshman/domain"
|
||||||
import Link from "@lib/components/Link.svelte"
|
import Link from "@lib/components/Link.svelte"
|
||||||
import Cv from "@lib/components/Cv.svelte"
|
import Cv from "@lib/components/Cv.svelte"
|
||||||
import NoteContent from "@app/components/NoteContent.svelte"
|
import NoteContent from "@app/components/NoteContent.svelte"
|
||||||
import ContentActions from "@app/components/ContentActions.svelte"
|
import ContentActions from "@app/components/ContentActions.svelte"
|
||||||
|
import {reader} from "@app/core"
|
||||||
import type {FeedContext} from "@app/feeds"
|
import type {FeedContext} from "@app/feeds"
|
||||||
import RoomLink from "@app/components/RoomLink.svelte"
|
import RoomLink from "@app/components/RoomLink.svelte"
|
||||||
import ProfileLink from "@app/components/ProfileLink.svelte"
|
import ProfileLink from "@app/components/ProfileLink.svelte"
|
||||||
|
|
@ -20,7 +21,7 @@
|
||||||
const {url, event, context}: Props = $props()
|
const {url, event, context}: Props = $props()
|
||||||
|
|
||||||
const path = makePollPath(url, event.id)
|
const path = makePollPath(url, event.id)
|
||||||
const h = tagValue(tagSpec("h"), event.tags)
|
const h = reader(Poll)(event).room()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Cv tag={Link} class="relative flex flex-col gap-2 card card-interactive w-full" href={path}>
|
<Cv tag={Link} class="relative flex flex-col gap-2 card card-interactive w-full" href={path}>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {onMount} from "svelte"
|
import {onMount} from "svelte"
|
||||||
import {matchTag, tagSpec} from "@welshman/util"
|
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
|
import {Report} from "@welshman/domain"
|
||||||
import InboxOut from "@assets/icons/inbox-out.svg?dataurl"
|
import InboxOut from "@assets/icons/inbox-out.svg?dataurl"
|
||||||
import MinusCircle from "@assets/icons/minus-circle.svg?dataurl"
|
import MinusCircle from "@assets/icons/minus-circle.svg?dataurl"
|
||||||
import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl"
|
import TrashBin2 from "@assets/icons/trash-bin-2.svg?dataurl"
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
import Icon from "@lib/components/Icon.svelte"
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
import Button from "@lib/components/Button.svelte"
|
import Button from "@lib/components/Button.svelte"
|
||||||
import Confirm from "@lib/components/Confirm.svelte"
|
import Confirm from "@lib/components/Confirm.svelte"
|
||||||
import {app, deletes, profiles, relayManagement, relays, user} from "@app/core"
|
import {app, deletes, profiles, reader, relayManagement, relays, user} from "@app/core"
|
||||||
import {deriveSpacePermissions} from "@app/management"
|
import {deriveSpacePermissions} from "@app/management"
|
||||||
import {pushToast} from "@app/toast"
|
import {pushToast} from "@app/toast"
|
||||||
import {pushModal} from "@app/modal"
|
import {pushModal} from "@app/modal"
|
||||||
|
|
@ -24,8 +24,10 @@
|
||||||
const {url, event, onResolved, onClick}: Props = $props()
|
const {url, event, onResolved, onClick}: Props = $props()
|
||||||
|
|
||||||
const permissions = deriveSpacePermissions(url)
|
const permissions = deriveSpacePermissions(url)
|
||||||
const etag = matchTag(tagSpec("e"), event.tags)
|
const report = reader(Report)(event)
|
||||||
const ptag = matchTag(tagSpec("p"), event.tags)
|
const reportedId = report.eventId()
|
||||||
|
const reportedPubkey = report.pubkey()
|
||||||
|
const reason = report.reason() ?? ""
|
||||||
|
|
||||||
const deleteReport = async () => {
|
const deleteReport = async () => {
|
||||||
const protect = await $relays.hasNip(url, 70)
|
const protect = await $relays.hasNip(url, 70)
|
||||||
|
|
@ -48,20 +50,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const banContent = () => {
|
const banContent = () => {
|
||||||
const [_, id, reason = ""] = etag!
|
|
||||||
|
|
||||||
pushModal(Confirm, {
|
pushModal(Confirm, {
|
||||||
title: `Remove Content`,
|
title: `Remove Content`,
|
||||||
message: `Are you sure you want to delete this content from the space?`,
|
message: `Are you sure you want to delete this content from the space?`,
|
||||||
confirm: async () => {
|
confirm: async () => {
|
||||||
const {error} = await $relayManagement.forUrl(url).banEvent(id, reason)
|
const {error} = await $relayManagement.forUrl(url).banEvent(reportedId!, reason)
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
pushToast({theme: "error", message: error})
|
pushToast({theme: "error", message: error})
|
||||||
} else {
|
} else {
|
||||||
pushToast({message: "Content has successfully been deleted!"})
|
pushToast({message: "Content has successfully been deleted!"})
|
||||||
$app.repository.removeEvent(event.id)
|
$app.repository.removeEvent(event.id)
|
||||||
$app.repository.removeEvent(id)
|
$app.repository.removeEvent(reportedId!)
|
||||||
history.back()
|
history.back()
|
||||||
setTimeout(() => onResolved?.())
|
setTimeout(() => onResolved?.())
|
||||||
}
|
}
|
||||||
|
|
@ -70,13 +70,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const banMember = () => {
|
const banMember = () => {
|
||||||
const [_, reported, reason = ""] = ptag!
|
|
||||||
|
|
||||||
pushModal(Confirm, {
|
pushModal(Confirm, {
|
||||||
title: "Ban User",
|
title: "Ban User",
|
||||||
message: `Are you sure you want to ban @${$profiles.display(reported, [url]).get()} from the space?`,
|
message: `Are you sure you want to ban @${$profiles.display(reportedPubkey!, [url]).get()} from the space?`,
|
||||||
confirm: async () => {
|
confirm: async () => {
|
||||||
const {error} = await $relayManagement.forUrl(url).banPubkey(reported, reason)
|
const {error} = await $relayManagement.forUrl(url).banPubkey(reportedPubkey!, reason)
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
pushToast({theme: "error", message: error})
|
pushToast({theme: "error", message: error})
|
||||||
|
|
@ -113,7 +111,7 @@
|
||||||
Dismiss Report
|
Dismiss Report
|
||||||
</Button>
|
</Button>
|
||||||
</li>
|
</li>
|
||||||
{#if etag}
|
{#if reportedId}
|
||||||
<li>
|
<li>
|
||||||
<Button class="text-error" onclick={banContent}>
|
<Button class="text-error" onclick={banContent}>
|
||||||
<Icon icon={TrashBin2} />
|
<Icon icon={TrashBin2} />
|
||||||
|
|
@ -122,7 +120,7 @@
|
||||||
</li>
|
</li>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{#if ptag && $permissions.ban}
|
{#if reportedPubkey && $permissions.ban}
|
||||||
<li>
|
<li>
|
||||||
<Button class="text-error" onclick={banMember}>
|
<Button class="text-error" onclick={banMember}>
|
||||||
<Icon icon={MinusCircle} />
|
<Icon icon={MinusCircle} />
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,8 @@
|
||||||
import {readable} from "svelte/store"
|
import {readable} from "svelte/store"
|
||||||
import {now, uniq, displayList, formatTimestampAsTime, formatTimestampAsDate} from "@welshman/lib"
|
import {now, uniq, displayList, formatTimestampAsTime, formatTimestampAsDate} from "@welshman/lib"
|
||||||
import type {TrustedEvent, EventContent} from "@welshman/util"
|
import type {TrustedEvent, EventContent} from "@welshman/util"
|
||||||
import {
|
import {MESSAGE, THREAD, getCommentFiltersForParent, getIdOrAddress} from "@welshman/util"
|
||||||
MESSAGE,
|
import {Thread, getContentQuote} from "@welshman/domain"
|
||||||
THREAD,
|
|
||||||
getCommentFiltersForParent,
|
|
||||||
getIdOrAddress,
|
|
||||||
tagSpec,
|
|
||||||
tagValue,
|
|
||||||
} from "@welshman/util"
|
|
||||||
import {getContentQuote} from "@welshman/domain"
|
|
||||||
import {isMobile} from "@lib/html"
|
import {isMobile} from "@lib/html"
|
||||||
import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl"
|
import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl"
|
||||||
import Pen from "@assets/icons/pen.svg?dataurl"
|
import Pen from "@assets/icons/pen.svg?dataurl"
|
||||||
|
|
@ -32,7 +25,7 @@
|
||||||
import RoomItemMenuButton from "@app/components/RoomItemMenuButton.svelte"
|
import RoomItemMenuButton from "@app/components/RoomItemMenuButton.svelte"
|
||||||
import RoomItemMenuMobile from "@app/components/RoomItemMenuMobile.svelte"
|
import RoomItemMenuMobile from "@app/components/RoomItemMenuMobile.svelte"
|
||||||
import RoomItemContent from "@app/components/RoomItemContent.svelte"
|
import RoomItemContent from "@app/components/RoomItemContent.svelte"
|
||||||
import {events, profiles, thunks, user} from "@app/core"
|
import {events, profiles, reader, thunks, user} from "@app/core"
|
||||||
import {noThunks, thunksByEventId} from "@app/thunks"
|
import {noThunks, thunksByEventId} from "@app/thunks"
|
||||||
import {colorFor} from "@app/theme"
|
import {colorFor} from "@app/theme"
|
||||||
import {ENABLE_ZAPS} from "@app/env"
|
import {ENABLE_ZAPS} from "@app/env"
|
||||||
|
|
@ -154,7 +147,7 @@
|
||||||
class="button button-xs button-neutral gap-1 rounded-full">
|
class="button button-xs button-neutral gap-1 rounded-full">
|
||||||
<Icon icon={NotesMinimalistic} />
|
<Icon icon={NotesMinimalistic} />
|
||||||
<span class="max-w-48 truncate">
|
<span class="max-w-48 truncate">
|
||||||
{tagValue(tagSpec("title"), thread.tags) || "Thread"}
|
{reader(Thread)(thread).title() || "Thread"}
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {tagSpec, tagValue} from "@welshman/util"
|
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
|
import {RoomJoin} from "@welshman/domain"
|
||||||
import Card from "@lib/components/Card.svelte"
|
import Card from "@lib/components/Card.svelte"
|
||||||
import Button from "@lib/components/Button.svelte"
|
import Button from "@lib/components/Button.svelte"
|
||||||
import ProfileName from "@app/components/ProfileName.svelte"
|
import ProfileName from "@app/components/ProfileName.svelte"
|
||||||
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
||||||
import RoomName from "@app/components/RoomName.svelte"
|
import RoomName from "@app/components/RoomName.svelte"
|
||||||
import {app, relayManagement} from "@app/core"
|
import {app, reader, relayManagement} from "@app/core"
|
||||||
import {deriveSpacePermissions} from "@app/management"
|
import {deriveSpacePermissions} from "@app/management"
|
||||||
import {pushModal} from "@app/modal"
|
import {pushModal} from "@app/modal"
|
||||||
import {pushToast} from "@app/toast"
|
import {pushToast} from "@app/toast"
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
const {url, event, onResolved}: Props = $props()
|
const {url, event, onResolved}: Props = $props()
|
||||||
|
|
||||||
const h = tagValue(tagSpec("h"), event.tags) || ""
|
const h = reader(RoomJoin)(event).room() || ""
|
||||||
|
|
||||||
const permissions = deriveSpacePermissions(url)
|
const permissions = deriveSpacePermissions(url)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,14 @@
|
||||||
import {derived} from "svelte/store"
|
import {derived} from "svelte/store"
|
||||||
import {filter, formatTimestamp, max, spec} from "@welshman/lib"
|
import {filter, formatTimestamp, max, spec} from "@welshman/lib"
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import {COMMENT, tagSpec, tagValue} from "@welshman/util"
|
import {COMMENT} from "@welshman/util"
|
||||||
|
import {Thread} from "@welshman/domain"
|
||||||
import Link from "@lib/components/Link.svelte"
|
import Link from "@lib/components/Link.svelte"
|
||||||
import Cv from "@lib/components/Cv.svelte"
|
import Cv from "@lib/components/Cv.svelte"
|
||||||
import ProfileCircle from "@app/components/ProfileCircle.svelte"
|
import ProfileCircle from "@app/components/ProfileCircle.svelte"
|
||||||
import ProfileName from "@app/components/ProfileName.svelte"
|
import ProfileName from "@app/components/ProfileName.svelte"
|
||||||
import UnreadDot from "@app/components/UnreadDot.svelte"
|
import UnreadDot from "@app/components/UnreadDot.svelte"
|
||||||
|
import {reader} from "@app/core"
|
||||||
import type {FeedContext} from "@app/feeds"
|
import type {FeedContext} from "@app/feeds"
|
||||||
import {makeThreadPath} from "@app/routes"
|
import {makeThreadPath} from "@app/routes"
|
||||||
|
|
||||||
|
|
@ -25,7 +27,7 @@
|
||||||
const replies = derived(related, $related => filter(spec({kind: COMMENT}), $related))
|
const replies = derived(related, $related => filter(spec({kind: COMMENT}), $related))
|
||||||
const replyCount = $derived($replies.length)
|
const replyCount = $derived($replies.length)
|
||||||
const lastActive = $derived(max([...$replies, event].map(e => e.created_at)))
|
const lastActive = $derived(max([...$replies, event].map(e => e.created_at)))
|
||||||
const title = tagValue(tagSpec("title"), event.tags)
|
const title = reader(Thread)(event).title()
|
||||||
const path = makeThreadPath(url, event.id)
|
const path = makeThreadPath(url, event.id)
|
||||||
const onClick = () => navigate(path)
|
const onClick = () => navigate(path)
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import {tagSpec, tagValue} from "@welshman/util"
|
import {Thread} from "@welshman/domain"
|
||||||
import Button from "@lib/components/Button.svelte"
|
import Button from "@lib/components/Button.svelte"
|
||||||
import ProfileCircle from "@app/components/ProfileCircle.svelte"
|
import ProfileCircle from "@app/components/ProfileCircle.svelte"
|
||||||
import ContentMinimal from "@app/components/ContentMinimal.svelte"
|
import ContentMinimal from "@app/components/ContentMinimal.svelte"
|
||||||
|
import {reader} from "@app/core"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
url: string
|
url: string
|
||||||
|
|
@ -13,7 +14,7 @@
|
||||||
|
|
||||||
const {url, event, onClick}: Props = $props()
|
const {url, event, onClick}: Props = $props()
|
||||||
|
|
||||||
const title = tagValue(tagSpec("title"), event.tags)
|
const title = reader(Thread)(event).title()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,9 @@ export const AUDIO_CONTENT_TYPES = [
|
||||||
]
|
]
|
||||||
|
|
||||||
export const getUrlTags = (url: string, event: TrustedEvent) => {
|
export const getUrlTags = (url: string, event: TrustedEvent) => {
|
||||||
// An imeta tag packs its own tags into space-separated values, so unpack them.
|
// An imeta entry is "key value" and the value may contain spaces, so split at the first one only.
|
||||||
const imetas = matchTags(tagSpec("imeta"), event.tags).map(([, ...values]: string[]) =>
|
const imetas = matchTags(tagSpec("imeta"), event.tags).map(([, ...values]: string[]) =>
|
||||||
values.map(value => value.split(" ")),
|
values.map(value => value.split(/ (.*)/s, 2)),
|
||||||
)
|
)
|
||||||
const imeta = imetas.find(meta => tagValue(tagSpec("url"), meta) === url)
|
const imeta = imetas.find(meta => tagValue(tagSpec("url"), meta) === url)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
import {identity, uniq} from "@welshman/lib"
|
import {identity, uniq} from "@welshman/lib"
|
||||||
import {tagSpec, tagValue} from "@welshman/util"
|
import {Article, Classified, Thread, ZapGoal, displayPubkey} from "@welshman/domain"
|
||||||
import {displayPubkey} from "@welshman/domain"
|
|
||||||
import {makeRoomKey} from "@welshman/app"
|
import {makeRoomKey} from "@welshman/app"
|
||||||
import {decodePubkey} from "@lib/util"
|
import {decodePubkey} from "@lib/util"
|
||||||
import {getEventTitle} from "@app/calendar"
|
import {getEventTitle} from "@app/calendar"
|
||||||
import {app, profiles, rooms} from "@app/core"
|
import {app, profiles, reader, rooms} from "@app/core"
|
||||||
import {PLATFORM_NAME} from "@app/env"
|
import {PLATFORM_NAME} from "@app/env"
|
||||||
import {decodeRelay} from "@app/relays"
|
import {decodeRelay} from "@app/relays"
|
||||||
|
|
||||||
|
|
@ -134,7 +133,7 @@ export const getPageTitle = ({page, pubkey}: PageTitleContext) => {
|
||||||
const event = getEventForTitle(routeId, page.params)
|
const event = getEventForTitle(routeId, page.params)
|
||||||
|
|
||||||
if (routeId === "/spaces/[relay]/threads/[id]") {
|
if (routeId === "/spaces/[relay]/threads/[id]") {
|
||||||
return makeTitle(tagValue(tagSpec("title"), event?.tags || []) || "Thread")
|
return makeTitle((event && reader(Thread)(event).title()) || "Thread")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (routeId === "/spaces/[relay]/calendar/[address]") {
|
if (routeId === "/spaces/[relay]/calendar/[address]") {
|
||||||
|
|
@ -142,15 +141,15 @@ export const getPageTitle = ({page, pubkey}: PageTitleContext) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (routeId === "/spaces/[relay]/classifieds/[address]") {
|
if (routeId === "/spaces/[relay]/classifieds/[address]") {
|
||||||
return makeTitle(tagValue(tagSpec("title"), event?.tags || []) || "Listing")
|
return makeTitle((event && reader(Classified)(event).title()) || "Listing")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (routeId === "/spaces/[relay]/articles/[address]") {
|
if (routeId === "/spaces/[relay]/articles/[address]") {
|
||||||
return makeTitle(tagValue(tagSpec("title"), event?.tags || []) || "Article")
|
return makeTitle((event && reader(Article)(event).title()) || "Article")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (routeId === "/spaces/[relay]/goals/[id]") {
|
if (routeId === "/spaces/[relay]/goals/[id]") {
|
||||||
return makeTitle(event?.content || tagValue(tagSpec("summary"), event?.tags || []) || "Goal")
|
return makeTitle(event?.content || (event && reader(ZapGoal)(event).summary()) || "Goal")
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeTitle()
|
return makeTitle()
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,14 @@
|
||||||
import type {Maybe} from "@welshman/lib"
|
import type {Maybe} from "@welshman/lib"
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import {THREAD, tagValue, tagSpec} from "@welshman/util"
|
import {THREAD, tagValue, tagSpec} from "@welshman/util"
|
||||||
|
import {Thread} from "@welshman/domain"
|
||||||
import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl"
|
import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl"
|
||||||
import Icon from "@lib/components/Icon.svelte"
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
import PageContent from "@lib/components/PageContent.svelte"
|
import PageContent from "@lib/components/PageContent.svelte"
|
||||||
import Spinner from "@lib/components/Spinner.svelte"
|
import Spinner from "@lib/components/Spinner.svelte"
|
||||||
import SpaceBar from "@app/components/SpaceBar.svelte"
|
import SpaceBar from "@app/components/SpaceBar.svelte"
|
||||||
import ThreadBoard from "@app/components/ThreadBoard.svelte"
|
import ThreadBoard from "@app/components/ThreadBoard.svelte"
|
||||||
|
import {reader} from "@app/core"
|
||||||
import {decodeRelay} from "@app/relays"
|
import {decodeRelay} from "@app/relays"
|
||||||
import {displayRoom} from "@app/rooms"
|
import {displayRoom} from "@app/rooms"
|
||||||
import {makeCommentFilter} from "@app/content"
|
import {makeCommentFilter} from "@app/content"
|
||||||
|
|
@ -46,7 +48,7 @@
|
||||||
|
|
||||||
const items = sortBy(e => -max([...(scores.get(e.id) || []), e.created_at]), threads)
|
const items = sortBy(e => -max([...(scores.get(e.id) || []), e.created_at]), threads)
|
||||||
|
|
||||||
const grouped = groupBy(e => tagValue(tagSpec("h"), e.tags) || "", items)
|
const grouped = groupBy(e => reader(Thread)(e).room() || "", items)
|
||||||
const byRoom = new Map<string, TrustedEvent[]>([["", []], ...grouped])
|
const byRoom = new Map<string, TrustedEvent[]>([["", []], ...grouped])
|
||||||
const roomName = (h: string) => (h ? displayRoom(url, h) : "general").toLowerCase()
|
const roomName = (h: string) => (h ? displayRoom(url, h) : "general").toLowerCase()
|
||||||
const boards = sortBy(([h]) => roomName(h), Array.from(byRoom.entries()))
|
const boards = sortBy(([h]) => roomName(h), Array.from(byRoom.entries()))
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue