@bobfrankston/rmfmail 1.1.215 → 1.1.216

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.
@@ -1814,6 +1814,33 @@ async function showMessage(accountId, uid, folderId, specialUse, isRetry = false
1814
1814
  attEl.hidden = true;
1815
1815
  if (msg.attachments?.length) {
1816
1816
  attEl.hidden = false;
1817
+ const saveAttachmentAt = async (idx) => {
1818
+ const a0 = msg.attachments[idx];
1819
+ try {
1820
+ const data = await getAttachment(accountId, uid, idx, msg.folderId);
1821
+ const bytes = Uint8Array.from(atob(data.content), (c) => c.charCodeAt(0));
1822
+ const blob = new Blob([bytes], { type: data.contentType || "application/octet-stream" });
1823
+ const url = URL.createObjectURL(blob);
1824
+ const a = document.createElement("a");
1825
+ a.href = url;
1826
+ a.download = a0.filename || "attachment";
1827
+ a.style.display = "none";
1828
+ document.body.appendChild(a);
1829
+ a.click();
1830
+ setTimeout(() => {
1831
+ a.remove();
1832
+ URL.revokeObjectURL(url);
1833
+ }, 5e3);
1834
+ } catch (err) {
1835
+ window.dispatchEvent(new CustomEvent("mailx-alert", { detail: { message: `Couldn't save "${a0.filename}": ${err?.message || err}`, key: "attachment-save" } }));
1836
+ }
1837
+ };
1838
+ const saveAllAttachments = async () => {
1839
+ for (let k = 0; k < msg.attachments.length; k++) {
1840
+ await saveAttachmentAt(k);
1841
+ await new Promise((r) => setTimeout(r, 300));
1842
+ }
1843
+ };
1817
1844
  for (let i = 0; i < msg.attachments.length; i++) {
1818
1845
  const att = msg.attachments[i];
1819
1846
  const chip = document.createElement("button");
@@ -1885,6 +1912,22 @@ async function showMessage(accountId, uid, folderId, specialUse, isRetry = false
1885
1912
  console.error(`Attachment drag-out failed: ${err.message || err}`);
1886
1913
  }
1887
1914
  });
1915
+ chip.addEventListener("contextmenu", (e) => {
1916
+ e.preventDefault();
1917
+ e.stopPropagation();
1918
+ const items = [
1919
+ { label: "Open", action: () => chip.click() },
1920
+ { label: `Save "${att.filename}"\u2026`, action: () => {
1921
+ void saveAttachmentAt(i);
1922
+ } }
1923
+ ];
1924
+ if (msg.attachments.length > 1) {
1925
+ items.push({ label: `Save all (${msg.attachments.length})\u2026`, action: () => {
1926
+ void saveAllAttachments();
1927
+ } });
1928
+ }
1929
+ showContextMenu(e.clientX, e.clientY, items);
1930
+ });
1888
1931
  attEl.appendChild(chip);
1889
1932
  }
1890
1933
  }