|
|
|
|
@ -1429,6 +1429,7 @@ HTML = """<!doctype html>
|
|
|
|
|
body[data-contrast="high"] { --ui-muted: var(--ui-muted-contrast); --ui-border: var(--ui-border-contrast); }
|
|
|
|
|
body[data-motion="none"] *, body[data-motion="none"] *::before, body[data-motion="none"] *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
|
|
|
|
|
body[data-motion="expressive"] .settings-panel, body[data-motion="expressive"] .model-panel, body[data-motion="expressive"] .archive-panel { animation-duration: .62s; }
|
|
|
|
|
.video, .settings-panel, .model-panel, .archive-panel { width: 100%; max-width: none; }
|
|
|
|
|
@keyframes appearance-in { from { opacity: 0; transform: translateY(-5px) scale(.98); } to { opacity: 1; transform: none; } }
|
|
|
|
|
@media (max-width: 760px) {
|
|
|
|
|
.appearance-trigger { min-width: 38px; width: 38px; padding: 0; justify-content: center; }
|
|
|
|
|
@ -1990,7 +1991,10 @@ HTML = """<!doctype html>
|
|
|
|
|
} catch (_error) { return {}; }
|
|
|
|
|
}
|
|
|
|
|
function saveConfigLayout() {
|
|
|
|
|
try { localStorage.setItem('fpv-config-layout-v1', JSON.stringify(configLayout)); } catch (_error) {}
|
|
|
|
|
try {
|
|
|
|
|
localStorage.setItem('fpv-config-layout-v1', JSON.stringify(configLayout));
|
|
|
|
|
if (configCanvas) localStorage.setItem('fpv-config-canvas-width', String(Math.round(configCanvasWidth())));
|
|
|
|
|
} catch (_error) {}
|
|
|
|
|
}
|
|
|
|
|
function configMinWidth() {
|
|
|
|
|
return window.innerWidth <= 760 ? 220 : 240;
|
|
|
|
|
@ -2040,6 +2044,22 @@ HTML = """<!doctype html>
|
|
|
|
|
function applyStoredConfigLayout() {
|
|
|
|
|
if (!configCanvas) return;
|
|
|
|
|
const width = configCanvasWidth();
|
|
|
|
|
let previousWidth = 0;
|
|
|
|
|
try { previousWidth = Number(localStorage.getItem('fpv-config-canvas-width') || 0); } catch (_error) {}
|
|
|
|
|
if (!previousWidth) previousWidth = Object.values(configLayout).reduce((value, entry) => {
|
|
|
|
|
if (!entry || typeof entry !== 'object') return value;
|
|
|
|
|
const left = Number(entry.left); const blockWidth = Number(entry.width);
|
|
|
|
|
return Number.isFinite(left) && Number.isFinite(blockWidth) ? Math.max(value, left + blockWidth) : value;
|
|
|
|
|
}, 0);
|
|
|
|
|
if (previousWidth > 0 && width > configMinWidth() && Math.abs(width - previousWidth) > 80) {
|
|
|
|
|
const scale = width / previousWidth;
|
|
|
|
|
Object.values(configLayout).forEach(entry => {
|
|
|
|
|
if (!entry || typeof entry !== 'object') return;
|
|
|
|
|
if (Number.isFinite(Number(entry.left))) entry.left = Math.max(0, Math.round(Number(entry.left) * scale));
|
|
|
|
|
if (Number.isFinite(Number(entry.width))) entry.width = Math.max(configMinWidth(), Math.round(Number(entry.width) * scale));
|
|
|
|
|
});
|
|
|
|
|
saveConfigLayout();
|
|
|
|
|
}
|
|
|
|
|
const gap = 14;
|
|
|
|
|
const visible = block => block && !configBlockState(block);
|
|
|
|
|
const source = configBlocks.find(block => block.dataset.section === 'source' && visible(block));
|
|
|
|
|
|