diff --git a/lib/main.dart b/lib/main.dart index a72f687..2c4efbf 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -48,9 +48,7 @@ Future alreadyRunning() async { final executable = Platform.resolvedExecutable; final executableName = path.basename(executable); final journalers = - processes - .where((process) => process == executableName) - .toList(); + processes.where((process) => process == executableName).toList(); debugPrint("Journalers: $journalers"); return journalers.length > 1; } @@ -359,8 +357,9 @@ class MainPageState extends State with WindowListener { } @override - void onWindowClose() { - _saveData(); + void onWindowClose() async { + // Save data when window is closed + await _saveData(); windowManager.hide(); } @@ -494,6 +493,12 @@ class MainPageState extends State with WindowListener { Future _goToPreviousNote() async { if (!_canGoPrevious || _currentlyDisplayedNote == null) return; + // Save the current note content before navigating away + if (_currentlyDisplayedNote != null) { + _currentlyDisplayedNote!.content = _previousEntryController.text; + await updateNote(_currentlyDisplayedNote!); + } + final prevNote = await getPreviousNote(_currentlyDisplayedNote!.date); if (prevNote != null) { setState(() { @@ -507,6 +512,12 @@ class MainPageState extends State with WindowListener { Future _goToNextNote() async { if (!_canGoNext || _currentlyDisplayedNote == null) return; + // Save the current note content before navigating away + if (_currentlyDisplayedNote != null) { + _currentlyDisplayedNote!.content = _previousEntryController.text; + await updateNote(_currentlyDisplayedNote!); + } + final nextNote = await getNextNote(_currentlyDisplayedNote!.date); if (nextNote != null) { setState(() { @@ -565,18 +576,40 @@ class MainPageState extends State with WindowListener { debugPrint("Volume saved: $_volume"); } - void _saveData() async { + Future _saveData() async { String previousEntry = _previousEntryController.text; String currentEntry = _currentEntryController.text; String scratchContent = _scratchController.text; String intervalStr = _intervalController.text; String soundStr = _soundController.text; - await createNote(currentEntry); + // Handle current entry + if (currentEntry.isNotEmpty) { + await createNote(currentEntry); + } + + // Handle scratch pad await createScratch(scratchContent); - if (previousNote != null) { - previousNote!.content = previousEntry; - await updateNote(previousNote!); + + // Handle previous/currently displayed note + if (_currentlyDisplayedNote != null) { + _currentlyDisplayedNote!.content = previousEntry; + await updateNote(_currentlyDisplayedNote!); + + // If the note was deleted (due to being empty), update the UI state + if (previousEntry.isEmpty) { + // Check if we need to navigate to another note + Note? nextNote = await getLatestNote(); + setState(() { + _currentlyDisplayedNote = nextNote; + if (nextNote != null) { + _previousEntryController.text = nextNote.content; + } else { + _previousEntryController.text = ""; + } + }); + await _checkNavigation(); + } } int newIntervalMinutes = @@ -716,9 +749,15 @@ class MainPageState extends State with WindowListener { try { final results = await searchNotes(trimmedQuery); + // Filter out empty notes (which may exist in the search index but were deleted) + final filteredResults = + results + .where((note) => note.content.isNotEmpty) + .toList(); + // Important: update the dialog state after search completes dialogSetState(() { - _searchResults = results; + _searchResults = filteredResults; _isSearching = false; }); } catch (e) { @@ -787,7 +826,18 @@ class MainPageState extends State with WindowListener { ), // Smaller font for content ), isThreeLine: true, - onTap: () { + onTap: () async { + // Save current note if needed + if (_currentlyDisplayedNote != + null) { + _currentlyDisplayedNote!.content = + _previousEntryController.text; + await updateNote( + _currentlyDisplayedNote!, + ); + } + + // Navigate to the selected note Navigator.of(context).pop(); this.setState(() { _currentlyDisplayedNote = note; @@ -1027,9 +1077,7 @@ class MainPageState extends State with WindowListener { Expanded( child: TextField( controller: _previousEntryController, - readOnly: - _currentlyDisplayedNote?.date != - previousNote?.date, + readOnly: false, // Always allow editing maxLines: null, expands: true, style: Theme.of(context).textTheme.bodyMedium, @@ -1037,7 +1085,7 @@ class MainPageState extends State with WindowListener { hintText: _currentlyDisplayedNote?.date != previousNote?.date - ? 'Viewing note from ${_currentlyDisplayedNote?.date} (Read-Only)' + ? 'Viewing note from ${_currentlyDisplayedNote?.date} (Editable)' : 'Latest Note', border: const OutlineInputBorder(), filled: diff --git a/lib/notes.dart b/lib/notes.dart index 8cf9627..66fe31e 100644 --- a/lib/notes.dart +++ b/lib/notes.dart @@ -30,16 +30,26 @@ Future getLatestNote() async { } Future createNote(String content) async { - if (content.isEmpty) { + // Trim the content to avoid saving just whitespace + final trimmedContent = content.trim(); + if (trimmedContent.isEmpty) { return; } - await DB.db.insert('notes', {'content': content}); + await DB.db.insert('notes', {'content': trimmedContent}); } Future updateNote(Note note) async { + // Trim the content to avoid saving just whitespace + final trimmedContent = note.content.trim(); + if (trimmedContent.isEmpty) { + // Delete the note if content is empty + await DB.db.delete('notes', where: 'date = ?', whereArgs: [note.date]); + return; + } + await DB.db.update( 'notes', - {'content': note.content}, + {'content': trimmedContent}, where: 'date = ?', whereArgs: [note.date], ); @@ -61,7 +71,9 @@ Future getLatestScratch() async { } Future createScratch(String content) async { - await DB.db.insert('scratches', {'content': content}); + // Trim content but allow empty scratch notes (they might be intentionally cleared) + final trimmedContent = content.trim(); + await DB.db.insert('scratches', {'content': trimmedContent}); } // Get the note immediately older than the given date @@ -103,6 +115,17 @@ Future getNextNote(String currentDate) async { return getLatestNote(); } +/// Delete a note by its date +Future deleteNote(String date) async { + final result = await DB.db.delete( + 'notes', + where: 'date = ?', + whereArgs: [date], + ); + + return result > 0; // Return true if a note was deleted +} + // Search notes using full-text search Future> searchNotes(String query) async { if (query.isEmpty) {