@bobfrankston/rmfmail 1.2.175 → 1.2.178

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 (57) hide show
  1. package/TODO.md +2 -2
  2. package/client/android-bootstrap.bundle.js +112 -0
  3. package/client/android-bootstrap.bundle.js.map +3 -3
  4. package/client/app.bundle.js +79 -16
  5. package/client/app.bundle.js.map +3 -3
  6. package/client/components/alarms.js +107 -20
  7. package/client/components/alarms.js.map +1 -1
  8. package/client/components/alarms.ts +104 -20
  9. package/client/compose/compose.bundle.js +4 -0
  10. package/client/compose/compose.bundle.js.map +2 -2
  11. package/client/lib/api-client.js +6 -0
  12. package/client/lib/api-client.js.map +1 -1
  13. package/client/lib/api-client.ts +9 -0
  14. package/client/lib/mailxapi.js +27 -5
  15. package/package.json +7 -7
  16. package/packages/mailx-imap/package-lock.json +2 -2
  17. package/packages/mailx-imap/package.json +1 -1
  18. package/packages/mailx-service/index.d.ts +5 -0
  19. package/packages/mailx-service/index.d.ts.map +1 -1
  20. package/packages/mailx-service/index.js +22 -1
  21. package/packages/mailx-service/index.js.map +1 -1
  22. package/packages/mailx-service/index.ts +25 -1
  23. package/packages/mailx-service/jsonrpc.js +4 -0
  24. package/packages/mailx-service/jsonrpc.js.map +1 -1
  25. package/packages/mailx-service/jsonrpc.ts +4 -0
  26. package/packages/mailx-service/package.json +1 -1
  27. package/packages/mailx-settings/index.d.ts +8 -1
  28. package/packages/mailx-settings/index.d.ts.map +1 -1
  29. package/packages/mailx-settings/index.js +71 -0
  30. package/packages/mailx-settings/index.js.map +1 -1
  31. package/packages/mailx-settings/index.ts +61 -1
  32. package/packages/mailx-settings/package.json +1 -1
  33. package/packages/mailx-store/package.json +1 -1
  34. package/packages/mailx-store-web/android-bootstrap.js +4 -0
  35. package/packages/mailx-store-web/android-bootstrap.js.map +1 -1
  36. package/packages/mailx-store-web/android-bootstrap.ts +4 -0
  37. package/packages/mailx-store-web/package.json +1 -1
  38. package/packages/mailx-store-web/web-service.d.ts +4 -0
  39. package/packages/mailx-store-web/web-service.d.ts.map +1 -1
  40. package/packages/mailx-store-web/web-service.js +48 -2
  41. package/packages/mailx-store-web/web-service.js.map +1 -1
  42. package/packages/mailx-store-web/web-service.ts +41 -2
  43. package/packages/mailx-types/index.d.ts +2 -0
  44. package/packages/mailx-types/index.d.ts.map +1 -1
  45. package/packages/mailx-types/index.js +3 -0
  46. package/packages/mailx-types/index.js.map +1 -1
  47. package/packages/mailx-types/index.ts +7 -0
  48. package/packages/mailx-types/mailx-api.d.ts +14 -0
  49. package/packages/mailx-types/mailx-api.d.ts.map +1 -1
  50. package/packages/mailx-types/mailx-api.ts +5 -0
  51. package/packages/mailx-types/package.json +1 -1
  52. package/packages/mailx-types/reminder-state.d.ts +42 -0
  53. package/packages/mailx-types/reminder-state.d.ts.map +1 -0
  54. package/packages/mailx-types/reminder-state.js +85 -0
  55. package/packages/mailx-types/reminder-state.js.map +1 -0
  56. package/packages/mailx-types/reminder-state.ts +88 -0
  57. /package/packages/mailx-imap/{node_modules.npmglobalize-stash-33656 → node_modules.npmglobalize-stash-7544}/.package-lock.json +0 -0
