v1.1.0: favorites, note modes, long-press, search improvements
Bump version to 1.1.0+2. New features since 1.0.x: - Three editor modes: View (read-only, syntax-highlighted), Edit, Preview - Favorites: swipe right to star a note; Show Favorites filter in menu - Long-press a note to open scrolled to end; Edit mode always places cursor at end of file - Subdirectory note creation (subdir/notename) and search (/subdir) - Tag search (#tag @context +project) with case-insensitive matching - Tag highlighting no longer falsely matches phone numbers / emails - Font size slider and Share button in editor menu - Search cache: note metadata indexed at load time, no per-keystroke file I/O - App ID changed to com.randogoth.muzzlevelocity Update Help and About texts to document all current features. Update QuickStart note for new installs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
14d6b3c44d
commit
8645c656f2
3 changed files with 140 additions and 61 deletions
|
|
@ -48,6 +48,8 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
bool _includeFileContent = false;
|
||||
bool _includeSubdirectories = true;
|
||||
Timer? _debounce;
|
||||
Set<String> _favorites = {};
|
||||
bool _showOnlyFavorites = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
@ -90,6 +92,23 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
}
|
||||
|
||||
|
||||
Future<void> _saveFavorites() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setStringList('favorites', _favorites.toList());
|
||||
}
|
||||
|
||||
void _toggleFavorite(File note) {
|
||||
setState(() {
|
||||
if (_favorites.contains(note.path)) {
|
||||
_favorites.remove(note.path);
|
||||
} else {
|
||||
_favorites.add(note.path);
|
||||
}
|
||||
});
|
||||
_saveFavorites();
|
||||
_filterNotes();
|
||||
}
|
||||
|
||||
Future<void> _toggleExternalEditor(bool value) async {
|
||||
setState(() {
|
||||
_useExternalEditor = value;
|
||||
|
|
@ -124,6 +143,7 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
defaultDir = dir.path;
|
||||
_useExternalEditor = prefs.getBool('use_external_editor') ?? false;
|
||||
_includeSubdirectories = prefs.getBool('include_subdirectories') ?? true;
|
||||
_favorites = (prefs.getStringList('favorites') ?? []).toSet();
|
||||
});
|
||||
|
||||
notesDirectoryPath = prefs.getString('notes_directory') ?? defaultDir;
|
||||
|
|
@ -149,11 +169,13 @@ class _NoteListScreenState extends State<NoteListScreen> {
|
|||
Welcome to *Muzzle Velocity*.
|
||||
This is your fast and minimal note-taking app.
|
||||
|
||||
1. ✍️ Create Notes quickly: just type a title in the search bar and press enter.
|
||||
2. 🔍 Type keywords to filter notes instantly.
|
||||
3. 💻 Type commands like :help to get more information.
|
||||
4. 🏷️ Use hashtags like #quickstart, context tags like @help, or project tags like +muzzle in your notes for categorization.
|
||||
5. 🔫 Tap the blaster at the top right for more settings or to clear the search field.
|
||||
1. ✍️ **Create** a note: type a title in the search bar and press Enter.
|
||||
2. 🔍 **Search** by title, #tag, +project, @context, or /subfolder.
|
||||
3. ⭐ **Favorite** a note: swipe it to the right.
|
||||
4. 🗑️ **Delete** a note: swipe it to the left.
|
||||
5. 📖 **View / ✏️ Edit / 👁️ Preview**: switch modes from the editor menu.
|
||||
6. 💻 **Commands**: type :help in the search bar for more information.
|
||||
7. 🔫 Tap the blaster at the top right for settings.
|
||||
|
||||
*Muzzle Velocity* is built for speed and simplicity! 🚀
|
||||
|
||||
|
|
@ -326,9 +348,7 @@ Happy note taking! ✨
|
|||
setState(() {
|
||||
if (query.isEmpty) {
|
||||
filteredNotes = List.from(notes);
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
final terms = query.split(' '); // Split search into words
|
||||
final searchTags = terms.where((t) => t.startsWith(RegExp(r'[#@+]'))).toSet();
|
||||
final searchText = terms.where((t) => !t.startsWith(RegExp(r'[#@+]'))).join(' ');
|
||||
|
|
@ -350,6 +370,13 @@ Happy note taking! ✨
|
|||
return (relativePath.contains(normalizedSearch) || content.contains(normalizedSearch)) && matchesTags;
|
||||
}
|
||||
}).toList();
|
||||
}
|
||||
|
||||
if (_showOnlyFavorites) {
|
||||
filteredNotes = filteredNotes
|
||||
.where((note) => _favorites.contains(note.path))
|
||||
.toList();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -717,6 +744,10 @@ Happy note taking! ✨
|
|||
),
|
||||
onSelected: (String value) {
|
||||
switch (value) {
|
||||
case 'Toggle Favorites':
|
||||
setState(() { _showOnlyFavorites = !_showOnlyFavorites; });
|
||||
_filterNotes();
|
||||
break;
|
||||
case 'Toggle Tags':
|
||||
widget.toggleTags();
|
||||
break;
|
||||
|
|
@ -744,6 +775,17 @@ Happy note taking! ✨
|
|||
}
|
||||
},
|
||||
itemBuilder: (BuildContext context) => [
|
||||
PopupMenuItem<String>(
|
||||
value: 'Toggle Favorites',
|
||||
child: ListTile(
|
||||
leading: Icon(
|
||||
_showOnlyFavorites ? Icons.star : Icons.star_outline,
|
||||
color: _showOnlyFavorites ? Colors.amber : null,
|
||||
),
|
||||
title: Text(_showOnlyFavorites ? 'Show All Notes' : 'Show Favorites'),
|
||||
),
|
||||
),
|
||||
PopupMenuDivider(),
|
||||
PopupMenuItem<String>(
|
||||
value: 'Toggle Tags',
|
||||
child: ListTile(
|
||||
|
|
@ -869,16 +911,35 @@ Happy note taking! ✨
|
|||
final noteFile = filteredNotes[index];
|
||||
return Dismissible(
|
||||
key: Key(noteFile.path),
|
||||
direction: DismissDirection.endToStart,
|
||||
direction: DismissDirection.horizontal,
|
||||
background: Container(
|
||||
color: Colors.amber,
|
||||
alignment: Alignment.centerLeft,
|
||||
padding: EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Icon(
|
||||
_favorites.contains(noteFile.path) ? Icons.star_outline : Icons.star,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
secondaryBackground: Container(
|
||||
color: Colors.redAccent,
|
||||
alignment: Alignment.centerRight,
|
||||
padding: EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Icon(Icons.delete, color: Colors.white),
|
||||
),
|
||||
confirmDismiss: (direction) async {
|
||||
if (direction == DismissDirection.startToEnd) {
|
||||
_toggleFavorite(noteFile);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
onDismissed: (direction) => _deleteNote(noteFile),
|
||||
child: ListTile(
|
||||
title: Text(noteFile.uri.pathSegments.last.replaceAll('.md', '')),
|
||||
trailing: _favorites.contains(noteFile.path)
|
||||
? Icon(Icons.star, color: Colors.amber, size: 18)
|
||||
: null,
|
||||
subtitle: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final bool hasEnoughSpace = constraints.maxWidth > 200; // Adjust threshold
|
||||
|
|
|
|||
80
lib/texts.dart
Normal file → Executable file
80
lib/texts.dart
Normal file → Executable file
|
|
@ -3,63 +3,82 @@ String helpContent = """
|
|||
|
||||
Type to filter notes by title.
|
||||
Use #tags, +projects, or @contexts to find notes with specific tags.
|
||||
Start with a / to filter notes within /subdirectories.
|
||||
Mix text, tags, and folders (/work project #important).
|
||||
Start with a / to filter notes within /folders and /sub/folders.
|
||||
Mix text, tags, and folders freely (/work project #important).
|
||||
|
||||
# Create Notes
|
||||
|
||||
Type the title of a new note in the search bar and hit Enter.
|
||||
Use /folder/note title to create a note inside a subdirectory.
|
||||
Subfolders will be automatically created if they don’t exist.
|
||||
Use /folder/note to create a note inside a subdirectory.
|
||||
Subfolders are automatically created if they don't exist.
|
||||
|
||||
# Delete Notes
|
||||
# Open Notes
|
||||
|
||||
Swipe a note in the list to the left to move it to the trash.
|
||||
The trash is a directory in the root folder.
|
||||
Use :emptytrash or the context menu button to permanently clear deleted notes.
|
||||
**Tap** a note to open it in View mode (syntax-highlighted, read-only).
|
||||
**Long-press** a note to open it scrolled to the end of the file.
|
||||
Switch between View, Edit, and Preview modes from the editor menu.
|
||||
|
||||
# Edit Notes
|
||||
|
||||
Enable/disable autosave in the menu. When disabled you can use the Save button in the menu.
|
||||
If there are unsaved changes when you are leaving the editor, you will be prompted to save.
|
||||
Switch to Edit mode from the editor menu. The cursor is placed at the end.
|
||||
Enable/disable Autosave in the editor menu.
|
||||
When Autosave is off, use the Save button — or you will be prompted on exit.
|
||||
Adjust the font size with the slider in the editor menu.
|
||||
Share a note as plain text from the editor menu.
|
||||
|
||||
# Favorites
|
||||
|
||||
Swipe a note to the **right** to mark it as a favorite (gold star).
|
||||
Swipe right again to remove it from favorites.
|
||||
Use *Show Favorites* in the menu to filter the list to starred notes only.
|
||||
|
||||
# Delete Notes
|
||||
|
||||
Swipe a note to the **left** to move it to the trash.
|
||||
The trash is a directory in the root notes folder.
|
||||
Use :emptytrash or the context menu to permanently clear deleted notes.
|
||||
|
||||
# Tag Notes
|
||||
|
||||
Use tags anywhere in the notes and they will be detected.
|
||||
Use tags anywhere in note content — they are detected automatically.
|
||||
|
||||
#tags – General categorization.
|
||||
+projects – Project-based grouping.
|
||||
@contexts – Context-specific notes.
|
||||
|
||||
Tags must start with a letter and be preceded by a space or line break.
|
||||
|
||||
# Context Menu
|
||||
|
||||
Tap the orange blaster at the top right to open the Preferences.
|
||||
Tap the orange blaster at the top right to open the preferences menu.
|
||||
|
||||
Here you find toggles to show/hide the tags below the note titles and switch between light and dark themes.
|
||||
|
||||
You can also exclude subdirectories from your search.
|
||||
|
||||
By default the search bar filters by note titles, folders, and tags, but you can also toggle including the file contents. Please be aware that this might slow down the app if you have many files.
|
||||
|
||||
If you prefer to use a different Markdown editor for your files you can toggle that and when you tap a file in the list you can choose what to open the file with.
|
||||
|
||||
By default the notes are saved in the App's own directory which is inaccessible to other apps. If you want to choose your own custom folder for this, you can set it. You will be asked for special permissions to do so. This will enable you to save the notes wherever you want, for example to sync them with a different app. You can also choose a folder that already has notes in it.
|
||||
- *Show Favorites / Show All Notes* – Filter the list to starred notes.
|
||||
- *Hide/Show Tags* – Show tag chips below note titles in the list.
|
||||
- *Switch to Light/Dark Mode* – Toggle themes.
|
||||
- *Exclude/Search Subdirectories* – Control the depth of your search.
|
||||
- *Search/Exclude File Content* – Also search inside note content (may slow down the app with many files).
|
||||
- *Use External/Internal Editor* – Open notes in your preferred editor app.
|
||||
- *Set Notes Directory* – Choose a folder anywhere on the device.
|
||||
- *Empty Trash* – Permanently delete all trashed notes.
|
||||
- *Help* – Show this guide.
|
||||
- *About* – App credits and version.
|
||||
|
||||
# File Organization
|
||||
|
||||
Root notes are listed above subfolder notes.
|
||||
Subfolders are ordered by the latest modified file inside them.
|
||||
Empty folders auto-delete after the last file is removed.
|
||||
Empty folders are automatically removed after the last file is deleted.
|
||||
|
||||
# Commands
|
||||
|
||||
Use commands by starting with a colon :
|
||||
Type a colon command in the search bar and press Enter:
|
||||
|
||||
:help – Open this guide.
|
||||
:tags – Toggle tag visibility.
|
||||
:day - Switch to light theme.
|
||||
:night - Switch to dark theme.
|
||||
:extern – Toggle external editor usage.
|
||||
:intern – Toggle internal editor usage.
|
||||
:day – Switch to light theme.
|
||||
:night – Switch to dark theme.
|
||||
:extern – Toggle external editor.
|
||||
:intern – Toggle internal editor.
|
||||
:emptytrash – Permanently delete trashed notes.
|
||||
:about – Open app information.
|
||||
|
||||
|
|
@ -67,12 +86,11 @@ Use commands by starting with a colon :
|
|||
""";
|
||||
|
||||
String aboutContent = """
|
||||
**Muzzle Velocity** is a fast and minimalist note-taking app inspired by *Notational Velocity* and *Terminal Velocity*.
|
||||
v.1.1.0
|
||||
|
||||
**Muzzle Velocity** is a fast and minimalist but opinionated note-taking app inspired by the legendary *Notational Velocity* on MacOS and *Terminal Velocity* for command line terminals.
|
||||
|
||||
It is built for speed and efficiency, eliminating unnecessary UI clutter. Every action should be as fast and frictionless as possible.
|
||||
|
||||
Made with 🧡 by randogoth
|
||||
|
||||
with the invaluable help of
|
||||
OpenAI's 🤖 ChatGPT
|
||||
""";
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
name: muzzle_velocity
|
||||
description: "A new Flutter project."
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
version: 1.0.0+1
|
||||
version: 1.1.0+2
|
||||
|
||||
environment:
|
||||
sdk: ^3.6.0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue