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

@@ -559,6 +559,38 @@ body.theme-light .input-row input:focus {
background: var(--bg-tertiary);
}
.setting-item input[type="range"] {
width: 100%;
appearance: none;
-webkit-appearance: none;
height: 6px;
border-radius: 999px;
background: var(--bg-tertiary);
border: 1px solid var(--border);
cursor: pointer;
margin: 6px 0;
}
.setting-item input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 18px;
height: 18px;
border-radius: 50%;
background: var(--text-primary);
border: none;
cursor: pointer;
}
.setting-item input[type="range"]::-moz-range-thumb {
width: 18px;
height: 18px;
border-radius: 50%;
background: var(--text-primary);
border: none;
cursor: pointer;
}
.setting-item select {
width: 100%;
padding: 9px 12px;
@@ -872,11 +904,11 @@ body.theme-light .setting-item select option {
}
.video-card h4 {
font-size: 16px;
font-size: calc(16px * var(--card-font-scale, 1));
}
.video-card p {
font-size: 13px;
font-size: calc(13px * var(--card-font-scale, 1));
}
}
@@ -989,7 +1021,7 @@ body.theme-light .setting-item select option {
}
.video-card h4 {
font-size: 15px;
font-size: calc(15px * var(--card-font-scale, 1));
font-weight: 500;
padding: 12px 12px 10px;
line-height: 1.3;
@@ -1022,7 +1054,7 @@ body.theme-light .setting-item select option {
}
.video-card p {
font-size: 12px;
font-size: calc(12px * var(--card-font-scale, 1));
color: var(--text-secondary);
padding: 0 12px 12px 12px;
margin: 0;
@@ -1040,7 +1072,7 @@ body.theme-light .setting-item select option {
}
.video-tag {
font-size: 11px;
font-size: calc(11px * var(--card-font-scale, 1));
color: var(--text-secondary);
background: var(--bg-tertiary);
border: 1px solid var(--border);

View File

@@ -98,6 +98,14 @@
<option value="compact">Compact</option>
</select>
</div>
<div class="setting-item">
<label for="card-size-range">Card Size</label>
<input type="range" id="card-size-range" min="0.7" max="1.5" step="0.1" value="1">
</div>
<div class="setting-item">
<label for="text-size-range">Text Size</label>
<input type="range" id="text-size-range" min="0.8" max="1.4" step="0.1" value="1">
</div>
<div class="setting-item">
<label for="feed-end-select">Reels: On Video End</label>
<select id="feed-end-select">

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;
};