diff options
| author | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-12-15 09:00:23 +0100 |
|---|---|---|
| committer | Nathan Reiner <nathan@nathanreiner.xyz> | 2025-12-15 09:00:23 +0100 |
| commit | aa7cb18b17dc169c0b1134bfa61fe3f7809c0f1f (patch) | |
| tree | 8d8fc28906d3d53790cf68250b613f0c27be42f8 /static | |
| parent | 7e340dacafb3b0758cc4641e4ab2630b04177bab (diff) | |
frontent: add date handling
Diffstat (limited to 'static')
| -rw-r--r-- | static/api/images.js | 2 | ||||
| -rw-r--r-- | static/index.js | 2 | ||||
| -rw-r--r-- | static/pages/image-viewer/index.css | 10 | ||||
| -rw-r--r-- | static/pages/image-viewer/index.js | 25 | ||||
| -rw-r--r-- | static/widgets/image/index.css | 12 | ||||
| -rw-r--r-- | static/widgets/image/index.js | 8 |
6 files changed, 55 insertions, 4 deletions
diff --git a/static/api/images.js b/static/api/images.js index 3b8c394..8e9cff2 100644 --- a/static/api/images.js +++ b/static/api/images.js @@ -71,7 +71,7 @@ export function list() { return rest.get('/api/image/list') .then(r => { r.images.forEach(i => { - i.date = new Date(i.date * 1000) + i.date = new Date(i.timestamp * 1000) }); return r.images; }); diff --git a/static/index.js b/static/index.js index 338d636..74386a1 100644 --- a/static/index.js +++ b/static/index.js @@ -26,6 +26,8 @@ const reload = () => { for (const image of images) { image_viewer.add(image); } + + image_viewer.preload_all(); }); } diff --git a/static/pages/image-viewer/index.css b/static/pages/image-viewer/index.css index ec98173..8b57f58 100644 --- a/static/pages/image-viewer/index.css +++ b/static/pages/image-viewer/index.css @@ -26,3 +26,13 @@ font-style: normal; color: var(--fg-disabled); } + +#date { + font-size: 1.2em; + font-weight: bold; + background: #efefef99; + backdrop-filter: blur(10px); + padding: 10px; + border-radius: var(--border-radius); + box-shadow: #223223aa 1px 1px 4px; +} diff --git a/static/pages/image-viewer/index.js b/static/pages/image-viewer/index.js index 73b824e..62e39d8 100644 --- a/static/pages/image-viewer/index.js +++ b/static/pages/image-viewer/index.js @@ -1,6 +1,8 @@ import * as sfw from 'sfw'; const { Div, Img } = sfw.element.native; +import Month from '../../month.js'; + import Image from '../../widgets/image/index.js'; const css = await sfw.css(import.meta.url, './index.css') @@ -9,16 +11,19 @@ export default class ImageViewer extends sfw.element.Container { #container #subtitle #images + #current_month constructor() { super({ css }); + this.#current_month = null; + this.#images = []; this.body.append( this.#container = Div.new({ id: 'container', - onscroll: () => this.#images.forEach(image => this.#preload(image)), + onscroll: () => this.preload_all(), children: [ this.#subtitle = Div.new({ id: 'subtitle', @@ -30,11 +35,21 @@ export default class ImageViewer extends sfw.element.Container { } add(metadata) { + const month = Month.from_unix(metadata.timestamp); + + if (month != this.#current_month && !(month?.is_same(this.#current_month))) { + const content = month == null ? 'No Date' : `${month.name} ${month.year}`; + this.#current_month = month; + const title = Div.new({ + id: 'date', + innerText: content, + }) + this.#container.insertBefore(title, this.#subtitle); + } + const image = Image.new({ metadata }); this.#images.push(image); this.#container.insertBefore(image, this.#subtitle); - - this.#preload(image); } clear() { @@ -47,6 +62,10 @@ export default class ImageViewer extends sfw.element.Container { image.scrollIntoView({ behavior: 'instant' }) } + preload_all() { + this.#images.forEach(image => this.#preload(image)) + } + #preload(image) { const loading_zone_after = (this.#container.scrollTop + this.#container.offsetHeight) * 2; const loading_zone_before = this.#container.scrollTop - (this.#container.offsetHeight - image.offsetHeight) * 2; diff --git a/static/widgets/image/index.css b/static/widgets/image/index.css index a53bddc..f265644 100644 --- a/static/widgets/image/index.css +++ b/static/widgets/image/index.css @@ -94,3 +94,15 @@ cursor: pointer; user-select: none; } + +#date { + background: #efefef99; + padding: 10px; + font-weight: bold; + margin: auto; + width: min-content; + border-radius: var(--border-radius); + cursor: pointer; + user-select: none; + margin-bottom: 10px; +} diff --git a/static/widgets/image/index.js b/static/widgets/image/index.js index 291cf23..e9e1507 100644 --- a/static/widgets/image/index.js +++ b/static/widgets/image/index.js @@ -11,6 +11,7 @@ export default class Image extends sfw.element.Container { #menu #id #month + #date constructor() { super ({ css }) @@ -26,6 +27,7 @@ export default class Image extends sfw.element.Container { this.#menu = Div.new({ id: 'menu', children: [ + this.#date = Div.new({ id: 'date' }), Div.new({ id: 'delete', innerText: 'Delete', @@ -40,15 +42,21 @@ export default class Image extends sfw.element.Container { oncontextmenu: (e) => { this.#menu.classList.toggle('open'); e.preventDefault(); + }, + ondblclick: (e) => { + this.#menu.classList.toggle('open'); + e.preventDefault(); } }) ); } set metadata(image) { + const date = new Date(image.timestamp * 1000); this.#id = image.id; this.#month = Month.from_unix(image.timestamp); this.#container.classList.remove('loaded'); + this.#date.innerText = date.toLocaleDateString() } load() { |