fix(status): show Open by default instead of infinite loading spinner

StatusIndicator was stuck showing a loading spinner indefinitely when no
status events existed, because the useTimeline observable never completes
for live Nostr subscriptions. Default to showing "Open" immediately and
update reactively when status events arrive.

https://claude.ai/code/session_01UAjKegpi8uWyLdjgRpNeEJ
This commit is contained in:
Claude
2026-02-12 21:09:04 +00:00
parent 140a4b207a
commit 6668c8fd8a
4 changed files with 5 additions and 28 deletions

View File

@@ -1,10 +1,4 @@
import {
CircleDot,
CheckCircle2,
XCircle,
FileEdit,
Loader2,
} from "lucide-react";
import { CircleDot, CheckCircle2, XCircle, FileEdit } from "lucide-react";
import { getStatusType } from "@/lib/nip34-helpers";
/**
@@ -66,8 +60,6 @@ function getStatusBadgeClasses(kind: number): string {
export interface StatusIndicatorProps {
/** The status event kind (1630-1633) or undefined for default "open" */
statusKind?: number;
/** Whether status is loading */
loading?: boolean;
/** Event type for appropriate labeling (affects "resolved" vs "merged") */
eventType?: "issue" | "patch" | "pr";
/** Display variant */
@@ -82,23 +74,11 @@ export interface StatusIndicatorProps {
*/
export function StatusIndicator({
statusKind,
loading = false,
eventType = "issue",
variant = "inline",
className = "",
}: StatusIndicatorProps) {
if (loading) {
return (
<span
className={`inline-flex items-center gap-1.5 text-sm text-muted-foreground ${className}`}
>
<Loader2 className="size-3.5 animate-spin" />
<span>Loading...</span>
</span>
);
}
// Default to "open" if no status
// Default to "open" if no status (shown immediately, updates reactively when status events arrive)
const effectiveKind = statusKind ?? 1630;
// For patches/PRs, kind 1631 means "merged" not "resolved"

View File

@@ -88,7 +88,7 @@ export function IssueDetailRenderer({ event }: { event: NostrEvent }) {
[event.id],
);
const { events: statusEvents, loading: statusLoading } = useTimeline(
const { events: statusEvents } = useTimeline(
`issue-status-${event.id}`,
statusFilter,
statusRelays,
@@ -120,7 +120,6 @@ export function IssueDetailRenderer({ event }: { event: NostrEvent }) {
{/* Status Badge (below title) */}
<StatusIndicator
statusKind={currentStatus?.kind}
loading={statusLoading}
eventType="issue"
variant="badge"
/>

View File

@@ -91,7 +91,7 @@ export function PatchDetailRenderer({ event }: { event: NostrEvent }) {
[event.id],
);
const { events: statusEvents, loading: statusLoading } = useTimeline(
const { events: statusEvents } = useTimeline(
`patch-status-${event.id}`,
statusFilter,
statusRelays,
@@ -124,7 +124,6 @@ export function PatchDetailRenderer({ event }: { event: NostrEvent }) {
<div className="flex items-center gap-2 flex-wrap">
<StatusIndicator
statusKind={currentStatus?.kind}
loading={statusLoading}
eventType="patch"
variant="badge"
/>

View File

@@ -90,7 +90,7 @@ export function PullRequestDetailRenderer({ event }: { event: NostrEvent }) {
[event.id],
);
const { events: statusEvents, loading: statusLoading } = useTimeline(
const { events: statusEvents } = useTimeline(
`pr-status-${event.id}`,
statusFilter,
statusRelays,
@@ -124,7 +124,6 @@ export function PullRequestDetailRenderer({ event }: { event: NostrEvent }) {
{/* Status Badge (below title) */}
<StatusIndicator
statusKind={currentStatus?.kind}
loading={statusLoading}
eventType="pr"
variant="badge"
/>