v0.2.17
RustBox CI / rustbox (push) Canceled after 0s

This commit is contained in:
Mateusz Gruszczyński committed 2026-11-03 10:35:05 +01:00
1 parent 2ac1566eca
commit 1bb398acd1
32 files changed
+907 -136

No files matched your search

+26 -4
View File
@@ -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;