From dac08f1d2fd09707a01284341d3304fdea380278 Mon Sep 17 00:00:00 2001 From: drelich Date: Wed, 25 Mar 2026 23:43:14 +0100 Subject: [PATCH] Revert scroll position changes - restore original auto-resize behavior The attempts to fix scroll jumping caused other issues. Reverting to original working state with auto-resize, accepting the scroll-to-top behavior for now. This can be revisited later with more time for proper testing. --- src/components/NoteEditor.tsx | 118 ++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 47 deletions(-) diff --git a/src/components/NoteEditor.tsx b/src/components/NoteEditor.tsx index cf5ed74..07e0411 100644 --- a/src/components/NoteEditor.tsx +++ b/src/components/NoteEditor.tsx @@ -25,11 +25,13 @@ const imageCache = new Map(); export function NoteEditor({ note, onUpdateNote, onUnsavedChanges, categories, isFocusMode, onToggleFocusMode, editorFont = 'Source Code Pro', editorFontSize = 14, previewFont = 'Merriweather', previewFontSize = 16, api }: NoteEditorProps) { + const [localTitle, setLocalTitle] = useState(''); const [localContent, setLocalContent] = useState(''); const [localCategory, setLocalCategory] = useState(''); const [localFavorite, setLocalFavorite] = useState(false); const [isSaving, setIsSaving] = useState(false); const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false); + const [titleManuallyEdited, setTitleManuallyEdited] = useState(false); const [isExportingPDF, setIsExportingPDF] = useState(false); const [isPreviewMode, setIsPreviewMode] = useState(false); const [processedContent, setProcessedContent] = useState(''); @@ -138,10 +140,17 @@ export function NoteEditor({ note, onUpdateNote, onUnsavedChanges, categories, i useEffect(() => { const loadNewNote = () => { if (note) { + setLocalTitle(note.title); setLocalContent(note.content); setLocalCategory(note.category || ''); setLocalFavorite(note.favorite); setHasUnsavedChanges(false); + setIsPreviewMode(false); + setProcessedContent(''); // Clear preview content immediately + + const firstLine = note.content.split('\n')[0].replace(/^#+\s*/, '').trim(); + const titleMatchesFirstLine = note.title === firstLine || note.title === firstLine.substring(0, 50); + setTitleManuallyEdited(!titleMatchesFirstLine); previousNoteIdRef.current = note.id; previousNoteContentRef.current = note.content; @@ -175,14 +184,9 @@ export function NoteEditor({ note, onUpdateNote, onUnsavedChanges, categories, i console.log('Last 50 chars:', localContent.slice(-50)); setIsSaving(true); setHasUnsavedChanges(false); - - // Extract title from first line - const firstLine = localContent.split('\n')[0].replace(/^#+\s*/, '').trim(); - const title = firstLine || 'Untitled'; - onUpdateNote({ ...note, - title, + title: localTitle, content: localContent, category: localCategory, favorite: localFavorite, @@ -190,18 +194,36 @@ export function NoteEditor({ note, onUpdateNote, onUnsavedChanges, categories, i setTimeout(() => setIsSaving(false), 500); }; + const handleTitleChange = (value: string) => { + setLocalTitle(value); + setTitleManuallyEdited(true); + setHasUnsavedChanges(true); + }; + const handleContentChange = (value: string) => { setLocalContent(value); setHasUnsavedChanges(true); + + if (!titleManuallyEdited) { + const firstLine = value.split('\n')[0].replace(/^#+\s*/, '').trim(); + if (firstLine) { + setLocalTitle(firstLine.substring(0, 50)); + } + } }; const handleDiscard = () => { if (!note) return; + setLocalTitle(note.title); setLocalContent(note.content); setLocalCategory(note.category || ''); setLocalFavorite(note.favorite); setHasUnsavedChanges(false); + + const firstLine = note.content.split('\n')[0].replace(/^#+\s*/, '').trim(); + const titleMatchesFirstLine = note.title === firstLine || note.title === firstLine.substring(0, 50); + setTitleManuallyEdited(!titleMatchesFirstLine); }; const loadFontAsBase64 = async (fontPath: string): Promise => { @@ -322,8 +344,7 @@ export function NoteEditor({ note, onUpdateNote, onUnsavedChanges, categories, i container.style.color = '#000000'; const titleElement = document.createElement('h1'); - const firstLine = localContent.split('\n')[0].replace(/^#+\s*/, '').trim(); - titleElement.textContent = firstLine || 'Untitled'; + titleElement.textContent = localTitle || 'Untitled'; titleElement.style.marginTop = '0'; titleElement.style.marginBottom = '20px'; titleElement.style.fontSize = '24px'; @@ -364,8 +385,7 @@ export function NoteEditor({ note, onUpdateNote, onUnsavedChanges, categories, i // Use jsPDF's html() method with custom font set await pdf.html(container, { callback: async (doc) => { - const firstLine = localContent.split('\n')[0].replace(/^#+\s*/, '').trim(); - const fileName = `${firstLine || 'note'}.pdf`; + const fileName = `${localTitle || 'note'}.pdf`; doc.save(fileName); setTimeout(async () => { @@ -402,12 +422,9 @@ export function NoteEditor({ note, onUpdateNote, onUnsavedChanges, categories, i const handleFavoriteToggle = () => { setLocalFavorite(!localFavorite); if (note) { - const firstLine = localContent.split('\n')[0].replace(/^#+\s*/, '').trim(); - const title = firstLine || 'Untitled'; - onUpdateNote({ ...note, - title, + title: localTitle, content: localContent, category: localCategory, favorite: !localFavorite, @@ -421,24 +438,12 @@ export function NoteEditor({ note, onUpdateNote, onUnsavedChanges, categories, i }; const handleAttachmentUpload = async (event: React.ChangeEvent) => { - console.log('handleAttachmentUpload called'); const file = event.target.files?.[0]; - console.log('File selected:', file?.name); - console.log('Current note ID:', note?.id); - console.log('Current note title:', note?.title); - console.log('Current note category:', note?.category); - console.log('API available:', !!api); - - if (!file || !note || !api) { - console.log('Upload aborted - missing:', { file: !!file, note: !!note, api: !!api }); - return; - } + if (!file || !note || !api) return; setIsUploading(true); - console.log('Starting upload for file:', file.name, 'to note:', note.id); try { const relativePath = await api.uploadAttachment(note.id, file, note.category); - console.log('Upload successful, path:', relativePath); // Determine if it's an image or other file const isImage = file.type.startsWith('image/'); @@ -466,10 +471,16 @@ export function NoteEditor({ note, onUpdateNote, onUnsavedChanges, categories, i setHasUnsavedChanges(true); } - console.log('Attachment uploaded successfully!'); + await message(`Attachment uploaded successfully!`, { + title: 'Upload Complete', + kind: 'info', + }); } catch (error) { console.error('Upload failed:', error); - alert(`Failed to upload attachment: ${error}`); + await message(`Failed to upload attachment: ${error}`, { + title: 'Upload Failed', + kind: 'error', + }); } finally { setIsUploading(false); // Reset file input @@ -656,6 +667,36 @@ export function NoteEditor({ note, onUpdateNote, onUnsavedChanges, categories, i return (
+ {/* Header */} +
+
+
+ handleTitleChange(e.target.value)} + placeholder="Note Title" + className="w-full text-2xl font-semibold border-none outline-none focus:ring-0 bg-transparent text-gray-900 dark:text-gray-100 placeholder-gray-400" + /> +
+ + +
+
+ {/* Toolbar */}
@@ -725,21 +766,6 @@ export function NoteEditor({ note, onUpdateNote, onUnsavedChanges, categories, i {/* Action Buttons */}
- -