From 70db78fe3b55cf6df70aeb6a8be8c510ca937d9a Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Jan 2026 09:39:58 +0000 Subject: [PATCH] refactor: Make republish code production-ready with optimizations and accessibility Comprehensive improvements to the republish feature for production deployment: **Performance Optimizations**: - Use useMemo for expensive computations (seenRelays, connectedRelays, allRelays) - Use useCallback for event handlers to prevent unnecessary re-renders - Memoize connected relays filter to avoid duplicate array operations - Reduce re-renders by caching computed values **Better Error Handling**: - Add try-catch with proper error logging to console - Extract error messages consistently across handlers - Add .catch() to relay fetch promise for graceful failures - Prevent duplicate publish operations with guard clauses **Accessibility Improvements**: - Add aria-labels to all interactive buttons with descriptive text - Add role="group" to relay sections for screen readers - Add role="status" to empty state message - Add aria-hidden="true" to decorative icons - Add type="button" to prevent form submission - Add focus ring styles for keyboard navigation **Code Quality**: - Add JSDoc comments to all handler functions - Better variable naming (isPublishing flag, connectedRelays) - Consolidate duplicate code (connected relays filter) - Improve code organization with clear sections - Remove magic numbers and duplicate logic **Edge Cases**: - Check isPublishing before starting batch publish - Check publishingRelays.has(relay) before individual publish - Handle relay fetch errors gracefully without crashing - Proper state cleanup in finally blocks **State Management**: - Consistent state updates using functional updates - Proper Set operations for tracking publishing/published states - Clear separation between local UI state and event state All tests pass and build succeeds. Code is now production-ready. --- .../nostr/kinds/BaseEventRenderer.tsx | 202 ++++++++++++------ 1 file changed, 134 insertions(+), 68 deletions(-) diff --git a/src/components/nostr/kinds/BaseEventRenderer.tsx b/src/components/nostr/kinds/BaseEventRenderer.tsx index 7b1224d..f7780ad 100644 --- a/src/components/nostr/kinds/BaseEventRenderer.tsx +++ b/src/components/nostr/kinds/BaseEventRenderer.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useState, useEffect, useMemo, useCallback } from "react"; import { NostrEvent } from "@/types/nostr"; import { UserName } from "../UserName"; import { KindBadge } from "@/components/KindBadge"; @@ -126,6 +126,7 @@ function formatRelayUrlForDisplay(url: string): string { /** * RelayPublishItem - Clickable relay item for republish submenu + * Shows relay info (icon, name, URL) with publish status */ function RelayPublishItem({ url, @@ -141,13 +142,22 @@ function RelayPublishItem({ const relayInfo = useRelayInfo(url); const displayUrl = formatRelayUrlForDisplay(url); + // Determine button label for accessibility + const ariaLabel = isPublished + ? `${displayUrl} - Already published` + : isPublishing + ? `${displayUrl} - Publishing...` + : `Publish event to ${displayUrl}`; + return ( @@ -390,18 +447,25 @@ export function EventMenu({ event }: { event: NostrEvent }) { {/* No relays available */} {allRelays.length === 0 && ( -
+
No relays available
)} - {/* My relays list */} + {/* User's outbox relays */} {account && myRelays.length > 0 && ( <> My relays -
+
{myRelays.map((relay) => ( )} - {/* Connected relays (seen relays not in my relays) */} - {seenRelays.filter((r) => !myRelays.includes(r)).length > 0 && ( + {/* Connected relays (seen on but not in user's list) */} + {connectedRelays.length > 0 && ( <> {account && myRelays.length > 0 && } Connected relays -
- {seenRelays - .filter((r) => !myRelays.includes(r)) - .map((relay) => ( - handleRepublishToRelay(relay)} - /> - ))} +
+ {connectedRelays.map((relay) => ( + handleRepublishToRelay(relay)} + /> + ))}
)}