still snoting

This commit is contained in:
2026-09-25 14:24:33 -07:00
parent 1fc3cc0e74
commit 54da169fe5
4 changed files with 52 additions and 10 deletions

View File

@@ -200,7 +200,7 @@ function header() {
el("span", {}), el("span", {}), el("span", {}),
]);
return el("header", { class: "topbar" }, [
el("div", { class: "brand" }, [
el("div", { class: "brand", onclick: showHome, title: "Home", role: "button" }, [
el("img", { src: "/static/snotes-logo.png", class: "brand-logo", alt: "snotes" }),
]),
burger,
@@ -214,7 +214,7 @@ function showHelp() {
root.innerHTML = "";
state.editor?.destroy(); state.editor = null;
const back = el("button", { class: "btn ghost", text: "← Back", onclick: showHome });
const back = backButton(showHome);
const wrap = el("div", { class: "editor-wrap" }, [
el("div", { class: "editor-topbar" }, [back]),
el("div", { class: "help-card" }, [
@@ -254,7 +254,7 @@ function showTools() {
root.innerHTML = "";
state.editor?.destroy(); state.editor = null;
const back = el("button", { class: "btn ghost", text: "← Back", onclick: showHome });
const back = backButton(showHome);
const extStatus = el("div", { class: "muted", text: "" });
const installBtn = el("button", { class: "btn primary", text: "Install Browser Extension" });
@@ -422,11 +422,13 @@ function noteList(notes) {
if (isCommon) meta.appendChild(el("span", { class: "common-badge", text: "common" }));
meta.appendChild(document.createTextNode(`${n.username} · edited ${relTime(n.updated_at)} · created ${fmtDate(n.created_at)}`));
if (n.attachments) meta.appendChild(el("span", { class: "attach-count", text: n.attachments + " attachment" + (n.attachments === 1 ? "" : "s") }));
let snippetHtml = n.snippet ? marked.parse(n.snippet) : "";
if (n.image) snippetHtml = snippetHtml.replace(/<img[^>]*>/g, "").trim();
const bodyEl = el("div", { class: "note-body" }, [
el("div", { class: "note-title", text: n.title || "Untitled" }),
meta,
el("div", { class: "note-tags", text: tags }),
n.snippet ? el("div", { class: "note-snippet", html: marked.parse(n.snippet) }) : null,
snippetHtml ? el("div", { class: "note-snippet", html: snippetHtml }) : null,
]);
ul.appendChild(el("li", { class: isCommon ? "note-item note-common" : "note-item", onclick: () => openNote(n.id) }, [
n.image ? el("img", { class: "note-banner", src: n.image, alt: "", loading: "lazy" }) : null,
@@ -442,7 +444,7 @@ async function onSearch(e) {
const results = await api("GET", "/api/search?q=" + encodeURIComponent(q));
const box = document.getElementById("search-results");
box.innerHTML = "";
box.appendChild(el("h2", { text: `Results for "${q}"` }));
box.appendChild(searchHeader(q));
box.appendChild(noteList(results));
}
@@ -451,10 +453,23 @@ async function searchFor(q) {
const results = await api("GET", "/api/search?q=" + encodeURIComponent(q));
const box = document.getElementById("search-results");
box.innerHTML = "";
box.appendChild(el("h2", { text: `Results for "${q}"` }));
box.appendChild(searchHeader(q));
box.appendChild(noteList(results));
}
function searchHeader(q) {
return el("div", { class: "results-head" }, [
backButton(clearSearch),
el("h2", { text: `Results for "${q}"` }),
]);
}
async function clearSearch() {
document.getElementById("search").value = "";
document.getElementById("search-results").innerHTML = "";
await loadRecent();
}
function fmtDate(iso) {
if (!iso) return "";
const d = new Date(iso.replace(" ", "T") + "Z");
@@ -494,7 +509,7 @@ function renderEditor(body, owner) {
state.editor?.destroy();
const isNew = !state.noteId;
const back = el("button", { class: "btn ghost", text: "← Back", onclick: exitEditor });
const back = backButton(exitEditor);
const del = state.noteId ? el("button", { class: "btn danger", text: "Delete", onclick: deleteNote }) : null;
const hist = state.noteId ? el("button", { class: "btn ghost", text: "History", onclick: showHistory }) : null;
@@ -570,6 +585,12 @@ function renderEditor(body, owner) {
function sep() { return el("span", { class: "sep" }); }
function backButton(onclick) {
return el("button", { class: "back-btn", title: "Back", "aria-label": "Back", onclick }, [
el("span", { class: "back-icon", html: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>' }),
]);
}
function toolbarBtn(label, action) {
return el("button", { class: "tool-btn", text: label, onclick: () => runToolbar(action) });
}