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

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

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Alejandro
2026-02-12 22:16:18 +01:00
committed by GitHub
parent 140a4b207a
commit 7167d64d9c
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"
/>