@bobfrankston/rmfmail 1.0.693 → 1.0.695

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
@@ -1357,28 +1357,31 @@ async function spamSelectedMessages() {
1357
1357
  // sync is a background detail, the user's action should feel instant.
1358
1358
  const snapshot = [...selected];
1359
1359
  removeMessagesAndReconcile(selected);
1360
- try {
1361
- const byAccount = new Map();
1362
- for (const msg of snapshot) {
1363
- const uids = byAccount.get(msg.accountId) || [];
1364
- uids.push(msg.uid);
1365
- byAccount.set(msg.accountId, uids);
1366
- }
1367
- for (const [accountId, uids] of byAccount) {
1368
- const result = await markAsSpamMessages(accountId, uids);
1369
- console.log(`[spam] ${accountId}: moved ${result?.moved ?? uids.length} to folderId=${result?.targetFolderId}`);
1370
- }
1371
- if (statusSync)
1372
- statusSync.textContent = `Spam: ${snapshot.length} queued — pending server sync`;
1360
+ // Fire-and-forget per local-first: the optimistic remove above has
1361
+ // already updated the UI; the service-side move is sync DB + queued
1362
+ // IMAP. An IPC 120s timeout here doesn't mean the move failed — it
1363
+ // means the response is stuck behind a long-running prior op (e.g.
1364
+ // simpleParser blocking the event loop). The local commit and server
1365
+ // sync still happen. Surfacing it as a failure with an alert lies to
1366
+ // the user; the next folder reload reconciles either way.
1367
+ const byAccount = new Map();
1368
+ for (const msg of snapshot) {
1369
+ const uids = byAccount.get(msg.accountId) || [];
1370
+ uids.push(msg.uid);
1371
+ byAccount.set(msg.accountId, uids);
1373
1372
  }
1374
- catch (e) {
1375
- console.error(`[spam] failed:`, e);
1376
- if (statusSync)
1377
- statusSync.textContent = `Spam failed: ${e?.message || e}`;
1378
- alert(`Mark-as-spam failed: ${e?.message || e}\n\n${selected.length} message(s) stayed in the list; check Settings → account spam folder and accounts.jsonc.`);
1379
- // Best-effort restore: re-set the messages we optimistically removed.
1380
- // removeMessages has no inverse in message-state, so we'll rely on the
1381
- // next folder reload to repopulate. Surface the failure clearly.
1373
+ if (statusSync)
1374
+ statusSync.textContent = `Spam: ${snapshot.length} queued — pending server sync`;
1375
+ for (const [accountId, uids] of byAccount) {
1376
+ markAsSpamMessages(accountId, uids)
1377
+ .then(result => {
1378
+ console.log(`[spam] ${accountId}: moved ${result?.moved ?? uids.length} to folderId=${result?.targetFolderId}`);
1379
+ })
1380
+ .catch(e => {
1381
+ console.error(`[spam] ${accountId} failed:`, e);
1382
+ if (statusSync)
1383
+ statusSync.textContent = `Spam sync issue (${accountId}): ${e?.message || e}`;
1384
+ });
1382
1385
  }
1383
1386
  }
1384
1387
  document.getElementById("btn-spam")?.addEventListener("click", spamSelectedMessages);