summaryrefslogtreecommitdiff
path: root/web/js/selection.js
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-02 23:18:16 +0300
committerPaul Buetow <paul@buetow.org>2026-05-02 23:18:16 +0300
commit92a59298ac32b4ee6e4f24e6c93307eaa152cd27 (patch)
tree6788f2603caa45ca3cc67d8ed143f03f4d54cfee /web/js/selection.js
parent0482a98c538cbe9ca32b4775bd897b9c728cf686 (diff)
refine playback navigation and player modes
Diffstat (limited to 'web/js/selection.js')
-rw-r--r--web/js/selection.js68
1 files changed, 56 insertions, 12 deletions
diff --git a/web/js/selection.js b/web/js/selection.js
index 6ee4a58..828981a 100644
--- a/web/js/selection.js
+++ b/web/js/selection.js
@@ -10,10 +10,25 @@ export function initSelection() {
});
}
+export function clearSelection() {
+ selectedIndex = -1;
+ refreshCards().forEach((c) => c.classList.remove('selected'));
+}
+
function refreshCards() {
return Array.from(document.querySelectorAll('.media-card, .media-row, .folder-card'));
}
+function syncedIndex(cards) {
+ const domIndex = cards.findIndex((c) => c.classList.contains('selected'));
+ if (domIndex >= 0) {
+ selectedIndex = domIndex;
+ return domIndex;
+ }
+ selectedIndex = -1;
+ return -1;
+}
+
// Compute grid geometry from the rendered cards.
function gridGeometry(cards) {
if (!cards.length) return { cols: 0, rowMap: [] };
@@ -50,7 +65,12 @@ export function selectByElement(el) {
export function next(step = 1) {
const cards = refreshCards();
if (!cards.length) return;
- select((selectedIndex + step + cards.length) % cards.length);
+ const idx = syncedIndex(cards);
+ if (idx < 0) {
+ select(step >= 0 ? 0 : cards.length - 1);
+ return;
+ }
+ select((idx + step + cards.length) % cards.length);
}
export function prev(step = 1) { next(-step); }
@@ -59,12 +79,17 @@ export function prev(step = 1) { next(-step); }
export function navLeft() {
const cards = refreshCards();
if (!cards.length) return;
+ const idx = syncedIndex(cards);
+ if (idx < 0) {
+ select(cards.length - 1);
+ return;
+ }
const { cols } = gridGeometry(cards);
if (cols === 0) return;
- const row = Math.floor(selectedIndex / cols);
- const col = selectedIndex % cols;
+ const row = Math.floor(idx / cols);
+ const col = idx % cols;
if (col > 0) {
- select(selectedIndex - 1);
+ select(idx - 1);
} else if (row > 0) {
// wrap to end of previous row
select(row * cols - 1);
@@ -74,14 +99,19 @@ export function navLeft() {
export function navRight() {
const cards = refreshCards();
if (!cards.length) return;
+ const idx = syncedIndex(cards);
+ if (idx < 0) {
+ select(0);
+ return;
+ }
const { cols } = gridGeometry(cards);
if (cols === 0) return;
- const row = Math.floor(selectedIndex / cols);
- const col = selectedIndex % cols;
+ const row = Math.floor(idx / cols);
+ const col = idx % cols;
const lastInRow = Math.min((row + 1) * cols, cards.length) - 1;
if (col < (lastInRow - row * cols)) {
- select(selectedIndex + 1);
- } else if (selectedIndex < cards.length - 1) {
+ select(idx + 1);
+ } else if (idx < cards.length - 1) {
// wrap to start of next row
select(Math.min((row + 1) * cols, cards.length - 1));
}
@@ -90,9 +120,14 @@ export function navRight() {
export function navUp() {
const cards = refreshCards();
if (!cards.length) return;
+ const idx = syncedIndex(cards);
+ if (idx < 0) {
+ select(cards.length - 1);
+ return;
+ }
const { cols } = gridGeometry(cards);
if (cols === 0) return;
- const idxAbove = selectedIndex - cols;
+ const idxAbove = idx - cols;
if (idxAbove >= 0) {
select(idxAbove);
}
@@ -101,13 +136,22 @@ export function navUp() {
export function navDown() {
const cards = refreshCards();
if (!cards.length) return;
+ const idx = syncedIndex(cards);
+ if (idx < 0) {
+ select(0);
+ return;
+ }
const { cols } = gridGeometry(cards);
if (cols === 0) return;
- const idxBelow = selectedIndex + cols;
+ const idxBelow = idx + cols;
if (idxBelow < cards.length) {
select(idxBelow);
}
}
-export function currentIndex() { return selectedIndex; }
-export function currentElement() { return refreshCards()[selectedIndex] ?? null; }
+export function currentIndex() { return syncedIndex(refreshCards()); }
+export function currentElement() {
+ const cards = refreshCards();
+ const idx = syncedIndex(cards);
+ return idx >= 0 ? cards[idx] : null;
+}