From 200bd37a28ceaf3c81ac693d66db7526c9aa1364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lera=20Elvo=C3=A9?= Date: Fri, 5 Jun 2026 21:01:29 +0300 Subject: [PATCH] add lightbox for post image previews 2 --- app/templates/common/macros.html | 2 +- app/templates/threads/thread.html | 13 ++ data/static/css/style.css | 223 ++++++++++++++++++------------ data/static/js/bits/thread.js | 64 +++++++++ 4 files changed, 210 insertions(+), 92 deletions(-) create mode 100644 data/static/js/bits/thread.js diff --git a/app/templates/common/macros.html b/app/templates/common/macros.html index 8393f47..d53f58d 100644 --- a/app/templates/common/macros.html +++ b/app/templates/common/macros.html @@ -172,7 +172,7 @@ -
+
{{ bookmark_menu() }} + + + + + {%- if is_logged_in() and get_active_user().can_post_to_thread_or_topic(thread) -%}

Reply to "{{thread.title}}"

diff --git a/data/static/css/style.css b/data/static/css/style.css index d12f555..0762568 100644 --- a/data/static/css/style.css +++ b/data/static/css/style.css @@ -743,6 +743,125 @@ table { } } +ol.sortable-list { + display: flex; + gap: var(--base-padding); + flex-direction: column; + list-style: none; + flex-grow: 1; + margin: 0; + padding-left: 0; + + li { + display: flex; + gap: var(--big-padding); + } + + li.immovable .dragger { + cursor: not-allowed; + } +} + +.plank.dragger { + display: flex; + align-items: center; + /*background-color: var(--bg-color-tertiary);*/ + padding: var(--base-padding); + cursor: move; +} + +.sortable-item-inner { + display: flex; + gap: var(--base-padding); + flex-grow: 1; + flex-direction: column; + + & > * { + flex-grow: 1; + } + + &.row { + flex-direction: row; + } + + &:not(.row):not(.full) > * { + margin-right: auto; + } +} + +.badge-editor-badge-container { + display: flex; + align-items: baseline; + gap: var(--base-padding); + + & > input[type=text], & > input[type=url] { + width: 100%; + } +} + +.badge-editor-file-picker { + display: flex; + gap: var(--base-padding); + flex-direction: column; + align-items: center; + min-width: 150px; + + & > input[type=file] { + width: 100%; + + &::file-selector-button { + display: none; + } + } + + &.hidden { + display: none; + } +} + +.badge-editor-badge-select { + display: flex; + gap: var(--base-padding); + flex-direction: column; + align-items: center; + min-width: 200px; + & > select { + width: 100%; + } +} + +.js-only { + display: none; +} + +dialog.plank.thread-lighbox { + margin: auto; + min-width: 80vw; + min-height: 70vh; + max-width: 80vw; + max-height: 70vh; + + flex-direction: column; + justify-content: space-between; + align-items: center; + + & > .menu { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + } + + &:open { + display: flex; + } +} + +.lightbox-image { + max-width: 50vw; + max-height: 50vh; +} + /* babycode tags */ .inline-code { background-color: var(--code-bg-color); @@ -924,97 +1043,6 @@ a.mention { } } -ol.sortable-list { - display: flex; - gap: var(--base-padding); - flex-direction: column; - list-style: none; - flex-grow: 1; - margin: 0; - padding-left: 0; - - li { - display: flex; - gap: var(--big-padding); - } - - li.immovable .dragger { - cursor: not-allowed; - } -} - -.plank.dragger { - display: flex; - align-items: center; - /*background-color: var(--bg-color-tertiary);*/ - padding: var(--base-padding); - cursor: move; -} - -.sortable-item-inner { - display: flex; - gap: var(--base-padding); - flex-grow: 1; - flex-direction: column; - - & > * { - flex-grow: 1; - } - - &.row { - flex-direction: row; - } - - &:not(.row):not(.full) > * { - margin-right: auto; - } -} - -.badge-editor-badge-container { - display: flex; - align-items: baseline; - gap: var(--base-padding); - - & > input[type=text], & > input[type=url] { - width: 100%; - } -} - -.badge-editor-file-picker { - display: flex; - gap: var(--base-padding); - flex-direction: column; - align-items: center; - min-width: 150px; - - & > input[type=file] { - width: 100%; - - &::file-selector-button { - display: none; - } - } - - &.hidden { - display: none; - } -} - -.badge-editor-badge-select { - display: flex; - gap: var(--base-padding); - flex-direction: column; - align-items: center; - min-width: 200px; - & > select { - width: 100%; - } -} - -.js-only { - display: none; -} - @media (max-width: 768px) { body { margin-left: 0; @@ -1085,4 +1113,17 @@ ol.sortable-list { flex-direction: column; align-items: center; } + + dialog.plank.thread-lighbox { + margin: 0; + min-width: 100vw; + min-height: 100vh; + max-width: unset; + max-height: unset; + } + + .lightbox-image { + max-width: 100%; + max-height: 100%; + } } diff --git a/data/static/js/bits/thread.js b/data/static/js/bits/thread.js new file mode 100644 index 0000000..7a6852a --- /dev/null +++ b/data/static/js/bits/thread.js @@ -0,0 +1,64 @@ +export const b = { + init: 'activatePostImages', +} + +const POST_IMAGES_SELECTOR = 'img.post-image:not(aside img.post-image)' + +let images = []; +let currentIndex = 0; + +export function activatePostImages(_, __, ___) { + const images = document.querySelectorAll(POST_IMAGES_SELECTOR); + images.forEach(image => { + image.style.cursor = 'pointer'; + image.dataset.s = 'collectImages'; + }); +} + +export function collectImages(_, sender, el) { + if (!el.contains(sender)) return; + images = Array.from(el.querySelectorAll(POST_IMAGES_SELECTOR)); + currentIndex = images.indexOf(sender); + b.trigger('showLightbox'); +} + +export function showLightbox(_, __, el) { + const originalImg = images[currentIndex]; + const lightboxImg = el.querySelector('img'); + const anchor = el.querySelector('a'); + anchor.href = originalImg.src; + lightboxImg.src = originalImg.src; + lightboxImg.alt = originalImg.alt; + + if (!el.open) { + el.showModal(); + } + + b.trigger('lightboxSetCounter'); +} + +export function closeLightbox(_, __, el) { + el.close(); +} + +export function lightboxSetCounter(_, __, el) { + el.innerText = `${currentIndex + 1}/${images.length}`; +} + +export function lightboxNext(_, __, ___) { + if (images.length == 1) return; + currentIndex++; + if (currentIndex >= images.length) { + currentIndex = 0; + } + b.trigger('showLightbox'); +} + +export function lightboxPrevious(_, __, ___) { + if (images.length == 1) return; + currentIndex--; + if (currentIndex < 0) { + currentIndex = images.length - 1; + } + b.trigger('showLightbox'); +}