@@ -83,6 +83,7 @@ __export(api_client_exports, {
83
83
  logClientEvent: () => logClientEvent,
84
84
  markAsSpamMessages: () => markAsSpamMessages,
85
85
  markFolderRead: () => markFolderRead,
86
+ mergeReminderState: () => mergeReminderState,
86
87
  moveFolderToTrash: () => moveFolderToTrash,
87
88
  moveMessage: () => moveMessage,
88
89
  moveMessages: () => moveMessages,
@@ -616,6 +617,9 @@ function closeWordEdit(editId) {
616
617
  function showReminderPopup(opts) {
617
618
  return ipc().showReminderPopup?.(opts) ?? Promise.resolve({ button: "", reason: "no host" });
618
619
  }
620
+ function mergeReminderState(patch) {
621
+ return ipc().mergeReminderState?.(patch) ?? Promise.resolve(null);
622
+ }
619
623
  function consumePendingMailto() {
620
624
  return ipc().consumePendingMailto?.() ?? Promise.resolve(null);
621
625
  }
@@ -942,6 +946,16 @@ var init_groups = __esm({
942
946
  }
943
947
  });
944
948
 
949
+ // packages/mailx-types/reminder-state.js
950
+ var DISMISSED_RETENTION_MS, SNOOZED_RETENTION_MS;
951
+ var init_reminder_state = __esm({
952
+ "packages/mailx-types/reminder-state.js"() {
953
+ "use strict";
954
+ DISMISSED_RETENTION_MS = 30 * 864e5;
955
+ SNOOZED_RETENTION_MS = 7 * 864e5;
956
+ }
957
+ });
958
+
945
959
  // packages/mailx-types/index.js
946
960
  function _has(msg, flag) {
947
961
  return !!msg.flags && msg.flags.includes(flag);
@@ -960,6 +974,7 @@ var init_mailx_types = __esm({
960
974
  init_contact_rules();
961
975
  init_contacts_config();
962
976
  init_groups();
977
+ init_reminder_state();
963
978
  _SEEN = "\\Seen";
964
979
  _FLAGGED = "\\Flagged";
965
980
  _DRAFT = "\\Draft";
@@ -6089,6 +6104,48 @@ function pruneState(now) {
6089
6104
  }
6090
6105
  if (changed)
6091
6106
  saveSnoozed(snoozed);
6107
+ const dismissed = loadDismissed();
6108
+ let dChanged = false;
6109
+ for (const [uuid, at] of Object.entries(dismissed)) {
6110
+ if (typeof at === "number" && at < now - 30 * 864e5) {
6111
+ delete dismissed[uuid];
6112
+ dChanged = true;
6113
+ }
6114
+ }
6115
+ if (dChanged)
6116
+ saveDismissed(dismissed);
6117
+ }
6118
+ async function syncReminderState(force = false) {
6119
+ const now = Date.now();
6120
+ if (!force && now - _lastStateSync < STATE_SYNC_MIN_MS)
6121
+ return false;
6122
+ _lastStateSync = now;
6123
+ try {
6124
+ const merged = await mergeReminderState({
6125
+ dismissed: loadDismissed(),
6126
+ // `true` legacy values are normalized service-side
6127
+ snoozed: loadSnoozed()
6128
+ });
6129
+ if (!merged)
6130
+ return false;
6131
+ const dm = loadDismissed();
6132
+ for (const [k, v] of Object.entries(merged.dismissed)) {
6133
+ const cur = dm[k];
6134
+ if (cur === void 0 || cur === true || v > cur)
6135
+ dm[k] = v;
6136
+ }
6137
+ saveDismissed(dm);
6138
+ const sn = loadSnoozed();
6139
+ for (const [k, v] of Object.entries(merged.snoozed)) {
6140
+ if (!sn[k] || v > sn[k])
6141
+ sn[k] = v;
6142
+ }
6143
+ saveSnoozed(sn);
6144
+ return true;
6145
+ } catch (e) {
6146
+ alog("state sync failed", { err: e?.message || String(e) });
6147
+ return false;
6148
+ }
6092
6149
  }
6093
6150
  function occKey(uuid, ms) {
6094
6151
  return `${uuid}:${ms}`;
@@ -6141,7 +6198,7 @@ async function collectDueAlarms(now) {
6141
6198
  continue;
6142
6199
  const k = `${occBaseKey}@${offsetMs}`;
6143
6200
  if (!dismissed[k]) {
6144
- dismissed[k] = true;
6201
+ dismissed[k] = Date.now();
6145
6202
  touched = true;
6146
6203
  }
6147
6204
  }
@@ -6231,9 +6288,8 @@ async function firePopupForItem(item) {
6231
6288
  if (openPopups.has(item.uuid))
6232
6289
  return;
6233
6290
  openPopups.add(item.uuid);
6234
- const buttons = ["snooze", "Dismiss"];
6235
- if (item.htmlLink)
6236
- buttons.push("Open");
6291
+ const openUrl = item.kind === "calendar" ? item.htmlLink || "https://calendar.google.com/" : "https://tasks.google.com/";
6292
+ const buttons = ["snooze", "Dismiss", "Open"];
6237
6293
  if (item.kind === "calendar")
6238
6294
  buttons.push("Delete");
6239
6295
  const icon = item.kind === "calendar" ? "\u{1F4C5}" : "\u2611";
@@ -6247,9 +6303,7 @@ async function firePopupForItem(item) {
6247
6303
  { label: "1d", minutes: 60 * 24 }
6248
6304
  ];
6249
6305
  const presetChips = presets.map((p) => `<button type="button" class="chip" data-snooze-min="${p.minutes}">${p.label}</button>`).join("");
6250
- const actionBtns = ["Dismiss"];
6251
- if (item.htmlLink)
6252
- actionBtns.push("Open");
6306
+ const actionBtns = ["Dismiss", "Open"];
6253
6307
  if (item.kind === "calendar")
6254
6308
  actionBtns.push("Delete");
6255
6309
  const actionHtml = actionBtns.map((b) => `<button type="button" class="action" data-btn="${escapeHtml6(b)}">${escapeHtml6(b)}</button>`).join("");
@@ -6361,12 +6415,14 @@ async function firePopupForItem(item) {
6361
6415
  }
6362
6416
  const api = window.mailxapi;
6363
6417
  const openLink = () => {
6364
- if (!item.htmlLink)
6418
+ if (item.kind === "calendar" && item.htmlLink && api?.openCalendarEvent) {
6419
+ api.openCalendarEvent(item.htmlLink);
6365
6420
  return;
6421
+ }
6366
6422
  if (api?.openExternal)
6367
- api.openExternal(item.htmlLink);
6423
+ api.openExternal(openUrl);
6368
6424
  else
6369
- window.open(item.htmlLink, "_blank");
6425
+ window.open(openUrl, "_blank");
6370
6426
  };
6371
6427
  try {
6372
6428
  switch (r.button) {
@@ -6408,7 +6464,7 @@ async function firePopupForItem(item) {
6408
6464
  case "closed":
6409
6465
  {
6410
6466
  const m = loadDismissed();
6411
- m[item.uuid] = true;
6467
+ m[item.uuid] = Date.now();
6412
6468
  saveDismissed(m);
6413
6469
  alog("dismiss saved", { key: item.uuid, via: r.button });
6414
6470
  }
@@ -6416,7 +6472,7 @@ async function firePopupForItem(item) {
6416
6472
  case "Delete":
6417
6473
  {
6418
6474
  const m = loadDismissed();
6419
- m[item.uuid] = true;
6475
+ m[item.uuid] = Date.now();
6420
6476
  saveDismissed(m);
6421
6477
  }
6422
6478
  firedThisSession.delete(item.uuid);
@@ -6426,7 +6482,7 @@ async function firePopupForItem(item) {
6426
6482
  alog("unknown popup result", { button: r.button, form: r.form });
6427
6483
  {
6428
6484
  const m = loadDismissed();
6429
- m[item.uuid] = true;
6485
+ m[item.uuid] = Date.now();
6430
6486
  saveDismissed(m);
6431
6487
  }
6432
6488
  break;
@@ -6435,11 +6491,12 @@ async function firePopupForItem(item) {
6435
6491
  alog("action handler threw \u2014 forcing Dismiss", { key: item.uuid, err: e?.message || String(e) });
6436
6492
  try {
6437
6493
  const m = loadDismissed();
6438
- m[item.uuid] = true;
6494
+ m[item.uuid] = Date.now();
6439
6495
  saveDismissed(m);
6440
6496
  } catch {
6441
6497
  }
6442
6498
  }
6499
+ void syncReminderState(true);
6443
6500
  }
6444
6501
  function snoozeItem(item, minutes) {
6445
6502
  const now = Date.now();
@@ -6454,7 +6511,10 @@ async function pollAlarms() {
6454
6511
  return;
6455
6512
  const now = Date.now();
6456
6513
  pruneState(now);
6457
- const due = await collectDueAlarms(now);
6514
+ let due = await collectDueAlarms(now);
6515
+ if (due.length > 0 && await syncReminderState()) {
6516
+ due = await collectDueAlarms(now);
6517
+ }
6458
6518
  const fresh = due.filter((d) => !firedThisSession.has(d.uuid) && !openPopups.has(d.uuid));
6459
6519
  if (fresh.length === 0)
6460
6520
  return;
@@ -6468,6 +6528,7 @@ function startAlarmPoller() {
6468
6528
  if (window.__mailxAlarmPollerRunning)
6469
6529
  return;
6470
6530
  window.__mailxAlarmPollerRunning = true;
6531
+ void syncReminderState(true);
6471
6532
  setTimeout(() => {
6472
6533
  pollAlarms().catch(() => {
6473
6534
  });
@@ -6482,7 +6543,7 @@ function startAlarmPoller() {
6482
6543
  });
6483
6544
  });
6484
6545
  }
6485
- var DISMISSED_KEY, SNOOZED_KEY, LOOKBACK_MS, LOOKAHEAD_MS, POLL_INTERVAL_MS, _soundCache, _lastSoundAt, firedThisSession, openPopups;
6546
+ var DISMISSED_KEY, SNOOZED_KEY, LOOKBACK_MS, LOOKAHEAD_MS, POLL_INTERVAL_MS, _soundCache, _lastSoundAt, _lastStateSync, STATE_SYNC_MIN_MS, firedThisSession, openPopups;
6486
6547
  var init_alarms = __esm({
6487
6548
  "client/components/alarms.js"() {
6488
6549
  "use strict";
@@ -6494,6 +6555,8 @@ var init_alarms = __esm({
6494
6555
  POLL_INTERVAL_MS = 3e4;
6495
6556
  _soundCache = null;
6496
6557
  _lastSoundAt = 0;
6558
+ _lastStateSync = 0;
6559
+ STATE_SYNC_MIN_MS = 6e4;
6497
6560
  firedThisSession = /* @__PURE__ */ new Set();
6498
6561
  openPopups = /* @__PURE__ */ new Set();
6499
6562
  }