diff --git a/src/components/PostWindow.tsx b/src/components/PostWindow.tsx index f916af3..3c07f61 100644 --- a/src/components/PostWindow.tsx +++ b/src/components/PostWindow.tsx @@ -1,4 +1,4 @@ -import { useCallback, useRef, useState, useMemo } from "react"; +import { useCallback, useRef, useState, useMemo, useEffect } from "react"; import { use$ } from "applesauce-react/hooks"; import accountManager from "@/services/accounts"; import { toast } from "sonner"; @@ -70,6 +70,22 @@ export function PostWindow({ kind = 1 }: PostWindowProps) { return new Set(pubkeys); }, [contactList]); + // Preload contact profiles for @ autocomplete + useEffect(() => { + if (contactPubkeys.size === 0) return; + + // Load profiles for all contacts (trigger fetching if not in store) + const pubkeysArray = Array.from(contactPubkeys); + for (const pubkey of pubkeysArray) { + // Subscribe to profile - this triggers loading if not in store + const sub = eventStore.replaceable(0, pubkey).subscribe(() => { + // Profile loaded or updated + }); + // Clean up subscription after initial load + setTimeout(() => sub.unsubscribe(), 1000); + } + }, [contactPubkeys]); + // Filter profile search to only contacts const searchContactProfiles = useCallback( async (query: string): Promise => { diff --git a/src/components/editor/PostComposer.tsx b/src/components/editor/PostComposer.tsx index 001affe..1c714f7 100644 --- a/src/components/editor/PostComposer.tsx +++ b/src/components/editor/PostComposer.tsx @@ -223,16 +223,20 @@ export const PostComposer = forwardRef( setExtractedMentions(mentions); setExtractedHashtags(hashtags); - // Auto-select new mentions + // Sync selected mentions with extracted mentions + // Remove mentions that are no longer in content setSelectedMentions((prev) => { + const stillPresent = prev.filter((m) => mentions.includes(m)); const newMentions = mentions.filter((m) => !prev.includes(m)); - return [...prev, ...newMentions]; + return [...stillPresent, ...newMentions]; }); - // Auto-select new hashtags + // Sync selected hashtags with extracted hashtags + // Remove hashtags that are no longer in content setSelectedHashtags((prev) => { + const stillPresent = prev.filter((h) => hashtags.includes(h)); const newHashtags = hashtags.filter((h) => !prev.includes(h)); - return [...prev, ...newHashtags]; + return [...stillPresent, ...newHashtags]; }); } }; diff --git a/src/index.css b/src/index.css index 463fcb9..83cbad5 100644 --- a/src/index.css +++ b/src/index.css @@ -380,25 +380,35 @@ body.animating-layout } /* Multi-row editor styles for card variant */ +.editor-card { + display: flex; + flex-direction: column; + align-items: stretch; +} + .editor-card .ProseMirror { min-height: 6rem; /* 4 rows at 1.5rem line-height */ overflow-y: auto; line-height: 1.5rem; padding: 0.75rem; - text-align: left; + text-align: left !important; vertical-align: top; } .editor-card .ProseMirror p { line-height: 1.5rem; margin-bottom: 0.5rem; - text-align: left; + text-align: left !important; } .editor-card .ProseMirror p:last-child { margin-bottom: 0; } +.editor-card .ProseMirror p.is-editor-empty:first-child::before { + text-align: left !important; +} + /* Mention styles */ .ProseMirror .mention { color: hsl(var(--primary));