Show which item raised an unread dot on every content board (#419)

Co-authored-by: Coracle-Bot <npub1klq6260@nostr.local>
This commit is contained in:
Coracle-Bot 2026-09-03 20:13:21 +00:00 committed by hodlbod
parent 4d7b052724
commit bec000b05c
25 changed files with 142 additions and 89 deletions

View file

@ -1577,6 +1577,18 @@ Acceptance:
- The thread list below the md breakpoint is a list of links rather than a
table, and alice's thread carries a dot there; bob's own does not.
### US-114 — See which listings are unread
As bob, I want the same dot on a board whose items are cards rather than rows,
so that every content section answers "which one is new" the same way.
Acceptance:
- A listing alice posted raises an unread dot on the Classifieds nav item; one
bob posted himself does not.
- Opening the list keeps the dot on the corner of alice's card, and bob's own
card carries none.
## Out of scope
Features the e2e suite cannot exercise, and what stops it.

View file

@ -1,7 +1,7 @@
import {neventEncode, npubEncode} from "nostr-tools/nip19"
import {HOUR, MINUTE} from "@welshman/lib"
import {displayRelayUrl} from "@welshman/util"
import {MessagingRelayList, RelayList, Thread} from "@welshman/domain"
import {Classified, MessagingRelayList, RelayList, Thread} from "@welshman/domain"
import type {Locator, Page} from "@playwright/test"
import {expect, roomPath, spacePath, test, users} from "../harness"
import type {SeededSpace, TestUser} from "../harness"
@ -481,6 +481,22 @@ test("US-110 see another space's unread activity from a phone", async ({seed, as
const contentNavItem = (page: Page, name: string) =>
page.locator(".secondary-nav").getByRole("link", {name})
const seedClassified = (space: SeededSpace, user: TestUser, title: string, createdAt: number) =>
space.event(
user,
() =>
space
.kind(Classified)
.writer()
.setRoom(space.url, "general")
.setIdentifier()
.setTitle(title)
.setPrice(100)
.setContent("in good condition")
.renderTemplate(),
createdAt,
)
const seedThread = (space: SeededSpace, user: TestUser, title: string, createdAt: number) =>
space.event(
user,
@ -579,3 +595,39 @@ test("US-113 see which threads are unread on a phone", async ({seed, as}) => {
await expect(unreadDot(hers)).toBeVisible()
await expect(unreadDot(his)).toHaveCount(0)
})
// Classifieds stands in for the five boards whose items are cards rather than rows — they all
// render the same UnreadDot off the same content path, and only the corner it sits in differs.
test("US-114 see which listings are unread", async ({seed, as}) => {
const scenario = await seed(({relay, user, at}) => {
const space = relay("space")
space.room("general", {name: "General"})
space.join(user.alice, "general")
space.join(user.bob, "general")
seedClassified(space, user.bob, "vintage sextant", at(3, HOUR))
seedClassified(space, user.alice, "brass astrolabe", at(2, HOUR))
})
const space = scenario.space("space")
const bob = await as(users.bob, roomPath(space.url, "general"))
const classifiedsNav = contentNavItem(bob, "Classifieds")
await expect(classifiedsNav).toBeVisible()
await expect(unreadDot(classifiedsNav)).toBeVisible()
await classifiedsNav.click()
const hers = bob.getByRole("link").filter({hasText: "brass astrolabe"})
const his = bob.getByRole("link").filter({hasText: "vintage sextant"})
await expect(his).toBeVisible()
// Same tick and throttle as US-112.
await bob.waitForTimeout(1500)
await expect(unreadDot(hers)).toBeVisible()
await expect(unreadDot(his)).toHaveCount(0)
})

View file

@ -1,7 +1,6 @@
<script lang="ts">
import {uniq} from "@welshman/lib"
import type {TrustedEvent, EventContent} from "@welshman/util"
import {getAddress} from "@welshman/util"
import {Article} from "@welshman/domain"
import Link from "@lib/components/Link.svelte"
import RoomName from "@app/components/RoomName.svelte"
@ -14,7 +13,7 @@
import EventActionBar from "@app/components/EventActionBar.svelte"
import {reader} from "@app/core"
import {deriveIsDeleted} from "@app/repository"
import {makeArticlePath, makeSpacePath} from "@app/routes"
import {makeSpacePath} from "@app/routes"
type Props = {
url: string
@ -31,7 +30,6 @@
const article = $derived(reader(Article)(event))
const h = $derived(article.room())
const topics = $derived(article.topics())
const path = $derived(makeArticlePath(url, getAddress(event)))
const deleted = $derived(deriveIsDeleted(event))
const deleteReaction = (reaction: TrustedEvent) => retractReaction(reaction, {url, h})
@ -54,7 +52,7 @@
<EventActionBar {url} {event} noun="Article">
{#snippet leading()}
{#if showActivity}
<EventActivity {path} {event} {context} size="sm" hideLastActive />
<EventActivity {event} {context} size="sm" hideLastActive />
{/if}
{/snippet}
</EventActionBar>
@ -84,7 +82,7 @@
{createReaction}
reactionClass="tip-left" />
{#if showActivity}
<EventActivity {path} {event} {context} />
<EventActivity {event} {context} />
{/if}
</ThunkStatusOrDeleted>
</div>

View file

@ -7,6 +7,7 @@
import Content from "@app/components/Content.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte"
import ArticleActions from "@app/components/ArticleActions.svelte"
import UnreadDot from "@app/components/UnreadDot.svelte"
import type {FeedContext} from "@app/feeds"
import {reader} from "@app/core"
import {makeArticlePath} from "@app/routes"
@ -19,6 +20,7 @@
const {url, event, context}: Props = $props()
const path = $derived(makeArticlePath(url, getAddress(event)))
const article = $derived(reader(Article)(event))
const title = $derived(article.title())
const summary = $derived(article.summary())
@ -28,10 +30,8 @@
<div data-component="ArticleItem" class="cv relative w-full card card-interactive">
<!-- An overlay rather than a wrapper: the card carries a profile button and the room and action
links, and none of those may sit inside an anchor. -->
<Link
class="absolute inset-0 rounded-2xl"
href={makeArticlePath(url, getAddress(event))}
aria-label={title || "Untitled"} />
<Link class="absolute inset-0 rounded-2xl" href={path} aria-label={title || "Untitled"} />
<UnreadDot {path} class="absolute right-3 top-3" />
<div class="pointer-events-none relative flex flex-col gap-2">
{#if image}
<img src={image} alt="" class="h-40 w-full rounded-2xl object-cover" />

View file

@ -1,6 +1,6 @@
<script lang="ts">
import type {TrustedEvent, EventContent} from "@welshman/util"
import {getAddress, tagSpec, tagValue} from "@welshman/util"
import {tagSpec, tagValue} from "@welshman/util"
import Pen2 from "@assets/icons/pen-2.svg?dataurl"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
@ -14,7 +14,7 @@
import EventActions from "@app/components/EventActions.svelte"
import CalendarEventEdit from "@app/components/CalendarEventEdit.svelte"
import {user} from "@app/core"
import {makeCalendarPath, makeSpacePath} from "@app/routes"
import {makeSpacePath} from "@app/routes"
import {pushModal} from "@app/modal"
type Props = {
@ -28,7 +28,6 @@
const {url, event, showRoom, showActivity, context}: Props = $props()
const h = $derived(tagValue(tagSpec("h"), event.tags))
const path = $derived(makeCalendarPath(url, getAddress(event)))
const editEvent = () => pushModal(CalendarEventEdit, {url, event})
@ -52,7 +51,7 @@
{createReaction}
reactionClass="tip tip-left" />
{#if showActivity}
<EventActivity {path} {event} {context} />
<EventActivity {event} {context} />
{/if}
<EventActions {url} {event} noun="Event">
{#snippet customActions()}

View file

@ -7,6 +7,7 @@
import CalendarEventHeader from "@app/components/CalendarEventHeader.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte"
import RoomLink from "@app/components/RoomLink.svelte"
import UnreadDot from "@app/components/UnreadDot.svelte"
import {makeCalendarPath} from "@app/routes"
type Props = {
@ -17,12 +18,12 @@
const {url, event, context}: Props = $props()
const path = $derived(makeCalendarPath(url, getAddress(event)))
const h = $derived(tagValue(tagSpec("h"), event.tags))
</script>
<Link
class="cv flex flex-col gap-3 card card-interactive w-full"
href={makeCalendarPath(url, getAddress(event))}>
<Link class="cv relative flex flex-col gap-3 card card-interactive w-full" href={path}>
<UnreadDot {path} class="absolute right-3 top-3" />
<CalendarEventHeader {event} />
<div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row">
<span class="whitespace-nowrap py-1 text-sm opacity-75">

View file

@ -1,7 +1,6 @@
<script lang="ts">
import {uniq} from "@welshman/lib"
import type {TrustedEvent, EventContent} from "@welshman/util"
import {getAddress} from "@welshman/util"
import {Classified} from "@welshman/domain"
import Pen2 from "@assets/icons/pen-2.svg?dataurl"
import {normalizeTopic} from "@lib/util"
@ -18,7 +17,7 @@
import EventActions from "@app/components/EventActions.svelte"
import ClassifiedEdit from "@app/components/ClassifiedEdit.svelte"
import {reader, user} from "@app/core"
import {makeClassifiedPath, makeSpacePath} from "@app/routes"
import {makeSpacePath} from "@app/routes"
import {pushModal} from "@app/modal"
type Props = {
@ -36,7 +35,6 @@
const classified = $derived(reader(Classified)(event))
const h = $derived(classified.room())
const topics = $derived(classified.topics() ?? [])
const path = $derived(makeClassifiedPath(url, getAddress(event)))
const editClassified = () => pushModal(ClassifiedEdit, {url, event})
@ -70,7 +68,7 @@
{createReaction}
reactionClass="tip-left" />
{#if showActivity}
<EventActivity {path} {event} {context} />
<EventActivity {event} {context} />
{/if}
<EventActions {url} {event} noun="Listing">
{#snippet customActions()}

View file

@ -12,6 +12,7 @@
import ClassifiedActions from "@app/components/ClassifiedActions.svelte"
import type {FeedContext} from "@app/feeds"
import RoomLink from "@app/components/RoomLink.svelte"
import UnreadDot from "@app/components/UnreadDot.svelte"
import {makeClassifiedPath} from "@app/routes"
type Props = {
@ -22,6 +23,7 @@
const {url, event, context}: Props = $props()
const path = $derived(makeClassifiedPath(url, getAddress(event)))
const classified = $derived(reader(Classified)(event))
const title = $derived(classified.title())
const h = $derived(classified.room())
@ -29,9 +31,8 @@
const price = $derived(classified.price())
</script>
<Link
class="cv flex flex-col gap-2 card card-interactive w-full"
href={makeClassifiedPath(url, getAddress(event))}>
<Link class="cv relative flex flex-col gap-2 card card-interactive w-full" href={path}>
<UnreadDot {path} class="absolute right-3 top-3" />
{#if title}
<div class="flex w-full items-center justify-between gap-2">
<p class="text-xl">

View file

@ -7,22 +7,18 @@
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
import EventActivity from "@app/components/EventActivity.svelte"
import EventActions from "@app/components/EventActions.svelte"
import {makeSpacePath} from "@app/routes"
type Props = {
url: string
event: TrustedEvent
segment?: string
showActivity?: boolean
context: FeedContext
}
const {url, event, segment, showActivity = false, context}: Props = $props()
const {url, event, showActivity = false, context}: Props = $props()
const h = tagValue(tagSpec("h"), event.tags)
const path = segment && makeSpacePath(url, segment, event.id)
const deleteReaction = (reaction: TrustedEvent) => retractReaction(reaction, {url, h})
const createReaction = (values: EventContent) => publishReaction(event, values, {url, h})
@ -38,8 +34,8 @@
{deleteReaction}
{createReaction}
reactionClass="tip-left" />
{#if showActivity && path}
<EventActivity {path} {event} {context} />
{#if showActivity}
<EventActivity {event} {context} />
{/if}
<EventActions {url} {event} noun="Comment" />
</ThunkStatusOrDeleted>

View file

@ -1,22 +1,19 @@
<script lang="ts">
import {derived} from "svelte/store"
import {filter, max, gt, spec, formatTimestampRelative} from "@welshman/lib"
import {filter, max, spec, formatTimestampRelative} from "@welshman/lib"
import {COMMENT} from "@welshman/util"
import type {TrustedEvent} from "@welshman/util"
import Reply from "@assets/icons/reply-2.svg?dataurl"
import Icon from "@lib/components/Icon.svelte"
import type {FeedContext} from "@app/feeds"
import {deriveChecked} from "@app/notifications"
// hideLastActive: redundant next to a detail page's own comments below.
const {
path,
event,
context,
size = "xs",
hideLastActive,
}: {
path: string
event: TrustedEvent
context: FeedContext
size?: "xs" | "sm"
@ -25,7 +22,6 @@
const buttonClass = `button button-neutral button-${size} rounded-full`
const checked = deriveChecked(path)
const related = context.related(event)
const replies = derived(related, $related => filter(spec({kind: COMMENT}), $related))
const lastActive = $derived(max([...$replies, event].map(e => e.created_at)))
@ -36,10 +32,7 @@
<span>{$replies.length} {$replies.length === 1 ? "reply" : "replies"}</span>
</div>
{#if !hideLastActive}
<div class="{buttonClass} relative">
{#if gt(lastActive, $checked)}
<div class="h-2 w-2 rounded-full bg-primary text-primary-content"></div>
{/if}
<div class={buttonClass}>
Active {formatTimestampRelative(lastActive)}
</div>
{/if}

View file

@ -10,7 +10,7 @@
import EventActivity from "@app/components/EventActivity.svelte"
import EventActions from "@app/components/EventActions.svelte"
import RoomName from "@app/components/RoomName.svelte"
import {makeGoalPath, makeSpacePath} from "@app/routes"
import {makeSpacePath} from "@app/routes"
interface Props {
url: string
@ -22,7 +22,6 @@
const {url, event, showRoom, showActivity, context}: Props = $props()
const path = makeGoalPath(url, event.id)
const goal = reader(ZapGoal)(event)
const h = goal.room()
@ -47,7 +46,7 @@
{createReaction}
reactionClass="tip-left" />
{#if showActivity}
<EventActivity {path} {event} {context} />
<EventActivity {event} {context} />
{/if}
<EventActions {url} {event} hideZap noun="Goal" />
</ThunkStatusOrDeleted>

View file

@ -9,6 +9,7 @@
import type {FeedContext} from "@app/feeds"
import GoalSummary from "@app/components/GoalSummary.svelte"
import RoomLink from "@app/components/RoomLink.svelte"
import UnreadDot from "@app/components/UnreadDot.svelte"
import {makeGoalPath} from "@app/routes"
type Props = {
@ -21,14 +22,14 @@
const goal = reader(ZapGoal)(event)
const path = makeGoalPath(url, event.id)
const title = goal.title()
const summary = goal.summary()
const h = goal.room()
</script>
<Link
class="cv flex flex-col gap-2 card card-interactive w-full"
href={makeGoalPath(url, event.id)}>
<Link class="cv relative flex flex-col gap-2 card card-interactive w-full" href={path}>
<UnreadDot {path} class="absolute right-3 top-3" />
<p class="text-2xl">{title}</p>
<Content
event={{content: summary, tags: event.tags}}

View file

@ -4,6 +4,8 @@
import Button from "@lib/components/Button.svelte"
import MenuButton from "@lib/components/MenuButton.svelte"
import BoardMenu from "@app/components/BoardMenu.svelte"
import UnreadDot from "@app/components/UnreadDot.svelte"
import {makeLibraryPath} from "@app/routes"
type Props = {
url: string
@ -13,6 +15,8 @@
}
const {url, board, selected, onclick}: Props = $props()
const path = $derived(makeLibraryPath(url, board.address()))
</script>
<div class="relative w-56 shrink-0">
@ -22,7 +26,8 @@
class={cx("card card-sm card-interactive flex h-full w-full flex-col items-start gap-1 pr-10", {
"card-primary": selected,
})}>
<strong class="truncate w-full text-left">{board.title() || "Untitled shelf"}</strong>
<strong class="truncate w-full text-left"
><UnreadDot {path} class="mr-1" />{board.title() || "Untitled shelf"}</strong>
{#if board.description()}
<span class="line-clamp-2 text-left text-sm opacity-70">{board.description()}</span>
{/if}

View file

@ -9,7 +9,7 @@
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
import EventActivity from "@app/components/EventActivity.svelte"
import EventActions from "@app/components/EventActions.svelte"
import {makePollPath, makeSpacePath} from "@app/routes"
import {makeSpacePath} from "@app/routes"
type Props = {
url: string
@ -22,7 +22,6 @@
const {url, event, showRoom, showActivity, context}: Props = $props()
const h = tagValue(tagSpec("h"), event.tags)
const path = makePollPath(url, event.id)
const deleteReaction = (reaction: TrustedEvent) => retractReaction(reaction, {url, h})
@ -44,7 +43,7 @@
{createReaction}
reactionClass="tip-left" />
{#if showActivity}
<EventActivity {path} {event} {context} />
<EventActivity {event} {context} />
{/if}
<EventActions {url} {event} noun="Poll" />
</ThunkStatusOrDeleted>

View file

@ -7,6 +7,7 @@
import type {FeedContext} from "@app/feeds"
import RoomLink from "@app/components/RoomLink.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte"
import UnreadDot from "@app/components/UnreadDot.svelte"
import {makePollPath} from "@app/routes"
type Props = {
@ -17,12 +18,12 @@
const {url, event, context}: Props = $props()
const path = makePollPath(url, event.id)
const h = tagValue(tagSpec("h"), event.tags)
</script>
<Link
class="cv flex flex-col gap-2 card card-interactive w-full"
href={makePollPath(url, event.id)}>
<Link class="cv relative flex flex-col gap-2 card card-interactive w-full" href={path}>
<UnreadDot {path} class="absolute right-3 top-3" />
<NoteContent {event} {url} />
<div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row">
<span class="whitespace-nowrap py-1 text-sm opacity-75">

View file

@ -9,7 +9,7 @@
import ThunkStatusOrDeleted from "@app/components/ThunkStatusOrDeleted.svelte"
import EventActivity from "@app/components/EventActivity.svelte"
import EventActions from "@app/components/EventActions.svelte"
import {makeThreadPath, makeSpacePath} from "@app/routes"
import {makeSpacePath} from "@app/routes"
interface Props {
url: string
@ -22,7 +22,6 @@
const {url, event, showRoom, showActivity, context}: Props = $props()
const h = tagValue(tagSpec("h"), event.tags)
const path = makeThreadPath(url, event.id)
const deleteReaction = (reaction: TrustedEvent) => retractReaction(reaction, {url})
const createReaction = (values: EventContent) => publishReaction(event, values, {url})
@ -43,7 +42,7 @@
{createReaction}
reactionClass="tip-left" />
{#if showActivity}
<EventActivity {path} {event} {context} />
<EventActivity {event} {context} />
{/if}
<EventActions {url} {event} noun="Thread" />
</ThunkStatusOrDeleted>

View file

@ -4,12 +4,11 @@
import {filter, formatTimestamp, max, spec} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util"
import {COMMENT, tagSpec, tagValue} from "@welshman/util"
import {fade} from "@lib/transition"
import Link from "@lib/components/Link.svelte"
import ProfileCircle from "@app/components/ProfileCircle.svelte"
import ProfileName from "@app/components/ProfileName.svelte"
import UnreadDot from "@app/components/UnreadDot.svelte"
import type {FeedContext} from "@app/feeds"
import {notifications} from "@app/notifications"
import {makeThreadPath} from "@app/routes"
type Props = {
@ -30,17 +29,13 @@
const onClick = () => goto(path)
</script>
{#snippet unread()}
{#if $notifications.has(path)}
<div class="mr-1 inline-block h-2 w-2 rounded-full bg-primary" transition:fade></div>
{/if}
{/snippet}
{#if mobile}
<Link
href={path}
class="cv hover:bg-surface-less flex w-full flex-col gap-2 border-b border-solid border-line px-4 py-3 text-left text-sm transition-colors">
<p class="truncate font-medium">{@render unread()}{title || "Untitled thread"}</p>
<p class="truncate font-medium">
<UnreadDot {path} class="mr-1" />{title || "Untitled thread"}
</p>
<div class="text-content-muted flex flex-wrap items-center gap-x-3 gap-y-1 text-xs">
<span class="flex min-w-0 items-center gap-1.5">
<ProfileCircle pubkey={event.pubkey} {url} size={4} />
@ -57,7 +52,7 @@
onclick={onClick}
class="hover:bg-surface-less cursor-pointer border-b border-solid border-line text-sm transition-colors">
<td class="max-w-0 truncate px-4 py-3 align-top">
{@render unread()}{title || "Untitled thread"}
<UnreadDot {path} class="mr-1" />{title || "Untitled thread"}
</td>
<td class="w-32 px-4 py-3 align-middle">
<div class="flex min-w-0 items-center gap-2">

View file

@ -8,6 +8,7 @@
import ThreadActions from "@app/components/ThreadActions.svelte"
import type {FeedContext} from "@app/feeds"
import RoomLink from "@app/components/RoomLink.svelte"
import UnreadDot from "@app/components/UnreadDot.svelte"
import {makeThreadPath} from "@app/routes"
type Props = {
@ -18,13 +19,13 @@
const {url, event, context}: Props = $props()
const path = makeThreadPath(url, event.id)
const title = tagValue(tagSpec("title"), event.tags)
const h = tagValue(tagSpec("h"), event.tags)
</script>
<Link
class="cv flex flex-col gap-2 card card-interactive w-full"
href={makeThreadPath(url, event.id)}>
<Link class="cv relative flex flex-col gap-2 card card-interactive w-full" href={path}>
<UnreadDot {path} class="absolute right-3 top-3" />
{#if title}
<div class="flex w-full items-center justify-between gap-2">
<p class="text-xl">{title}</p>

View file

@ -92,7 +92,7 @@
Reply
</Button>
{#if isComment}
<CommentActions segment="threads" {event} {url} {context} />
<CommentActions {event} {url} {context} />
{:else}
<ThreadActions {event} {url} {context} />
{/if}

View file

@ -0,0 +1,16 @@
<script lang="ts">
import cx from "classnames"
import {fade} from "@lib/transition"
import {notifications} from "@app/notifications"
type Props = {
path: string
class?: string
}
const {path, class: className}: Props = $props()
</script>
{#if $notifications.has(path)}
<div class={cx("inline-block h-2 w-2 rounded-full bg-primary", className)} transition:fade></div>
{/if}

View file

@ -1,18 +1,7 @@
import {derived, get, writable} from "svelte/store"
import {Badge} from "@capawesome/capacitor-badge"
import {page} from "$app/stores"
import {
assoc,
prop,
first,
identity,
groupBy,
now,
remove,
throttle,
parseJson,
gt,
} from "@welshman/lib"
import {assoc, first, identity, groupBy, now, remove, throttle, parseJson, gt} from "@welshman/lib"
import type {SignedEvent, TrustedEvent} from "@welshman/util"
import {
getIdOrAddress,
@ -48,8 +37,6 @@ export const checked = withGetter(
export const getChecked = (key: string) => checked.get()[key]
export const deriveChecked = (key: string) => derived(checked, prop<number>(key))
export const setChecked = (key: string) => checked.update(assoc(key, now()))
/** Room path while video call UI hides chat; checked + badge stay active until chat is shown. */

View file

@ -101,7 +101,7 @@
<NoteCard event={reply} {url} class="card z-feature w-full">
<div class="flex flex-col gap-3 ml-12">
<NoteContent showEntire event={reply} {url} />
<CommentActions segment="calendar" event={reply} {url} {context} />
<CommentActions event={reply} {url} {context} />
</div>
</NoteCard>
{/each}

View file

@ -89,7 +89,7 @@
<NoteCard event={reply} {url} class="card z-feature w-full">
<div class="flex flex-col gap-3 ml-12">
<NoteContent showEntire event={reply} {url} />
<CommentActions segment="classifieds" event={reply} {url} {context} />
<CommentActions event={reply} {url} {context} />
</div>
</NoteCard>
{/each}

View file

@ -90,7 +90,7 @@
<NoteCard event={reply} {url} class="card z-feature w-full">
<div class="flex flex-col gap-3 ml-12">
<NoteContent showEntire event={reply} {url} />
<CommentActions segment="goals" event={reply} {url} {context} />
<CommentActions event={reply} {url} {context} />
</div>
</NoteCard>
{/each}

View file

@ -86,7 +86,7 @@
<NoteCard event={$event} {url} class="card z-feature w-full">
<div class="flex flex-col gap-3 ml-12 flex flex-col gap-3">
<NoteContent showEntire event={$event} {url} />
<CommentActions segment="polls" showActivity {url} event={$event} {context} />
<CommentActions showActivity {url} event={$event} {context} />
</div>
</NoteCard>
{#if !showAll && $comments.length > 4}
@ -101,7 +101,7 @@
<NoteCard event={reply} {url} class="card z-feature w-full">
<div class="flex flex-col gap-3 ml-12">
<NoteContent showEntire event={reply} {url} />
<CommentActions segment="polls" event={reply} {url} {context} />
<CommentActions event={reply} {url} {context} />
</div>
</NoteCard>
{/each}