adjustable card/font size

This commit is contained in:
Simon
2026-06-30 16:26:20 +00:00
parent 2e6e74b959
commit 5d739bec12
6 changed files with 120 additions and 7 deletions

View File

@@ -8,6 +8,9 @@ window.App = window.App || {};
App.ui.applyPreferredQuality();
App.ui.applyFeedEndBehavior();
App.ui.applyDensity();
// Set the text-size CSS variable before the first pack so initial card
// heights are measured at the user's chosen size.
document.documentElement.style.setProperty('--card-font-scale', App.storage.getFontScale());
App.ui.renderMenu();
App.favorites.renderBar();
App.ui.bindGlobalHandlers();

View File

@@ -57,6 +57,30 @@ App.session = App.session || {};
localStorage.setItem('density', nextDensity === 'compact' ? 'compact' : 'comfortable');
};
// User-tunable card width / text size multipliers (default 1.0). Clamped so a
// stale or hand-edited value can never break the layout.
const clampScale = function(value, min, max, fallback) {
const n = parseFloat(value);
if (!isFinite(n)) return fallback;
return Math.min(max, Math.max(min, n));
};
App.storage.getCardScale = function() {
return clampScale(localStorage.getItem('cardScale'), 0.7, 1.5, 1);
};
App.storage.setCardScale = function(next) {
localStorage.setItem('cardScale', clampScale(next, 0.7, 1.5, 1));
};
App.storage.getFontScale = function() {
return clampScale(localStorage.getItem('fontScale'), 0.8, 1.4, 1);
};
App.storage.setFontScale = function(next) {
localStorage.setItem('fontScale', clampScale(next, 0.8, 1.4, 1));
};
App.storage.getServerEntries = function() {
const config = App.storage.getConfig();
if (!config.servers || !Array.isArray(config.servers)) return [];

View File

@@ -28,6 +28,29 @@ App.ui = App.ui || {};
if (select) select.value = density;
};
// Card Size: re-packs the virtual grid (column count derives from the scaled
// minimum card width in videos.js).
App.ui.applyCardScale = function() {
const scale = App.storage.getCardScale();
const range = document.getElementById('card-size-range');
if (range) range.value = scale;
if (App.virtualGrid && typeof App.virtualGrid.relayout === 'function') {
App.virtualGrid.relayout();
}
};
// Text Size: drives the --card-font-scale CSS variable; a re-pack follows so
// card heights account for the new text size.
App.ui.applyFontScale = function() {
const scale = App.storage.getFontScale();
document.documentElement.style.setProperty('--card-font-scale', scale);
const range = document.getElementById('text-size-range');
if (range) range.value = scale;
if (App.virtualGrid && typeof App.virtualGrid.relayout === 'function') {
App.virtualGrid.relayout();
}
};
// Toast helper for playback + network errors.
App.ui.showError = function(message) {
const toast = document.getElementById('error-toast');
@@ -305,6 +328,24 @@ App.ui = App.ui || {};
};
}
const cardSizeRange = document.getElementById('card-size-range');
if (cardSizeRange) {
cardSizeRange.value = App.storage.getCardScale();
cardSizeRange.oninput = () => {
App.storage.setCardScale(cardSizeRange.value);
App.ui.applyCardScale();
};
}
const textSizeRange = document.getElementById('text-size-range');
if (textSizeRange) {
textSizeRange.value = App.storage.getFontScale();
textSizeRange.oninput = () => {
App.storage.setFontScale(textSizeRange.value);
App.ui.applyFontScale();
};
}
const feedEndSelect = document.getElementById('feed-end-select');
if (feedEndSelect) {
feedEndSelect.value = App.storage.getFeedEndBehavior();

View File

@@ -565,6 +565,7 @@ App.videos = App.videos || {};
const measureMetrics = function() {
const el = grid();
if (!el) return false;
const phone = window.matchMedia('(max-width: 480px)').matches;
const mobile = window.matchMedia('(max-width: 768px)').matches;
const large = window.matchMedia('(min-width: 1600px)').matches;
gap = mobile ? 12 : (large ? 24 : 16);
@@ -580,8 +581,12 @@ App.videos = App.videos || {};
if (inner <= 0) return false;
// Density toggle (see enhance.js / settings) tunes the minimum card
// width, so "compact" packs more columns at the same viewport width.
const minCardW = document.body.dataset.density === 'compact' ? 210 : 260;
cols = mobile ? 2 : Math.max(1, Math.floor((inner + gap) / (minCardW + gap)));
// The user's Card Size setting scales that minimum on top of density.
const cardScale = (App.storage && App.storage.getCardScale) ? App.storage.getCardScale() : 1;
const minCardW = (document.body.dataset.density === 'compact' ? 210 : 260) * cardScale;
// One card per row on phones, two on larger handsets/tablets, and a
// size-driven count on desktop.
cols = phone ? 1 : (mobile ? 2 : Math.max(1, Math.floor((inner + gap) / (minCardW + gap))));
colWidth = (inner - gap * (cols - 1)) / cols;
return true;
};