fix: improve draft loading and add autocomplete debug logging

- Load drafts using setContent after editor is ready instead of initialContent prop
- Add onReady callback to NostrEditor to notify when editor is mounted
- Add console.log debugging to trace autocomplete update flow
This commit is contained in:
Claude
2026-01-20 16:27:18 +00:00
parent cc7b0448ca
commit d540f4a91e
2 changed files with 38 additions and 10 deletions

View File

@@ -56,26 +56,37 @@ export function PostViewer() {
// Use pubkey as draft key - one draft per account, persists across reloads
const draftKey = pubkey ? `${DRAFT_STORAGE_PREFIX}${pubkey}` : null;
// Load draft from localStorage on mount (stores full TipTap JSON for rich content)
const [initialContent, setInitialContent] = useState<object | undefined>(
undefined,
);
// Track if editor is mounted and draft is loaded
const [editorReady, setEditorReady] = useState(false);
const draftLoadedRef = useRef(false);
// Callback when editor mounts - triggers draft loading
const handleEditorReady = useCallback(() => {
setEditorReady(true);
}, []);
// Load draft from localStorage after editor is ready
useEffect(() => {
if (draftLoadedRef.current || !draftKey) return;
if (
draftLoadedRef.current ||
!draftKey ||
!editorReady ||
!editorRef.current
)
return;
draftLoadedRef.current = true;
try {
const savedDraft = localStorage.getItem(draftKey);
if (savedDraft) {
const parsed = JSON.parse(savedDraft);
setInitialContent(parsed);
// Use setContent to load draft after editor is mounted
editorRef.current.setContent(parsed);
}
} catch (error) {
console.warn("[PostViewer] Failed to load draft:", error);
}
}, [draftKey]);
}, [draftKey, editorReady]);
// Save draft to localStorage when content changes (uses full TipTap JSON)
const saveDraft = useCallback(() => {
@@ -250,7 +261,7 @@ export function PostViewer() {
minLines={6}
suggestions={suggestions}
onChange={handleChange}
initialContent={initialContent}
onReady={handleEditorReady}
autoFocus
/>

View File

@@ -66,12 +66,14 @@ export type { NostrEditorHandle };
export interface NostrEditorProps {
/** Placeholder text when editor is empty */
placeholder?: string;
/** Initial content (plain text) */
/** Initial content (plain text or TipTap JSON) */
initialContent?: string | object;
/** Called when content is submitted */
onSubmit?: (content: SerializedContent) => void;
/** Called when content changes */
onChange?: (content: SerializedContent) => void;
/** Called when editor is ready (mounted and initialized) */
onReady?: () => void;
/** Submit behavior: 'enter' (chat), 'ctrl-enter' (post), 'button-only' (external button) */
submitBehavior?: SubmitBehavior;
/** Layout variant: 'inline' (chat), 'multiline' (auto-expand), 'full' (fixed height) */
@@ -350,7 +352,11 @@ function createMentionSuggestionConfig(
items: async ({ query }) => {
// Always use the current search function from refs
const searchFn = refsObj.current.mentionSearch;
return await searchFn(query);
const results = await searchFn(query);
console.log(
`[NostrEditor] Mention items() query="${query}" results=${results.length}`,
);
return results;
},
render: () => {
let component: ReactRenderer<SuggestionListHandle>;
@@ -359,6 +365,9 @@ function createMentionSuggestionConfig(
return {
onStart: (props) => {
console.log(
`[NostrEditor] Mention onStart items=${props.items?.length}`,
);
editorRef = props.editor;
component = new ReactRenderer(config.component as never, {
props: {
@@ -384,6 +393,9 @@ function createMentionSuggestionConfig(
},
onUpdate(props) {
console.log(
`[NostrEditor] Mention onUpdate items=${props.items?.length}`,
);
component.updateProps({
items: props.items,
command: props.command,
@@ -585,6 +597,7 @@ export const NostrEditor = forwardRef<NostrEditorHandle, NostrEditorProps>(
initialContent,
onSubmit,
onChange,
onReady,
submitBehavior = "enter",
variant = "inline",
minLines = 1,
@@ -935,6 +948,10 @@ export const NostrEditor = forwardRef<NostrEditorHandle, NostrEditorProps>(
},
},
autofocus: autoFocus,
onCreate: () => {
// Notify parent that editor is ready for operations like loading drafts
onReady?.();
},
onUpdate: ({ editor }) => {
if (onChange) {
onChange(serializeContent(editor));