@bobfrankston/rmfmail 1.2.210 → 1.2.213

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.
Files changed (36) hide show
  1. package/client/android-bootstrap.bundle.js +7 -1
  2. package/client/android-bootstrap.bundle.js.map +2 -2
  3. package/client/app.bundle.js +41 -9
  4. package/client/app.bundle.js.map +2 -2
  5. package/client/app.js +57 -13
  6. package/client/app.js.map +1 -1
  7. package/client/app.ts +52 -13
  8. package/client/components/folder-tree.js +45 -3
  9. package/client/components/folder-tree.js.map +1 -1
  10. package/client/components/folder-tree.ts +42 -3
  11. package/client/index.html +1 -1
  12. package/client/package.json +1 -1
  13. package/package.json +5 -5
  14. package/packages/mailx-imap/package-lock.json +2 -2
  15. package/packages/mailx-imap/package.json +1 -1
  16. package/packages/mailx-service/index.d.ts +6 -0
  17. package/packages/mailx-service/index.d.ts.map +1 -1
  18. package/packages/mailx-service/index.js +8 -0
  19. package/packages/mailx-service/index.js.map +1 -1
  20. package/packages/mailx-service/index.ts +9 -0
  21. package/packages/mailx-service/jsonrpc.js +1 -1
  22. package/packages/mailx-service/jsonrpc.js.map +1 -1
  23. package/packages/mailx-service/jsonrpc.ts +1 -1
  24. package/packages/mailx-service/package.json +1 -1
  25. package/packages/mailx-store/db.d.ts +27 -0
  26. package/packages/mailx-store/db.d.ts.map +1 -1
  27. package/packages/mailx-store/db.js +81 -1
  28. package/packages/mailx-store/db.js.map +1 -1
  29. package/packages/mailx-store/db.ts +78 -1
  30. package/packages/mailx-store/package.json +1 -1
  31. package/packages/mailx-store-web/android-bootstrap.d.ts.map +1 -1
  32. package/packages/mailx-store-web/android-bootstrap.js +14 -1
  33. package/packages/mailx-store-web/android-bootstrap.js.map +1 -1
  34. package/packages/mailx-store-web/android-bootstrap.ts +14 -1
  35. package/packages/mailx-store-web/package.json +1 -1
  36. /package/packages/mailx-imap/{node_modules.npmglobalize-stash-14572 → node_modules.npmglobalize-stash-38948}/.package-lock.json +0 -0
package/client/app.js CHANGED
@@ -338,9 +338,16 @@ const alertText = document.getElementById("alert-text");
338
338
  const alertDismiss = document.getElementById("alert-dismiss");
339
339
  const dismissedAlerts = new Set();
340
340
  let alertAutoDismissTimer = null;
