From 316908196de1fed35e333eba630c755f259963d5 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 20 Jan 2026 15:25:36 +0000 Subject: [PATCH] fix: improve NIP-75 goal rendering - Remove icons from goal renderers - Remove "sats" suffixes from amounts - Use muted text instead of destructive color for closed goals - Content is the title, summary tag is the description - Only show description if summary tag exists --- .../nostr/kinds/GoalDetailRenderer.tsx | 38 +++++++------------ src/components/nostr/kinds/GoalRenderer.tsx | 31 +++++++-------- src/lib/nip75-helpers.ts | 14 +------ 3 files changed, 30 insertions(+), 53 deletions(-) diff --git a/src/components/nostr/kinds/GoalDetailRenderer.tsx b/src/components/nostr/kinds/GoalDetailRenderer.tsx index 123e1b2..6158c27 100644 --- a/src/components/nostr/kinds/GoalDetailRenderer.tsx +++ b/src/components/nostr/kinds/GoalDetailRenderer.tsx @@ -1,12 +1,12 @@ import { useMemo } from "react"; import { NostrEvent } from "@/types/nostr"; -import { Target, Clock, Users } from "lucide-react"; import { useTimeline } from "@/hooks/useTimeline"; import { getGoalAmount, getGoalRelays, getGoalClosedAt, getGoalTitle, + getGoalSummary, isGoalClosed, getGoalBeneficiaries, } from "@/lib/nip75-helpers"; @@ -36,6 +36,7 @@ export function GoalDetailRenderer({ event }: { event: NostrEvent }) { const goalRelays = getGoalRelays(event); const closedAt = getGoalClosedAt(event); const title = getGoalTitle(event); + const summary = getGoalSummary(event); const closed = isGoalClosed(event); const beneficiaries = getGoalBeneficiaries(event); @@ -112,28 +113,20 @@ export function GoalDetailRenderer({ event }: { event: NostrEvent }) {
{/* Header */}
-
- -

{title}

-
+

{title}

- {/* Description */} - {event.content && ( -

- {event.content} -

+ {/* Description (summary tag only) */} + {summary && ( +

{summary}

)} {/* Deadline */} {closedAt && ( -
- +
{closed ? ( - - Goal closed on {deadlineText} - + Closed on {deadlineText} ) : ( - Ends {deadlineText} + Ends {deadlineText} )}
)} @@ -147,7 +140,7 @@ export function GoalDetailRenderer({ event }: { event: NostrEvent }) { {raisedSats.toLocaleString()} - of {targetSats.toLocaleString()} sats + of {targetSats.toLocaleString()}
@@ -178,12 +171,9 @@ export function GoalDetailRenderer({ event }: { event: NostrEvent }) { {/* Contributors */}
-
- -

- Contributors -

-
+

+ Contributors +

{loading && contributors.length === 0 ? (
@@ -219,7 +209,7 @@ export function GoalDetailRenderer({ event }: { event: NostrEvent }) { )}
- {amountSats.toLocaleString()} sats + {amountSats.toLocaleString()}
); diff --git a/src/components/nostr/kinds/GoalRenderer.tsx b/src/components/nostr/kinds/GoalRenderer.tsx index 1c66475..0f4a44d 100644 --- a/src/components/nostr/kinds/GoalRenderer.tsx +++ b/src/components/nostr/kinds/GoalRenderer.tsx @@ -4,13 +4,13 @@ import { BaseEventContainer, ClickableEventTitle, } from "./BaseEventRenderer"; -import { Target, Clock } from "lucide-react"; import { useTimeline } from "@/hooks/useTimeline"; import { getGoalAmount, getGoalRelays, getGoalClosedAt, getGoalTitle, + getGoalSummary, isGoalClosed, } from "@/lib/nip75-helpers"; import { getZapAmount } from "applesauce-common/helpers/zap"; @@ -31,6 +31,7 @@ export function GoalRenderer({ event }: BaseEventProps) { const goalRelays = getGoalRelays(event); const closedAt = getGoalClosedAt(event); const title = getGoalTitle(event); + const summary = getGoalSummary(event); const closed = isGoalClosed(event); // Fetch zaps for this goal from specified relays @@ -80,20 +81,17 @@ export function GoalRenderer({ event }: BaseEventProps) {
{/* Title */} -
- - - {title} - -
+ + {title} + - {/* Description (full content if different from title) */} - {event.content && event.content.trim() !== title && ( + {/* Description (summary tag only) */} + {summary && (

- {event.content} + {summary}

)} @@ -111,7 +109,7 @@ export function GoalRenderer({ event }: BaseEventProps) { {raisedSats.toLocaleString()} {" / "} - {targetSats.toLocaleString()} sats + {targetSats.toLocaleString()} )} @@ -124,10 +122,9 @@ export function GoalRenderer({ event }: BaseEventProps) { {/* Deadline */} {closedAt && ( -
- +
{closed ? ( - Closed + Closed on {deadlineText} ) : ( Ends {deadlineText} )} diff --git a/src/lib/nip75-helpers.ts b/src/lib/nip75-helpers.ts index a83b226..bd999d6 100644 --- a/src/lib/nip75-helpers.ts +++ b/src/lib/nip75-helpers.ts @@ -103,24 +103,14 @@ export function isGoalClosed(event: NostrEvent): boolean { /** * Get a display title for the goal - * Falls back to summary, then content truncated, then "Untitled Goal" + * Content is the goal title per NIP-75 * @param event Goal event (kind 9041) * @returns Display title string */ export function getGoalTitle(event: NostrEvent): string { - // First try summary tag - const summary = getGoalSummary(event); - if (summary) return summary; - - // Fall back to content (first line, truncated) const content = event.content?.trim(); if (content) { - const firstLine = content.split("\n")[0]; - if (firstLine.length > 80) { - return firstLine.slice(0, 77) + "..."; - } - return firstLine; + return content; } - return "Untitled Goal"; }