@bobfrankston/rmfmail 1.1.131 → 1.1.133

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/client/index.html CHANGED
@@ -768,6 +768,7 @@
768
768
  </div>
769
769
  <button class="tb-btn" id="btn-tb-delete" title="Delete selected message (Del)">🗑</button>
770
770
  <button class="tb-btn" id="btn-tb-spam" title="Mark as spam — move to the configured Junk folder">⚠</button>
771
+ <button class="tb-btn" id="btn-tb-flag" title="Flag / unflag selected message(s) — Ctrl+Z to undo">★</button>
771
772
  <span id="app-version" class="app-version"></span>
772
773
  <span class="app-version" title="Cycle pane focus: F6 = forward (folders → list → viewer), Shift+F6 = back. From the preview, ⇧F6 lands on the message-list row that drove it.">⇧F6 ← list</span>
773
774
  </div>
@@ -838,6 +839,7 @@
838
839
  <datalist id="search-history"></datalist>
839
840
  <label class="search-server-check" title="Also search the IMAP server (slower; spans all folders on all accounts)"><input type="checkbox" id="search-server-too"> Server</label>
840
841
  <label class="search-server-check" title="Include Trash + Spam in search results (off by default)"><input type="checkbox" id="search-include-trash"> Trash/Spam</label>
842
+ <button type="button" id="btn-filter-flagged" class="search-help-btn" title="Show only flagged (★) messages in the list (toggle)">★</button>
841
843
  <button type="button" id="search-help" class="search-help-btn" title="Search syntax help">?</button>
842
844
  </search>
843
845
  <div class="ml-folder-title" id="ml-folder-title"></div>
@@ -2304,10 +2304,14 @@ body.calendar-sidebar-on .calendar-sidebar { display: flex; }
2304
2304
  padding: 0;
2305
2305
  }
2306
2306
  .search-help-btn:hover { color: var(--color-text); border-color: var(--color-text); }
2307
- .search-help-btn[aria-expanded="true"] {
2307
+ .search-help-btn[aria-expanded="true"],
2308
+ .search-help-btn.active {
2308
2309
  color: var(--color-accent);
2309
2310
  border-color: var(--color-accent);
2310
2311
  }
2312
+ /* When the ★ filter is on, fill the glyph too so the pressed state reads at
2313
+ a glance — matches the flagged-row pip Bob already recognizes. */
2314
+ #btn-filter-flagged.active { background: oklch(0.97 0.05 80); }
2311
2315
 
2312
2316
  /* Non-modal help panel anchored below the search bar. No backdrop — the
2313
2317
  search input stays usable while it's open so the user can build a query
package/npmchanges.md CHANGED
@@ -366,3 +366,35 @@ feat: -send <file> CLI + general-outbox auto-routing; draft UI fixes
366
366
  single-dash is canonical, double-dash still accepted as a synonym.
367
367
  README "Command Line" section refreshed in lockstep.
368
368
 
369
+ ## v1.1.131 — 2026-05-23
370
+
371
+ fix: -repair uses node:sqlite, not better-sqlite3
372
+
373
+ better-sqlite3 is not a project dependency — the daemon uses node:sqlite
374
+ (built-in) via mailx-store. -repair was crashing with ERR_MODULE_NOT_FOUND
375
+ on first run. Swap the dynamic import to node:sqlite's DatabaseSync, and
376
+ move the WAL setting from .pragma() (better-sqlite3-specific) to
377
+ .exec("PRAGMA …") (works on both).
378
+
379
+ ## v1.1.132 — 2026-05-24
380
+
381
+ feat: multi-level undo, viewer fate-sharing, ★ filter + ★ bulk-flag
382
+
383
+ - Multi-level undo (Ctrl+Z). Replaces single-slot lastDeleted / lastMoved
384
+ with a LIFO undoStack. Each user-driven destructive action (delete,
385
+ move, bulk-flag) pushes a typed UndoOp; Ctrl+Z pops and reverses via
386
+ existing service IPC. Bounded at 50 entries, 10 min per-entry TTL,
387
+ checked at pop time. No redo (undoing an undo isn't itself undoable).
388
+ - Viewer/list fate-sharing: when loadMessages produces an empty result OR
389
+ the focused row's message isn't in the freshly-loaded set (filter
390
+ toggle, sync drop, navigation), clearViewer() runs so the preview pane
391
+ doesn't keep showing a stale message that the list says doesn't exist.
392
+ - Search-bar ★ filter button (id=btn-filter-flagged). Mirrors the
393
+ buried-in-View-menu opt-flagged checkbox so the flagged-only filter is
394
+ reachable in one click. Pressed/active state via .active CSS marker.
395
+ - Toolbar ★ bulk-flag button (id=btn-tb-flag) next to trash/spam.
396
+ Operates on the message-list selection (falls back to viewer focus when
397
+ empty). Smart toggle: if any selected row is unflagged → flag all;
398
+ if all flagged → unflag all. Pushes a single undo entry capturing each
399
+ row's prior state so Ctrl+Z restores the exact mix.
400
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/rmfmail",
3
- "version": "1.1.131",
3
+ "version": "1.1.133",
4
4
  "description": "Local-first email client with IMAP sync and standalone native app",
5
5
  "type": "module",
6
6
  "main": "bin/mailx.js",
package/.commitmsg DELETED
@@ -1,7 +0,0 @@
1
- fix: -repair uses node:sqlite, not better-sqlite3
2
-
3
- better-sqlite3 is not a project dependency — the daemon uses node:sqlite
4
- (built-in) via mailx-store. -repair was crashing with ERR_MODULE_NOT_FOUND
5
- on first run. Swap the dynamic import to node:sqlite's DatabaseSync, and
6
- move the WAL setting from .pragma() (better-sqlite3-specific) to
7
- .exec("PRAGMA …") (works on both).