@bobfrankston/rmfmail 1.0.699 → 1.0.701

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/app.js CHANGED
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { initFolderTree, refreshFolderTree, updateFolderCounts, setFolderSynced, getFolderSynced, setOutboxTotal } from "./components/folder-tree.js";
6
6
  import { initMessageList, loadMessages, loadUnifiedInbox, loadSearchResults, reloadCurrentFolder, clearSearchMode, getSelectedMessages, markBodiesCached, getCurrentFocused, releaseFocus, removeMessagesAndReconcile, setRowFlagged, scrollFocusedIntoView, refreshPriorityIndex } from "./components/message-list.js";
7
+ import { FLAG, flagOps } from "@bobfrankston/mailx-types";
7
8
  import { getCurrentMessage, initViewer, popOutCurrentMessage, toggleFullscreenPreview, showPreviewBodyMenu, wrapHtmlBody } from "./components/message-viewer.js";
8
9
  import { connectWebSocket, onWsEvent, triggerSync, syncAccount, reauthenticate, getAccounts, getFolders, deleteMessages, undeleteMessage, restartServer, getSyncPending, getVersion, getSettings, saveSettings, getAutocompleteSettings, saveAutocompleteSettings, repairAccounts, updateFlags, markAsSpamMessages, logClientEvent, sendMessage as apiSendMessage } from "./lib/api-client.js";
9
10
  import * as messageState from "./lib/message-state.js";
@@ -1324,17 +1325,17 @@ document.getElementById("btn-flag")?.addEventListener("click", async () => {
1324
1325
  const sel = getCurrentFocused();
1325
1326
  if (!sel)
1326
1327
  return;
1327
- const isFlagged = sel.flags.includes("\\Flagged");
1328
+ const isFlagged = flagOps.isFlagged(sel.flags);
1328
1329
  const newFlags = isFlagged
1329
- ? sel.flags.filter((f) => f !== "\\Flagged")
1330
- : [...sel.flags, "\\Flagged"];
1330
+ ? flagOps.remove(sel.flags, FLAG.FLAGGED)
1331
+ : flagOps.add(sel.flags, FLAG.FLAGGED);
1331
1332
  try {
1332
1333
  await updateFlags(sel.accountId, sel.uid, newFlags);
1333
1334
  sel.flags = newFlags;
1334
1335
  messageState.updateMessageFlags(sel.accountId, sel.uid, newFlags);
1335
1336
  // Row owns its own DOM \u2014 go through the row object so class + star
1336
1337
  // update atomically and the list/preview stay in sync.
1337
- setRowFlagged(sel.accountId, sel.uid, newFlags.includes("\\Flagged"));
1338
+ setRowFlagged(sel.accountId, sel.uid, flagOps.isFlagged(newFlags));
1338
1339
  }
1339
1340
  catch (e) {
1340
1341
  console.error(`Flag toggle failed: ${e.message}`);
@@ -1447,16 +1448,14 @@ document.getElementById("btn-mark-unread")?.addEventListener("click", () => {
1447
1448
  const sel = getCurrentFocused();
1448
1449
  if (!sel)
1449
1450
  return;
1450
- const isSeen = sel.flags.includes("\\Seen");
1451
- const newFlags = isSeen
1452
- ? sel.flags.filter((f) => f !== "\\Seen")
1453
- : [...sel.flags, "\\Seen"];
1451
+ const isSeen = flagOps.isSeen(sel.flags);
1452
+ const newFlags = flagOps.set(sel.flags, FLAG.SEEN, !isSeen);
1454
1453
  updateFlags(sel.accountId, sel.uid, newFlags).then(() => {
1455
1454
  sel.flags = newFlags;
1456
1455
  messageState.updateMessageFlags(sel.accountId, sel.uid, newFlags);
1457
1456
  const row = document.querySelector(`.ml-row[data-uid="${sel.uid}"][data-account-id="${sel.accountId}"]`);
1458
1457
  if (row)
1459
- row.classList.toggle("unread", !newFlags.includes("\\Seen"));
1458
+ row.classList.toggle("unread", !flagOps.isSeen(newFlags));
1460
1459
  }).catch(() => { });
1461
1460
  });
1462
1461
  document.getElementById("btn-reply")?.addEventListener("click", () => openCompose("reply"));
@@ -2845,16 +2844,14 @@ document.addEventListener("keydown", (e) => {
2845
2844
  if (!sel)
2846
2845
  return;
2847
2846
  e.preventDefault();
2848
- const isSeen = sel.flags.includes("\\Seen");
2849
- const newFlags = isSeen
2850
- ? sel.flags.filter((f) => f !== "\\Seen")
2851
- : [...sel.flags, "\\Seen"];
2847
+ const isSeen = flagOps.isSeen(sel.flags);
2848
+ const newFlags = flagOps.set(sel.flags, FLAG.SEEN, !isSeen);
2852
2849
  updateFlags(sel.accountId, sel.uid, newFlags).then(() => {
2853
2850
  sel.flags = newFlags;
2854
2851
  messageState.updateMessageFlags(sel.accountId, sel.uid, newFlags);
2855
2852
  const row = document.querySelector(`.ml-row[data-uid="${sel.uid}"][data-account-id="${sel.accountId}"]`);
2856
2853
  if (row)
2857
- row.classList.toggle("unread", !newFlags.includes("\\Seen"));
2854
+ row.classList.toggle("unread", !flagOps.isSeen(newFlags));
2858
2855
  }).catch(() => { });
2859
2856
  }
2860
2857
  // Z = locate the focused row in the list (scroll-to-selected). After
@@ -4515,7 +4512,7 @@ document.addEventListener("mailx-popout-message", (async (e) => {
4515
4512
  // currently sitting in the user's Drafts folder. The read-only popout
4516
4513
  // surface is missing every action button (Reply, Forward, Edit Draft,
4517
4514
  // …) so dumping a draft into it is a worst-case dead-end.
4518
- const isDraft = Array.isArray(msg?.flags) && msg.flags.includes("\\Draft");
4515
+ const isDraft = Array.isArray(msg?.flags) && flagOps.isDraft(msg.flags);
4519
4516
  if (isDraft) {
4520
4517
  const accts = await getAccounts();
4521
4518
  const init = {