Online Cross-Device Notes Synchronization Tool

Online Cross-Device Notes Synchronization Tool

Your User ID: Connecting...

Last saved:

Welcome to your Notes

Select a note on the left or create a new one to get started.

No notes yet. Create one!

`; return; } allNotes.forEach(note => { const div = document.createElement('div'); div.className = `note-item p-4 border-b border-gray-200 cursor-pointer hover:bg-gray-100 ${note.id === selectedNoteId ? 'active' : ''}`; div.dataset.noteId = note.id; const updatedTime = note.updatedAt ? new Date(note.updatedAt.toMillis()).toLocaleString([], { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }) : '...'; div.innerHTML = `

${note.title || 'Untitled Note'}

${updatedTime}

`; notesListEl.appendChild(div); }); } function displayNoteContent(note) { welcomeScreen.classList.add('hidden'); editorArea.classList.remove('hidden'); editorArea.classList.add('flex'); noteTitleInput.value = note.title; noteContentTextarea.value = note.content; lastSavedStatus.textContent = note.updatedAt ? new Date(note.updatedAt.toMillis()).toLocaleTimeString() : 'Just now'; } function showWelcomeScreen() { selectedNoteId = null; editorArea.classList.add('hidden'); editorArea.classList.remove('flex'); welcomeScreen.classList.remove('hidden'); renderNotesList(); // To remove active state } // --- CRUD OPERATIONS --- async function createNewNote() { if (!currentUserId) return; try { const newNoteRef = await addDoc(collection(db, `artifacts/${appId}/users/${currentUserId}/notes`), { title: 'Untitled Note', content: '', createdAt: serverTimestamp(), updatedAt: serverTimestamp() }); selectedNoteId = newNoteRef.id; renderNotesList(); // Re-render to show new note immediately } catch (error) { console.error("Error creating new note:", error); } } async function updateNote() { if (!selectedNoteId || !currentUserId) return; const noteRef = doc(db, `artifacts/${appId}/users/${currentUserId}/notes`, selectedNoteId); try { await updateDoc(noteRef, { title: noteTitleInput.value, content: noteContentTextarea.value, updatedAt: serverTimestamp() }); } catch (error) { console.error("Error updating note:", error); } } async function deleteNote() { if (!selectedNoteId || !currentUserId) return; if (confirm(`Are you sure you want to delete "${noteTitleInput.value}"?`)) { const noteRef = doc(db, `artifacts/${appId}/users/${currentUserId}/notes`, selectedNoteId); try { await deleteDoc(noteRef); showWelcomeScreen(); } catch (error) { console.error("Error deleting note:", error); } } } // --- EVENT LISTENERS --- newNoteBtn.addEventListener('click', createNewNote); deleteNoteBtn.addEventListener('click', deleteNote); notesListEl.addEventListener('click', (e) => { const noteItem = e.target.closest('.note-item'); if (noteItem) { const noteId = noteItem.dataset.noteId; const note = allNotes.find(n => n.id === noteId); if (note) { selectedNoteId = noteId; displayNoteContent(note); renderNotesList(); // Re-render to show active state } } }); // Debounced save on input const handleInput = () => { lastSavedStatus.textContent = 'Saving...'; clearTimeout(debounceTimer); debounceTimer = setTimeout(updateNote, 1000); // Save 1 second after user stops typing }; noteTitleInput.addEventListener('input', handleInput); noteContentTextarea.addEventListener('input', handleInput); // --- INITIALIZATION --- initializeAuth(); });
Scroll to Top