Losing focus -- another tab, another window, another app -- now puts the whole page behind a blur, so an app switcher's snapshot or a glance over the shoulder gives nothing away. It comes back on focus, on the tab becoming visible again, and on the first touch or key, which lands on the veil rather than on a page nobody could see. Painted as a backdrop filter on a fixed overlay above everything the app can show: a filter on the page itself would make every fixed element position against the wrong box. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MPZFnNdHbPGDTqQUNiE4ZN
60 lines
2.1 KiB
JavaScript
60 lines
2.1 KiB
JavaScript
window.App = window.App || {};
|
|
|
|
(function() {
|
|
// App bootstrap: initialize storage, render UI, and load the first page.
|
|
async function initApp() {
|
|
// Armed before anything is on screen: there is nothing to show behind
|
|
// a blur yet, but the window can lose focus during startup too.
|
|
App.privacy.start();
|
|
|
|
await App.storage.ensureDefaults();
|
|
App.ui.applyTheme();
|
|
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();
|
|
|
|
App.videos.observeSentinel();
|
|
|
|
const loadMoreBtn = document.getElementById('load-more-btn');
|
|
if (loadMoreBtn) {
|
|
loadMoreBtn.onclick = () => {
|
|
App.videos.loadVideos({ force: true });
|
|
};
|
|
}
|
|
|
|
const errorToastClose = document.getElementById('error-toast-close');
|
|
if (errorToastClose) {
|
|
errorToastClose.onclick = () => {
|
|
const toast = document.getElementById('error-toast');
|
|
if (toast) toast.classList.remove('show');
|
|
};
|
|
}
|
|
|
|
window.addEventListener('resize', () => {
|
|
App.videos.ensureViewportFilled();
|
|
});
|
|
|
|
await App.videos.loadVideos();
|
|
App.favorites.syncButtons();
|
|
|
|
// The UI above is rendered entirely from the last known status cached in
|
|
// localStorage, so startup never blocks on (or breaks because of) a slow
|
|
// or failing status endpoint. Now fetch fresh status in the background and
|
|
// reconcile the UI with whatever comes back.
|
|
App.storage.refreshServerStatusInBackground();
|
|
|
|
// Watch for frontend deploys and seamlessly reload/hot-swap changed assets.
|
|
if (App.version && App.version.start) {
|
|
App.version.start();
|
|
}
|
|
}
|
|
|
|
initApp();
|
|
})();
|