From 80838fb2041c4e2b16ff3a2a9b75c7e1d654bb29 Mon Sep 17 00:00:00 2001 From: Jure <44338+hoornet@users.noreply.github.com> Date: Fri, 20 Mar 2026 16:32:50 +0100 Subject: [PATCH] Refactor: split overgrown files into focused modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split client.ts (1036 lines) into 11 domain modules under lib/nostr/ — core, notes, social, articles, engagement, dms, bookmarks, muting, search, relays, trending. Barrel index.ts re-exports all; zero consumer import changes. Extract ProfileView sub-components (ImageField, Nip05Field, EditProfileForm, ProfileMediaGallery), NoteContent renderers (TextSegments, MediaCards), and NoteCard actions (NoteActions, InlineReplyBox). All component files now ≤270 lines, all lib files ≤300. --- src/components/feed/InlineReplyBox.tsx | 96 ++ src/components/feed/MediaCards.tsx | 116 ++ src/components/feed/NoteActions.tsx | 224 ++++ src/components/feed/NoteCard.tsx | 283 +---- src/components/feed/NoteContent.tsx | 367 +----- src/components/feed/TextSegments.tsx | 116 ++ src/components/profile/EditProfileForm.tsx | 96 ++ src/components/profile/ImageField.tsx | 50 + src/components/profile/Nip05Field.tsx | 62 + .../profile/ProfileMediaGallery.tsx | 130 +++ src/components/profile/ProfileView.tsx | 338 +----- src/lib/nostr/articles.ts | 106 ++ src/lib/nostr/bookmarks.ts | 49 + src/lib/nostr/client.ts | 1036 ----------------- src/lib/nostr/core.ts | 82 ++ src/lib/nostr/dms.ts | 119 ++ src/lib/nostr/engagement.ts | 134 +++ src/lib/nostr/index.ts | 15 +- src/lib/nostr/muting.ts | 23 + src/lib/nostr/notes.ts | 154 +++ src/lib/nostr/relays.ts | 64 + src/lib/nostr/search.ts | 159 +++ src/lib/nostr/social.ts | 98 ++ src/lib/nostr/trending.ts | 45 + 24 files changed, 1973 insertions(+), 1989 deletions(-) create mode 100644 src/components/feed/InlineReplyBox.tsx create mode 100644 src/components/feed/MediaCards.tsx create mode 100644 src/components/feed/NoteActions.tsx create mode 100644 src/components/feed/TextSegments.tsx create mode 100644 src/components/profile/EditProfileForm.tsx create mode 100644 src/components/profile/ImageField.tsx create mode 100644 src/components/profile/Nip05Field.tsx create mode 100644 src/components/profile/ProfileMediaGallery.tsx create mode 100644 src/lib/nostr/articles.ts create mode 100644 src/lib/nostr/bookmarks.ts delete mode 100644 src/lib/nostr/client.ts create mode 100644 src/lib/nostr/core.ts create mode 100644 src/lib/nostr/dms.ts create mode 100644 src/lib/nostr/engagement.ts create mode 100644 src/lib/nostr/muting.ts create mode 100644 src/lib/nostr/notes.ts create mode 100644 src/lib/nostr/relays.ts create mode 100644 src/lib/nostr/search.ts create mode 100644 src/lib/nostr/social.ts create mode 100644 src/lib/nostr/trending.ts diff --git a/src/components/feed/InlineReplyBox.tsx b/src/components/feed/InlineReplyBox.tsx new file mode 100644 index 0000000..ace45be --- /dev/null +++ b/src/components/feed/InlineReplyBox.tsx @@ -0,0 +1,96 @@ +import { useState, useRef } from "react"; +import { NDKEvent } from "@nostr-dev-kit/ndk"; +import { publishReply } from "../../lib/nostr"; +import { useReplyCount } from "../../hooks/useReplyCount"; +import { EmojiPicker } from "../shared/EmojiPicker"; + +interface InlineReplyBoxProps { + event: NDKEvent; + name: string; +} + +export function InlineReplyBox({ event, name }: InlineReplyBoxProps) { + const [replyText, setReplyText] = useState(""); + const [replying, setReplying] = useState(false); + const [replyError, setReplyError] = useState(null); + const [replySent, setReplySent] = useState(false); + const [showReplyEmoji, setShowReplyEmoji] = useState(false); + const replyRef = useRef(null); + const [, adjustReplyCount] = useReplyCount(event.id); + + const handleReplySubmit = async () => { + if (!replyText.trim() || replying) return; + setReplying(true); + setReplyError(null); + try { + await publishReply(replyText.trim(), { id: event.id, pubkey: event.pubkey }); + setReplyText(""); + setReplySent(true); + adjustReplyCount(1); + setTimeout(() => { setReplySent(false); }, 1500); + } catch (err) { + setReplyError(`Failed: ${err}`); + } finally { + setReplying(false); + } + }; + + const handleReplyKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) handleReplySubmit(); + if (e.key === "Escape") { + // Parent controls visibility — just blur + replyRef.current?.blur(); + } + }; + + return ( +
+