diff --git a/src/components/InboxViewer.tsx b/src/components/InboxViewer.tsx index 30e3a43..bab40a9 100644 --- a/src/components/InboxViewer.tsx +++ b/src/components/InboxViewer.tsx @@ -21,13 +21,10 @@ import eventStore from "@/services/event-store"; import { Settings, MessageSquare, - Radio, + Wifi, ShieldCheck, ShieldAlert, Loader2, - Plug, - PlugZap, - Lock, } from "lucide-react"; import { toast } from "sonner"; import giftWrapManager from "@/services/gift-wrap"; @@ -35,6 +32,9 @@ import relayStateManager from "@/services/relay-state-manager"; import type { GlobalRelayState } from "@/types/relay-state"; import { RelayLink } from "@/components/nostr/RelayLink"; import { UserName } from "@/components/nostr/UserName"; +import { RichText } from "@/components/nostr/RichText"; +import Timestamp from "@/components/Timestamp"; +import { getConnectionIcon, getAuthIcon } from "@/lib/relay-status-utils"; import { DropdownMenu, DropdownMenuContent, @@ -223,31 +223,41 @@ export function InboxViewer(_props: InboxViewerProps) { {/* Compact Header - Like req viewer */}
{/* Left: Status */} -
- - -
- {syncEnabled ? ( - - ) : ( - - )} - - {syncEnabled ? "SYNC" : "OFF"} - -
-
- -

+ + +

+ {syncEnabled ? ( + + ) : ( + + )} + + {syncEnabled ? "SYNC" : "OFF"} + +
+ + +
+

{syncEnabled - ? "Gift wrap sync enabled" - : "Gift wrap sync disabled"} + ? "Gift Wrap Sync Active" + : "Gift Wrap Sync Disabled"}

- - -
+ {syncEnabled && ( + <> +

+ Total: {stats.totalGiftWraps} gift wraps +

+

+ Auto-decrypt: {autoDecrypt ? "ON" : "OFF"} +

+ + )} +
+ + - {/* Right: Stats + Controls */} + {/* Center: Stats */}
{/* Stats - Compact numbers only */} @@ -291,77 +301,71 @@ export function InboxViewer(_props: InboxViewerProps) {

Pending decryptions

+
- {/* Relay Dropdown (no chevron) */} + {/* Right: Relay + Settings */} +
+ {/* Relay Dropdown */} - - - DM Relays - -
+ +
+
+ DM Relays ({dmRelays.length}) +
+
+
{dmRelays.length > 0 ? ( - dmRelays.map((relay) => { - const state = relayState?.relays[relay]; - const isConnected = state?.connectionState === "connected"; - const isAuth = state?.authStatus === "authenticated"; +
+ {dmRelays.map((relay) => { + const state = relayState?.relays[relay]; + const connIcon = getConnectionIcon(state); + const authIcon = getAuthIcon(state); - return ( -
-
- -
-
- {/* Connection status */} - - -
- {isConnected ? ( - - ) : ( - - )} -
-
- -

- {isConnected - ? "Connected" - : state?.connectionState || "Disconnected"} -

-
-
- - {/* Auth status */} - {isAuth && ( + return ( +
+
+ +
+
- + {connIcon.icon}
-

Authenticated

+

{connIcon.label}

- )} + + +
+ {authIcon.icon} +
+
+ +

{authIcon.label}

+
+
+
-
- ); - }) + ); + })} +
) : (

No DM relays configured. Using general relays from kind @@ -528,43 +532,27 @@ function ConversationRow({ latestMessage, onClick, }: ConversationRowProps) { - // Format timestamp - const timestamp = new Date(latestMessage.createdAt * 1000); - const now = new Date(); - const isToday = timestamp.toDateString() === now.toDateString(); - const timeStr = isToday - ? timestamp.toLocaleTimeString(undefined, { - hour: "2-digit", - minute: "2-digit", - }) - : timestamp.toLocaleDateString(undefined, { - month: "short", - day: "numeric", - }); - - // Truncate content preview - show more text - const preview = latestMessage.content.slice(0, 100); - const truncated = latestMessage.content.length > 100; - return (

{/* Name */} -
- +
+
- {/* Message preview - no flex-1 to avoid big gap */} - - {preview} - {truncated && "..."} - + {/* Message preview - use CSS truncation and RichText */} +
+ +
- {/* Timestamp - push to end with ml-auto */} - - {timeStr} + {/* Timestamp */} + +
); diff --git a/src/services/gift-wrap.ts b/src/services/gift-wrap.ts index f8bec68..85a4ce5 100644 --- a/src/services/gift-wrap.ts +++ b/src/services/gift-wrap.ts @@ -286,11 +286,12 @@ class GiftWrapManager { const { pubkey } = account; - // Get oldest gift wrap timestamp, or use lastSyncTimestamp if no gift wraps yet + // Get oldest gift wrap timestamp from actual gift wrap events, not decryption attempts + // Get all gift wrap IDs for this user const decryptions = await db.giftWrapDecryptions .where("recipientPubkey") .equals(pubkey) - .sortBy("lastAttempt"); + .toArray(); let oldestTimestamp: number; if (decryptions.length === 0) { @@ -306,7 +307,24 @@ class GiftWrapManager { console.log("[GiftWrap] No gift wraps yet, starting from 90 days ago"); } } else { - oldestTimestamp = decryptions[0].lastAttempt; + // Find the oldest gift wrap event by looking up events in the event store + let oldest = Infinity; + for (const decryption of decryptions) { + const event = eventStore.getEvent(decryption.giftWrapId); + if (event && event.created_at < oldest) { + oldest = event.created_at; + } + } + + if (oldest === Infinity) { + // Fallback if no events found in store + const now = Math.floor(Date.now() / 1000); + oldestTimestamp = + now - GIFT_WRAP_CONFIG.MAX_STORAGE_DAYS * 24 * 60 * 60; + console.log("[GiftWrap] No gift wraps in event store, using fallback"); + } else { + oldestTimestamp = oldest; + } } const cutoff = oldestTimestamp - 30 * 24 * 60 * 60; // 30 days before oldest