@bobfrankston/rmfmail 1.2.312 → 1.2.313

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.
@@ -1516,24 +1516,37 @@ export async function showMessage(accountId, uid, folderId, specialUse, isRetry
1516
1516
  // Offered from the chip's own advice, which is the only
1517
1517
  // thing an unflagged list post shows; the banner has its
1518
1518
  // own button.
1519
+ //
1520
+ // Offered on every proved post, trusted or not: the write
1521
+ // is a toggle, and once the list is trusted the chip and
1522
+ // banner are gone, so this menu is the only place an
1523
+ // approval can be undone without editing allowlist.jsonc
1524
+ // by hand (Bob 2026-09-09: "how would I undo an approval").
1519
1525
  const listSpam = msg.spamScore;
1520
- if (listSpam?.listProved && listSpam.listId && !listSpam.listTrusted) {
1526
+ if (listSpam?.listProved && listSpam.listId) {
1521
1527
  const listId = listSpam.listId;
1528
+ const untrust = !!listSpam.listTrusted;
1522
1529
  items.push({
1523
- label: `✓ Trust the ${listId} mailing list`,
1530
+ label: untrust ? `✗ Stop trusting the ${listId} mailing list` : `✓ Trust the ${listId} mailing list`,
1524
1531
  action: async () => {
1525
1532
  const st = document.getElementById("status-sync");
1526
1533
  try {
1527
- // The action only ever ADDS, so anything but
1528
- // `trusted: true` means the write did not land.
1534
+ // A toggle: the answer says which way it went,
1535
+ // and it must match what was asked for — a
1536
+ // mismatch means the write did not land.
1529
1537
  const res = await trustSenderOrDomain("list", listId);
1530
- if (!res?.trusted)
1538
+ if (!res || !!res.trusted === untrust)
1531
1539
  throw new Error("the list did not save");
1532
- listSpam.listTrusted = true;
1533
- document.querySelector(".mv-spamscore")?.remove();
1534
- document.querySelector(".mv-trust")?.remove();
1540
+ listSpam.listTrusted = res.trusted;
1541
+ if (res.trusted) {
1542
+ document.querySelector(".mv-spamscore")?.remove();
1543
+ document.querySelector(".mv-spamscore-action")?.remove();
1544
+ document.querySelector(".mv-trust")?.remove();
1545
+ }
1535
1546
  if (st)
1536
- st.textContent = `Trusting the ${listId} mailing list`;
1547
+ st.textContent = res.trusted
1548
+ ? `Trusting the ${listId} mailing list`
1549
+ : `No longer trusting the ${listId} mailing list — reopen the message to see its score again`;
1537
1550
  }
1538
1551
  catch (e) {
1539
1552
  // The reader chose an action and must know whether it took.
@@ -1910,6 +1923,39 @@ export async function showMessage(accountId, uid, folderId, specialUse, isRetry
1910
1923
  : "");
1911
1924
  chip.textContent = `spam score ${spam.score} of ${spam.threshold}`;
1912
1925
  bodyEl.appendChild(chip);
1926
+ // The action beside the warning it answers (Bob 2026-09-09: "it
1927
+ // would be nice to have an [approve this list] on the red warning
1928
+ // banner"). An unflagged list post has no banner — the chip IS
1929
+ // the warning — so the button sits next to it. Same write as the
1930
+ // From-menu item and the banner button: trustedLists by List-Id.
1931
+ if (spam.listProved && spam.listId && !spam.listTrusted) {
1932
+ const listId = spam.listId;
1933
+ const b = document.createElement("button");
1934
+ b.className = "mv-trust-action mv-spamscore-action";
1935
+ b.textContent = `Trust the ${listId} list`;
1936
+ b.title = `Delivered by the ${listId} mailing list, which your server proved sent it. Trusting the list hides this score on every post the list delivers.`;
1937
+ b.addEventListener("click", async () => {
1938
+ b.disabled = true;
1939
+ try {
1940
+ // Only ever ADDS, so anything but `trusted: true` means
1941
+ // the write did not land — never hide the chip on a
1942
+ // failed save.
1943
+ const res = await trustSenderOrDomain("list", listId);
1944
+ if (!res?.trusted)
1945
+ throw new Error("the list did not save");
1946
+ spam.listTrusted = true;
1947
+ chip.remove();
1948
+ b.remove();
1949
+ document.querySelector(".mv-trust")?.remove();
1950
+ }
1951
+ catch (e) {
1952
+ // The reader pressed a button and must know whether it took.
1953
+ b.disabled = false;
1954
+ b.textContent = `Could not save: ${e?.message || e}`;
1955
+ }
1956
+ });
1957
+ bodyEl.appendChild(b);
1958
+ }
1913
1959
  }
1914
1960
  const trust = (msg.trust || []);
1915
1961
  if (trust.length) {