From 5b4f6381dabc8a843f5355f3c8da7ef0364f303b Mon Sep 17 00:00:00 2001 From: Jure <44338+hoornet@users.noreply.github.com> Date: Sun, 15 Mar 2026 21:30:54 +0100 Subject: [PATCH] Add NIP-17 gift-wrapped DMs, follow-from-menu, fix new conversation crash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DMs now send via NIP-17 (kind 1059 gift-wrap) with self-copy for sent messages. Receive supports both NIP-17 and legacy NIP-04 for backward compat. Protocol indicator shown in conversation list and compose footer. Note card context menu (โ‹ฏ) now includes follow/unfollow option so users can follow authors directly from the feed without visiting their profile. Fix crash (black screen) when starting a new DM conversation โ€” empty event array caused undefined access on lastEvent. --- src-tauri/Cargo.lock | 2 +- src/components/dm/DMView.tsx | 50 +++++++++++++------ src/components/feed/NoteCard.tsx | 8 ++- src/lib/nostr/client.ts | 85 +++++++++++++++++++++++++++----- 4 files changed, 115 insertions(+), 30 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9fa6f4a..a9b8bc0 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -5824,7 +5824,7 @@ dependencies = [ [[package]] name = "wrystr" -version = "0.4.0" +version = "0.4.1" dependencies = [ "keyring", "rusqlite", diff --git a/src/components/dm/DMView.tsx b/src/components/dm/DMView.tsx index 220e466..2ac4525 100644 --- a/src/components/dm/DMView.tsx +++ b/src/components/dm/DMView.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from "react"; -import { NDKEvent, nip19 } from "@nostr-dev-kit/ndk"; +import { NDKEvent, NDKKind, nip19 } from "@nostr-dev-kit/ndk"; import { useUserStore } from "../../stores/user"; import { useUIStore } from "../../stores/ui"; import { useNotificationsStore } from "../../stores/notifications"; @@ -68,7 +68,9 @@ function ConvRow({ {name} {time} -
๐Ÿ”’ encrypted
+
+ {lastEvent.kind === NDKKind.PrivateDirectMessage ? "๐Ÿ”’ NIP-17" : "๐Ÿ”’ NIP-04"} +
); @@ -139,6 +141,7 @@ function ThreadPanel({ setMessages([]); fetchDMThread(myPubkey, partnerPubkey) .then(setMessages) + .catch((err) => console.error("Failed to fetch DM thread:", err)) .finally(() => setLoading(false)); }, [partnerPubkey, myPubkey]); @@ -222,7 +225,7 @@ function ThreadPanel({ {sending ? "โ€ฆ" : "send"} -

Ctrl+Enter to send ยท NIP-04 encrypted

+

Ctrl+Enter to send ยท gift-wrapped (NIP-17)

); @@ -314,6 +317,7 @@ export function DMView() { })); useNotificationsStore.getState().computeDMUnread(convList); }) + .catch((err) => console.error("Failed to fetch DM conversations:", err)) .finally(() => setLoading(false)); }, [pubkey, hasSigner]); @@ -355,18 +359,34 @@ export function DMView() { No messages yet. )} - {sortedPartners.map(([partner, events]) => ( - { - setSelectedPubkey(partner); - useNotificationsStore.getState().markDMRead(partner); - }} - /> - ))} + {sortedPartners.map(([partner, events]) => + events[0] ? ( + { + setSelectedPubkey(partner); + useNotificationsStore.getState().markDMRead(partner); + }} + /> + ) : ( + + ) + )}
setMenuOpen(false)} />
+