341
+ /** Latched once the daemon reports a read-only DB handle. Every other error
342
+ * that follows is a SYMPTOM of it (each account's "attempt to write a
343
+ * readonly database", every failed flag/move), and letting those overwrite
344
+ * the banner buries the one message that names the actual problem. */
345
+ let dbReadOnlyLatched = false;
341
346
  function showAlert(message, key, opts) {
342
347
  if (key && dismissedAlerts.has(key))
343
348
  return;
349
+ if (dbReadOnlyLatched && key !== "db-readonly")
350
+ return;
344
351
  if (alertBanner && alertText) {
345
352
  alertText.textContent = message;
346
353
  alertBanner.hidden = false;
@@ -389,20 +396,14 @@ function hideAlert(opts) {
389
396
  }
390
397
  }
391
398
  alertDismiss?.addEventListener("click", () => hideAlert({ force: true }));
392
- /** Show the alert banner with a "Restart" button wired to the mailxapi
393
- * restartDaemon action. Used when a watched config file whose changes
394
- * don't apply live (accounts.jsonc) has been modified. */
395
- function showRestartForConfigBanner() {
399
+ /** Append a "Restart now" button to the alert banner, wired to the mailxapi
400
+ * restartDaemon action. Shared by every banner whose only cure is a fresh
401
+ * daemon (accounts.jsonc changed, read-only DB handle). No-op if one is
402
+ * already there. */
403
+ function addRestartButton() {
396
404
  if (!alertBanner || !alertText)
397
405
  return;
398
- // Timestamp in the banner so repeated / spurious fires are visually
399
- // distinguishable (and the user can see when the change actually
400
- // happened, useful for debugging false triggers).
401
- const ts = new Date().toLocaleTimeString([], { hour12: false });
402
- alertText.textContent = `[${ts}] accounts.jsonc changed — restart to apply.`;
403
- alertBanner.hidden = false;
404
- alertBanner.dataset.key = "config-restart";
405
- // Avoid duplicate buttons across repeat changes.
406
+ // Avoid duplicate buttons across repeat fires.
406
407
  const existing = alertBanner.querySelector("#alert-restart-btn");
407
408
  if (existing)
408
409
  return;
@@ -435,6 +436,21 @@ function showRestartForConfigBanner() {
435
436
  });
436
437
  alertText.after(btn);
437
438
  }
439
+ /** Show the alert banner with a "Restart" button wired to the mailxapi
440
+ * restartDaemon action. Used when a watched config file whose changes
441
+ * don't apply live (accounts.jsonc) has been modified. */
442
+ function showRestartForConfigBanner() {
443
+ if (!alertBanner || !alertText)
444
+ return;
445
+ // Timestamp in the banner so repeated / spurious fires are visually
446
+ // distinguishable (and the user can see when the change actually
447
+ // happened, useful for debugging false triggers).
448
+ const ts = new Date().toLocaleTimeString([], { hour12: false });
449
+ alertText.textContent = `[${ts}] accounts.jsonc changed — restart to apply.`;
450
+ alertBanner.hidden = false;
451
+ alertBanner.dataset.key = "config-restart";
452
+ addRestartButton();
453
+ }
438
454
  // ── Wire up components ──
439
455
  const folderTree = document.getElementById("folder-tree");
440
456
  let currentFolderSpecialUse = "";
@@ -3310,6 +3326,21 @@ onWsEvent((event) => {
3310
3326
  const slot = document.querySelector(".folder-loading");
3311
3327
  if (slot)
3312
3328
  slot.textContent = msg;
3329
+ // The message-list pane too — on a phone the folder tree is
3330
+ // off-canvas and the viewer pane is behind the list, so the
3331
+ // tree/viewer slots above are both invisible at boot. This is
3332
+ // the pane the user is actually staring at (Bob 2026-08-01:
3333
+ // "blank screen and 'syncing' at the bottom"). `.ml-empty`
3334
+ // exists only while the list has no rows, so live message
3335
+ // rows are never overwritten.
3336
+ const mlEmpty = document.querySelector("#ml-body .ml-empty");
3337
+ if (mlEmpty)
3338
+ mlEmpty.textContent = msg;
3339
+ // Zero-account welcome pane (the visible one on a phone until
3340
+ // accounts land) — folder-tree.ts renders this slot.
3341
+ const narrationSlot = document.getElementById("bootstrap-narration");
3342
+ if (narrationSlot)
3343
+ narrationSlot.textContent = msg;
3313
3344
  }
3314
3345
  break;
3315
3346
  }
@@ -6141,7 +6172,20 @@ versionPromise.then((d) => {
6141
6172
  if (tip)
6142
6173
  el.title = tip;
6143
6174
  }
6144
- if (d.settingsError) {
6175
+ if (d.dbWriteDenied) {
6176
+ // The daemon's SQLite handle came up read-only (OS refused read-write
6177
+ // at open; SQLite downgrades silently). Reads all work, so the app
6178
+ // LOOKS fine — but nothing is ever saved: ★ does nothing, moves snap
6179
+ // back, no new mail lands. Say so once, stickily, with the one action
6180
+ // that fixes it, instead of letting it dribble out as a per-account
6181
+ // "attempt to write a readonly database" banner (Bob 2026-08-02).
6182
+ if (alertBanner)
6183
+ alertBanner.style.background = "oklch(0.45 0.18 25)";
6184
+ dbReadOnlyLatched = true;
6185
+ showAlert("Database is READ-ONLY — nothing you do is being saved (★, moves, new mail). Restart rmfmail.", "db-readonly", { sticky: true });
6186
+ addRestartButton();
6187
+ }
6188
+ else if (d.settingsError) {
6145
6189
  showAlert(d.settingsError, "settings-error");
6146
6190
  // Add repair button to the banner
6147
6191
  const banner = document.getElementById("alert-banner");