This commit is contained in:
Mateusz Gruszczyński
2026-09-20 14:37:09 +02:00
parent e9f1dc515c
commit de3cb9f111
4 changed files with 72 additions and 85 deletions
+27 -23
View File
@@ -153,14 +153,6 @@ export function bindNoteFiles({ editor, endpoints, getAccessToken, getUploadMaxS
});
}
function fileTypeBadge(file) {
const filename = String(file?.filename || "");
const extension = filename.includes(".") ? filename.split(".").pop().replace(/[^a-z0-9]/gi, "").slice(0, 4) : "";
if (extension) return extension.toUpperCase();
const major = String(file?.mime_type || "file").split("/", 1)[0];
return ({ image: "IMG", video: "VID", audio: "AUD", text: "TXT", application: "FILE" })[major] || "FILE";
}
function fileActionButtons(file) {
const attributes = `data-url="${escapeHtml(file.url)}" data-name="${escapeHtml(file.filename)}" data-mime="${escapeHtml(file.mime_type)}"`;
const primaryInsert = isVideo(file.mime_type)
@@ -170,12 +162,12 @@ export function bindNoteFiles({ editor, endpoints, getAccessToken, getUploadMaxS
? `<button class="action-button action-button--secondary compact-button" data-add-file-to-note data-insert-mode="download" ${attributes}>${escapeHtml(t("files.addDownload", {}, "Add download"))}</button>`
: "";
const codeButtons = isVideo(file.mime_type)
? `<button class="action-button action-button--secondary compact-button" data-show-file-code="link" ${attributes}>${escapeHtml(t("files.link", {}, "Link"))}</button>
<button class="action-button action-button--secondary compact-button" data-show-file-code="player" ${attributes}>${escapeHtml(t("files.playerCode", {}, "Player code"))}</button>
<button class="action-button action-button--secondary compact-button" data-show-file-code="download" ${attributes}>${escapeHtml(t("files.downloadCode", {}, "Download code"))}</button>`
: `<button class="action-button action-button--secondary compact-button" data-show-file-code="link" ${attributes}>${escapeHtml(t("files.link", {}, "Link"))}</button>
<button class="action-button action-button--secondary compact-button" data-show-file-code="alias" ${attributes}>${escapeHtml(t("files.alias", {}, "Alias"))}</button>
<button class="action-button action-button--secondary compact-button" data-show-file-code="markdown" ${attributes}>${escapeHtml(t("files.markdown", {}, "Markdown"))}</button>`;
? `<button class="action-button action-button--secondary compact-button" data-show-file-code="link" aria-pressed="false" ${attributes}>${escapeHtml(t("files.link", {}, "Link"))}</button>
<button class="action-button action-button--secondary compact-button" data-show-file-code="player" aria-pressed="false" ${attributes}>${escapeHtml(t("files.playerCode", {}, "Player code"))}</button>
<button class="action-button action-button--secondary compact-button" data-show-file-code="download" aria-pressed="false" ${attributes}>${escapeHtml(t("files.downloadCode", {}, "Download code"))}</button>`
: `<button class="action-button action-button--secondary compact-button" data-show-file-code="link" aria-pressed="false" ${attributes}>${escapeHtml(t("files.link", {}, "Link"))}</button>
<button class="action-button action-button--secondary compact-button" data-show-file-code="alias" aria-pressed="false" ${attributes}>${escapeHtml(t("files.alias", {}, "Alias"))}</button>
<button class="action-button action-button--secondary compact-button" data-show-file-code="markdown" aria-pressed="false" ${attributes}>${escapeHtml(t("files.markdown", {}, "Markdown"))}</button>`;
const deleteButton = canDelete()
? `<button class="action-button action-button--danger compact-button" data-delete-file="${file.id}" data-file-name="${escapeHtml(file.filename)}">${escapeHtml(t("files.delete", {}, "Delete file"))}</button>`
: "";
@@ -200,7 +192,7 @@ export function bindNoteFiles({ editor, endpoints, getAccessToken, getUploadMaxS
}
function fileSearchText(file) {
return `${file.filename || ""} ${file.mime_type || ""} ${fileTypeBadge(file)}`.toLocaleLowerCase();
return `${file.filename || ""} ${file.mime_type || ""}`.toLocaleLowerCase();
}
function fileRow(file) {
@@ -211,7 +203,6 @@ export function bindNoteFiles({ editor, endpoints, getAccessToken, getUploadMaxS
return `
<article class="file-row" data-file-row="${file.id}" data-file-search="${escapeHtml(fileSearchText(file))}">
<div class="file-row-main">
<div class="file-type-badge" aria-hidden="true">${escapeHtml(fileTypeBadge(file))}</div>
<div class="file-copy">
<div class="file-name" title="${escapeHtml(file.filename)}">${escapeHtml(file.filename)}</div>
<div class="file-meta">
@@ -223,8 +214,13 @@ export function bindNoteFiles({ editor, endpoints, getAccessToken, getUploadMaxS
</div>
</div>
<div class="file-actions">${actions.primary}</div>
<div class="file-secondary-actions" hidden>${actions.secondary}</div>
<div class="file-code" hidden><textarea readonly aria-label="${escapeHtml(generatedCodeLabel)}"></textarea><button class="action-button action-button--primary compact-button" data-copy-generated>${escapeHtml(t("share.copy", {}, "Copy"))}</button></div>
<div class="file-secondary-actions" hidden>
<div class="file-secondary-actions__buttons">${actions.secondary}</div>
<div class="file-code" hidden>
<input class="file-code-value" type="text" readonly aria-label="${escapeHtml(generatedCodeLabel)}" spellcheck="false">
<button class="action-button action-button--secondary file-code-copy" data-copy-generated>${escapeHtml(t("share.copy", {}, "Copy"))}</button>
</div>
</div>
</article>`;
}
@@ -258,7 +254,7 @@ export function bindNoteFiles({ editor, endpoints, getAccessToken, getUploadMaxS
if (refreshing && filesLoaded) return;
list.innerHTML = Array.from({ length: 3 }, () => `
<div class="file-row file-row--skeleton" aria-hidden="true">
<div class="file-row-main"><span class="file-skeleton file-skeleton--badge"></span><div class="file-copy"><span class="file-skeleton file-skeleton--name"></span><span class="file-skeleton file-skeleton--meta"></span></div></div>
<div class="file-row-main"><div class="file-copy"><span class="file-skeleton file-skeleton--name"></span><span class="file-skeleton file-skeleton--meta"></span></div></div>
<span class="file-skeleton file-skeleton--action"></span>
</div>`).join("");
}
@@ -431,12 +427,18 @@ export function bindNoteFiles({ editor, endpoints, getAccessToken, getUploadMaxS
const toggleButton = event.target.closest("[data-toggle-file-actions]");
if (toggleButton) {
const panel = toggleButton.closest(".file-row")?.querySelector(".file-secondary-actions");
const row = toggleButton.closest(".file-row");
const panel = row?.querySelector(".file-secondary-actions");
if (!panel) return;
const expanded = panel.hidden;
panel.hidden = !expanded;
toggleButton.setAttribute("aria-expanded", String(expanded));
toggleButton.textContent = expanded ? t("files.less", {}, "Less") : t("common.more", {}, "More");
if (!expanded) {
const codePanel = row.querySelector(".file-code");
if (codePanel) codePanel.hidden = true;
row.querySelectorAll("[data-show-file-code][aria-pressed="true"]").forEach(button => button.setAttribute("aria-pressed", "false"));
}
return;
}
@@ -452,8 +454,9 @@ export function bindNoteFiles({ editor, endpoints, getAccessToken, getUploadMaxS
const showButton = event.target.closest("[data-show-file-code]");
if (showButton) {
const panel = showButton.closest(".file-row").querySelector(".file-code");
const output = panel.querySelector("textarea");
const row = showButton.closest(".file-row");
const panel = row.querySelector(".file-code");
const output = panel.querySelector(".file-code-value");
const safeUrl = safeAttachmentUrl(showButton.dataset.url);
const absolute = new URL(safeUrl, location.origin).href;
let text = showButton.dataset.showFileCode === "link" && isVideo(showButton.dataset.mime)
@@ -470,6 +473,7 @@ export function bindNoteFiles({ editor, endpoints, getAccessToken, getUploadMaxS
}
output.value = text;
panel.hidden = false;
row.querySelectorAll("[data-show-file-code]").forEach(button => button.setAttribute("aria-pressed", String(button === showButton)));
output.focus();
output.select();
return;
@@ -478,7 +482,7 @@ export function bindNoteFiles({ editor, endpoints, getAccessToken, getUploadMaxS
const copyButton = event.target.closest("[data-copy-generated]");
if (copyButton) {
try {
await copyText(copyButton.closest(".file-code").querySelector("textarea").value);
await copyText(copyButton.closest(".file-code").querySelector(".file-code-value").value);
notify("success", "Generated file code copied to the clipboard.", { title: "Copied" });
} catch (error) {
notify("danger", error.message, { title: "Could not copy file code" });