From a6997bc4b4778c02b74df16c3c4ab218204ca137 Mon Sep 17 00:00:00 2001 From: Kibi Kelburton Date: Mon, 8 Jun 2026 13:43:28 +0200 Subject: [PATCH] add clickable video timestamps --- public/s/css/f0ckm.css | 7 +++++-- public/s/js/comments.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/public/s/css/f0ckm.css b/public/s/css/f0ckm.css index 0bcc118..33d7558 100644 --- a/public/s/css/f0ckm.css +++ b/public/s/css/f0ckm.css @@ -3258,15 +3258,18 @@ body.layout-legacy .scroll-to-bottom svg { margin: 0; } -.comment-context-link { +.comment-context-link, +.comment-timestamp { color: var(--accent); text-decoration: none; font-family: 'VCR', monospace; font-size: 0.9em; opacity: 1; + cursor: pointer; } -.comment-context-link:hover { +.comment-context-link:hover, +.comment-timestamp:hover { opacity: 1; text-decoration: underline; } diff --git a/public/s/js/comments.js b/public/s/js/comments.js index 2d66e02..2d4a7b8 100644 --- a/public/s/js/comments.js +++ b/public/s/js/comments.js @@ -1727,6 +1727,16 @@ class CommentSystem { return `>>${id}`; }); + // Handle Timestamps (e.g., 2:20, 1:02:20) + const timestampRegex = /\b(? { + const h = hrs ? parseInt(hrs, 10) : 0; + const m = parseInt(mins, 10); + const s = parseInt(secs, 10); + const totalSeconds = h * 3600 + m * 60 + s; + return `${match}`; + }); + // Handle Image Embeds processedLine = processedLine.replace(imageRegex, (match, url) => { let fullUrl = url; @@ -3667,6 +3677,29 @@ class CommentSystem { } } }); + + // Global timestamp seek & scroll listener + document.addEventListener('click', (e) => { + const timestampLink = e.target.closest('.comment-timestamp'); + if (timestampLink) { + e.preventDefault(); + e.stopPropagation(); + const seconds = parseFloat(timestampLink.dataset.time); + if (!isNaN(seconds)) { + const mediaElement = document.querySelector('#my-video') || document.querySelector('audio#my-video'); + if (mediaElement) { + mediaElement.currentTime = seconds; + if (mediaElement.paused) { + mediaElement.play().catch(() => {}); + } + const playerContainer = mediaElement.closest('.v0ck') || mediaElement; + if (playerContainer) { + playerContainer.scrollIntoView({ behavior: 'smooth', block: 'center' }); + } + } + } + } + }); } toggleComments() {