1 parent
2ac1566eca
commit
1bb398acd1
32 files changed
+907
-136
No files matched your search
@@ -214,8 +214,9 @@ function renderComposeAttachments() {
|
||||
box.replaceChildren();
|
||||
const attachments = mergeComposeAttachments(state.composeAttachments);
|
||||
state.composeAttachments = attachments;
|
||||
box.classList.toggle("hidden", !attachments.length);
|
||||
for (const attachment of attachments) {
|
||||
const visibleAttachments = attachments.filter((attachment) => !state.signatureAttachmentIds.has(String(attachment.id || "")));
|
||||
box.classList.toggle("hidden", !visibleAttachments.length);
|
||||
for (const attachment of visibleAttachments) {
|
||||
const id = String(attachment.id || "");
|
||||
const filename = attachment.filename || "attachment";
|
||||
const isImage = composeAttachmentIsImage(attachment);
|
||||
@@ -306,6 +307,12 @@ function syncComposeInlineAttachments() {
|
||||
if (changed) renderComposeAttachments();
|
||||
}
|
||||
|
||||
function trackSignatureInlineAttachment(id) {
|
||||
const value = String(id || "");
|
||||
if (!value) return;
|
||||
state.signatureAttachmentIds.add(value);
|
||||
}
|
||||
|
||||
function composeAttachmentInsertionRange(range, editor = $("#compose-editor")) {
|
||||
const target = range?.cloneRange?.() || document.createRange();
|
||||
try {
|
||||
@@ -533,6 +540,7 @@ function hydrateComposeHtml(html, attachments = state.composeAttachments, draftI
|
||||
const contentUrl = composeAttachmentUrl(attachment, draftId);
|
||||
if (!contentUrl) return;
|
||||
state.inlineAttachmentIds.add(id);
|
||||
if (image.closest('.compose-signature, [data-rustbox-signature="true"]')) trackSignatureInlineAttachment(id);
|
||||
image.dataset.rustboxCid = id;
|
||||
image.draggable = true;
|
||||
image.setAttribute("src", contentUrl);
|
||||
@@ -749,6 +757,7 @@ async function deleteComposeDraft() {
|
||||
state.composeRemoteDraft = null;
|
||||
state.composeAttachments = [];
|
||||
state.inlineAttachmentIds = new Set();
|
||||
state.signatureAttachmentIds = new Set();
|
||||
setSelectedInlineImage(null);
|
||||
state.composeReplyMeta = null;
|
||||
state.composeDirty = false;
|
||||
@@ -853,6 +862,7 @@ async function uploadComposeFiles(files, options = {}) {
|
||||
setComposeUploadProgress(true, overall, `${trText("Uploading attachment…")} ${file.name} · ${overall}%`);
|
||||
}, controller.signal);
|
||||
const uploaded = Array.isArray(data.attachments) ? data.attachments : [];
|
||||
if (options.signature) uploaded.forEach((attachment) => trackSignatureInlineAttachment(attachment.id));
|
||||
added.push(...uploaded);
|
||||
state.composeAttachments = mergeComposeAttachments(state.composeAttachments, uploaded);
|
||||
renderComposeAttachments();
|
||||
@@ -1390,11 +1400,14 @@ async function applyInlineImageEditor(event) {
|
||||
|
||||
function scheduleUnusedInlineAttachmentCleanup() {
|
||||
clearTimeout(state.inlineImageCleanupTimer);
|
||||
state.inlineImageCleanupTimer = setTimeout(syncComposeInlineAttachments, 250);
|
||||
state.inlineImageCleanupTimer = setTimeout(() => { void cleanupUnusedInlineAttachments(); }, 250);
|
||||
}
|
||||
|
||||
async function cleanupUnusedInlineAttachments() {
|
||||
syncComposeInlineAttachments();
|
||||
const referenced = composeInlineAttachmentIds();
|
||||
const staleSignatureIds = [...state.signatureAttachmentIds].filter((id) => !referenced.has(id));
|
||||
for (const id of staleSignatureIds) await deleteComposeAttachment(id);
|
||||
}
|
||||
|
||||
function editorRangeFromPoint(x, y) {
|
||||
@@ -1438,6 +1451,7 @@ async function openImapDraftComposer(folder, uid) {
|
||||
state.composeRemoteDraft = draft.imap_source || { folder, uid, uid_validity: 0 };
|
||||
state.composeAttachments = mergeComposeAttachments(draft.attachments);
|
||||
state.inlineAttachmentIds = new Set();
|
||||
state.signatureAttachmentIds = new Set();
|
||||
setSelectedInlineImage(null);
|
||||
state.composeReplyMeta = {
|
||||
inReplyTo: draft.in_reply_to || null,
|
||||
@@ -1482,6 +1496,7 @@ function applyRecoveredDraft(draft, sourceLabel = "Saved draft") {
|
||||
state.composeRemoteDraft = draft.imap_source || null;
|
||||
state.composeAttachments = mergeComposeAttachments(draft.attachments);
|
||||
state.inlineAttachmentIds = new Set();
|
||||
state.signatureAttachmentIds = new Set();
|
||||
setSelectedInlineImage(null);
|
||||
state.composeReplyMeta = {
|
||||
inReplyTo: draft.in_reply_to || null,
|
||||
@@ -1592,10 +1607,14 @@ function attachmentReminderNeeded() {
|
||||
|
||||
async function deleteComposeAttachment(id) {
|
||||
const attachment = state.composeAttachments.find((item) => String(item.id) === String(id));
|
||||
if (!attachment) return;
|
||||
if (!attachment) {
|
||||
state.signatureAttachmentIds.delete(String(id));
|
||||
return;
|
||||
}
|
||||
if (attachment.source === "imap") {
|
||||
state.composeAttachments = state.composeAttachments.filter((item) => String(item.id) !== String(id));
|
||||
state.inlineAttachmentIds.delete(String(id));
|
||||
state.signatureAttachmentIds.delete(String(id));
|
||||
if (state.composeSelectedImage?.dataset?.rustboxCid === String(id)) setSelectedInlineImage(null);
|
||||
$("#compose-editor")?.querySelectorAll("img[data-rustbox-cid], a[data-rustbox-cid]").forEach((node) => {
|
||||
if (String(node.dataset.rustboxCid) === String(id)) node.remove();
|
||||
@@ -1609,6 +1628,7 @@ async function deleteComposeAttachment(id) {
|
||||
await request(`/drafts/${encodeURIComponent(state.composeDraftId)}/attachments/${encodeURIComponent(id)}`, { method: "DELETE" });
|
||||
state.composeAttachments = state.composeAttachments.filter((a) => a.id !== id);
|
||||
state.inlineAttachmentIds.delete(String(id));
|
||||
state.signatureAttachmentIds.delete(String(id));
|
||||
if (state.composeSelectedImage?.dataset?.rustboxCid === String(id)) setSelectedInlineImage(null);
|
||||
$("#compose-editor")?.querySelectorAll("img[data-rustbox-cid], a[data-rustbox-cid]").forEach((node) => {
|
||||
if (String(node.dataset.rustboxCid) === String(id)) node.remove();
|
||||
@@ -1683,6 +1703,7 @@ function openCompose(mode = "new", options = {}) {
|
||||
state.composeRemoteDraft = null;
|
||||
state.composeAttachments = [];
|
||||
state.inlineAttachmentIds = new Set();
|
||||
state.signatureAttachmentIds = new Set();
|
||||
setSelectedInlineImage(null);
|
||||
setComposeFieldsCollapsed(false);
|
||||
state.composeDirty = false;
|
||||
@@ -1832,6 +1853,7 @@ async function sendMessage(event) {
|
||||
state.composeRemoteDraft = null;
|
||||
state.composeAttachments = [];
|
||||
state.inlineAttachmentIds = new Set();
|
||||
state.signatureAttachmentIds = new Set();
|
||||
setSelectedInlineImage(null);
|
||||
state.composeReplyMeta = null;
|
||||
state.composeDirty = false;
|
||||
|
||||
Reference in new issue
Block a user