aboutsummaryrefslogtreecommitdiff
path: root/static
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2025-11-24 21:13:47 +0100
committerNathan Reiner <nathan@nathanreiner.xyz>2025-11-24 21:17:05 +0100
commitf3756dac8a49f3b5599fd50f4c631da4168e9eb0 (patch)
treea84d95e30269d4b368b741ffd1a781b7cfbb1988 /static
parent97b35ce73fab8a84d4d3e6807618a252efcf4cd9 (diff)
add jump-to month
Diffstat (limited to 'static')
-rw-r--r--static/index.js11
-rw-r--r--static/month.js10
-rw-r--r--static/pages/image-viewer/index.js17
-rw-r--r--static/widgets/image/index.js11
-rw-r--r--static/widgets/month-select/index.css9
-rw-r--r--static/widgets/month-select/index.js11
6 files changed, 54 insertions, 15 deletions
diff --git a/static/index.js b/static/index.js
index c5bfccc..e67d234 100644
--- a/static/index.js
+++ b/static/index.js
@@ -1,6 +1,6 @@
import * as sfw from 'sfw';
import * as api from 'api';
-import { literal as m } from './month.js';
+import Month from './month.js';
import * as service_worker from './service-worker/index.js';
import LoginView from './pages/login/index.js';
@@ -19,8 +19,12 @@ const image_viewer = ImageViewer.new();
const reload = () => {
image_viewer.clear();
api.images.list().then(images => {
+ const last = Month.from_unix(images[0].timestamp);
+ let first = Month.from_unix(images.findLast(i => i.timestamp).timestamp);
+ month_select.months = first.to(last);
+
for (const image of images) {
- image_viewer.add(image.id);
+ image_viewer.add(image);
}
});
}
@@ -50,9 +54,8 @@ const search = Search.new({
});
const month_select = MonthSelect.new({
- months: m`2019-08`.to(m`2025-11`),
+ onmonth: (month) => image_viewer.jump_to(month),
});
-
const upload_bar = UploadBar.new();
const settings = SettingsView.new({
diff --git a/static/month.js b/static/month.js
index 7875f36..05037d4 100644
--- a/static/month.js
+++ b/static/month.js
@@ -55,7 +55,7 @@ export default class Month {
}
is_same(other) {
- return this.year == other.year || this.month == other.month;
+ return this.year == other?.year && this.month == other?.month;
}
is_same_year(other) {
@@ -68,8 +68,14 @@ export default class Month {
return date.toLocaleDateString('default', { month: 'long' })
}
+ static from_unix(date) {
+ if (date == null) return null;
+
+ return Month.from_date(new Date(date * 1000));
+ }
+
static from_date(date) {
- return new Month(date.getMonth() - 1, date.getFullYear());
+ return new Month(date.getMonth() + 1, date.getFullYear());
}
static from_string(string) {
diff --git a/static/pages/image-viewer/index.js b/static/pages/image-viewer/index.js
index 72af671..73b824e 100644
--- a/static/pages/image-viewer/index.js
+++ b/static/pages/image-viewer/index.js
@@ -15,9 +15,6 @@ export default class ImageViewer extends sfw.element.Container {
this.#images = [];
- this.onnewer = () => {}
- this.onolder = () => {}
-
this.body.append(
this.#container = Div.new({
id: 'container',
@@ -32,8 +29,8 @@ export default class ImageViewer extends sfw.element.Container {
);
}
- add(id) {
- const image = Image.new({ id });
+ add(metadata) {
+ const image = Image.new({ metadata });
this.#images.push(image);
this.#container.insertBefore(image, this.#subtitle);
@@ -45,10 +42,16 @@ export default class ImageViewer extends sfw.element.Container {
this.#container.append(this.#subtitle);
}
+ jump_to(month) {
+ const image = this.#images.find(i => i.month == month || i.month.is_same(month));
+ image.scrollIntoView({ behavior: 'instant' })
+ }
+
#preload(image) {
- const loading_zone = (this.#container.scrollTop + this.#container.offsetHeight) * 2;
+ const loading_zone_after = (this.#container.scrollTop + this.#container.offsetHeight) * 2;
+ const loading_zone_before = this.#container.scrollTop - (this.#container.offsetHeight - image.offsetHeight) * 2;
- if (image.offsetTop < loading_zone) {
+ if (loading_zone_before < image.offsetTop && image.offsetTop < loading_zone_after) {
image.load();
}
}
diff --git a/static/widgets/image/index.js b/static/widgets/image/index.js
index 4c25988..291cf23 100644
--- a/static/widgets/image/index.js
+++ b/static/widgets/image/index.js
@@ -1,5 +1,6 @@
import * as api from 'api';
import * as sfw from 'sfw';
+import Month from '../../month.js';
const { Div, Img } = sfw.element.native;
const css = await sfw.css(import.meta.url, './index.css')
@@ -9,6 +10,7 @@ export default class Image extends sfw.element.Container {
#image
#menu
#id
+ #month
constructor() {
super ({ css })
@@ -43,8 +45,9 @@ export default class Image extends sfw.element.Container {
);
}
- set id(id) {
- this.#id = id;
+ set metadata(image) {
+ this.#id = image.id;
+ this.#month = Month.from_unix(image.timestamp);
this.#container.classList.remove('loaded');
}
@@ -53,4 +56,8 @@ export default class Image extends sfw.element.Container {
this.#image.src = `/api/image/load/${this.#id}`;
}
}
+
+ get month() {
+ return this.#month;
+ }
}
diff --git a/static/widgets/month-select/index.css b/static/widgets/month-select/index.css
index 95a87b0..25ed5d2 100644
--- a/static/widgets/month-select/index.css
+++ b/static/widgets/month-select/index.css
@@ -56,6 +56,10 @@
position: relative;
}
+.month-item.none {
+ font-style: italic;
+}
+
.month-item:before {
content: '';
display: block;
@@ -84,6 +88,11 @@
height: 27px;
}
+.month-item.none:before {
+ top: 0;
+ height: 20px;
+}
+
.month-item:hover {
background: var(--primary);
color: var(--fg-primary);
diff --git a/static/widgets/month-select/index.js b/static/widgets/month-select/index.js
index 6ffbac2..63caf70 100644
--- a/static/widgets/month-select/index.js
+++ b/static/widgets/month-select/index.js
@@ -70,5 +70,16 @@ export default class MonthSelect extends sfw.element.Container {
last = month;
}
+
+ this.#month_container.append(
+ Div.new({
+ className: 'month-item none',
+ innerText: 'No Date',
+ onclick: () => {
+ this.hide();
+ this.onmonth(null);
+ }
+ })
+ );
}
}