ventures: refresh havre from havre-open

This commit is contained in:
github-actions[bot] committed 2026-10-19 15:44:56 +00:00
1 parent fcee957cb9
commit 54d2137fac
2 files changed
+32 -1

No files matched your search

+30 -1
View File
@@ -913,12 +913,41 @@ function renderGallery() {
$("#gal-empty").textContent = "no photos or clips here yet.";
$("#gal-grid").replaceChildren(...items.map(({ m, t }) => {
const md = m.media, clip = md.kind === "clip";
const pic = mediaEl(clip ? "video" : "img", md.id, clip ? { muted: true, playsinline: true, preload: "metadata" } : { alt: md.shot || (md.kind === "photo-in" ? "your photo" : "a photo"), decoding: "async" }, md.kind === "clip" ? "clip" : "photo");
const pic = clip ? clipStill(md) : mediaEl("img", md.id, { alt: md.shot || (md.kind === "photo-in" ? "your photo" : "a photo"), decoding: "async" }, "photo");
const when = m.at ? T.ago(m.at) : "";
return h("li", {}, h("button", { type: "button", title: md.shot || null, onclick: () => jumpTo(t, m) }, pic,
h("span", { class: "cap", text: [clip ? "clip" : md.kind === "photo-in" ? "yours" : "photo", when, galScope === "all" && T.titleOf(t, t.msgs, 24)].filter(Boolean).join(" · ") })));
}));
}
/** a clip as a still: a frame taken from it, kept for the session, under a play mark */
const stills = new Map();
function clipStill(md) {
const img = h("img", { alt: md.shot ? "A clip: " + md.shot : "A clip", decoding: "async" });
const box = h("span", { class: "still" }, img, h("span", { class: "play", "aria-hidden": "true", text: "▶" }));
if (stills.has(md.id)) { img.src = stills.get(md.id); return box; }
M.url(md.id).then((u) => {
if (!u) return;
const v = document.createElement("video");
v.muted = true; v.playsInline = true; v.preload = "auto"; v.src = u;
const grab = () => {
try {
const w = v.videoWidth, hgt = v.videoHeight;
if (!w || !hgt) return;
const s = 320 / Math.max(w, hgt), cv = document.createElement("canvas");
cv.width = Math.round(w * s); cv.height = Math.round(hgt * s);
cv.getContext("2d").drawImage(v, 0, 0, cv.width, cv.height);
const data = cv.toDataURL("image/jpeg", 0.8);
stills.set(md.id, data);
img.src = data;
} catch { /* no still: the play mark on its own */ }
v.removeAttribute("src"); v.load();
};
v.addEventListener("seeked", grab, { once: true });
v.addEventListener("loadeddata", () => { v.currentTime = Math.min(0.5, (v.duration || 1) / 2); }, { once: true });
v.load();
});
return box;
}
/** go to a photo or clip in its chat */
function jumpTo(t, m) {
$("#gallerydlg").close();
+2
View File
@@ -228,6 +228,8 @@ input:disabled, textarea:disabled, select:disabled { background: #f2f2f2; color:
.gal button { display: block; width: 100%; padding: 0; border: 0; background: none; color: inherit; text-align: left; cursor: pointer; }
.gal img, .gal video { display: block; width: 100%; aspect-ratio: 1; object-fit: cover; border: 1px solid var(--ink); background: var(--ink); }
.gal button:hover img, .gal button:hover video, .gal button:focus-visible img, .gal button:focus-visible video { outline: 3px solid var(--hi); }
.gal .still { position: relative; display: block; }
.gal .play { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); padding: 6px 10px; background: var(--paper); color: var(--ink); border: 1px solid var(--ink); font: 14px/1 var(--mono); }
.gal .cap { display: block; margin-top: 4px; font: 11px/1.4 var(--mono); overflow-wrap: anywhere; }
/* edit / delete under a message: shown on hover or focus; always, faintly, where there's no hover (phones) */
.msgtools { grid-column: 2; font: 12px/1.4 var(--mono); opacity: 0; }