mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-11 01:12:20 +02:00
perf(ui): stop session loading from blocking shell (#5927)
* perf(ui): stop session loading from blocking shell * fix(startup): open routes on their own data, retire the loader for good Follow-up to review on #5927. - Route openers are now classified by the data they actually read. Only /email touches the hydrated session list (its new-chat path falls back to the most recent session's model when no default chat is set), so every other route opens as soon as module wiring completes instead of queueing behind /api/sessions. This is the deferred-route half of #5926, which the first pass left unimplemented. - index.html's 5s fallback removes the loader node again. Leaving it in the DOM indefinitely kept _shouldPreserveStartupComposer true forever on a hung /api/sessions, so the composer stopped clearing on session switch. - A missing session module settles hydration instead of leaving the sidebar on "Loading chats…" and dropping the user's route on the floor. - Startup sequencing moved to static/js/startupShell.js so it can be run by tests. The source-text assertions in test_startup_shell_session_loading.py are replaced by node-driven behavioural tests, per tests/TESTING_STANDARD.md. - Reverted the unrequested loader a11y rework, removed the duplicated inert writes (the module stops the wave interval through a callback), and moved the bootstrap row's inline styles into .session-list-bootstrap. * fix: preserve session bootstrap failure state --------- Co-authored-by: Léo <leograndcontact@gmail.com>
This commit is contained in:
+28
-19
@@ -15,6 +15,12 @@ import compareModule from './js/compare/index.js?v=20260723compareicon2';
|
||||
import documentModule from './js/document.js?v=20260722emailfastindex1';
|
||||
import searchChatModule from './js/search-chat.js';
|
||||
import { makeWindowDraggable } from './js/windowDrag.js';
|
||||
import {
|
||||
revealApplicationShellAfterPaint,
|
||||
runDeferredRouteOpener,
|
||||
deferRouteOpener,
|
||||
settleSessionHydration
|
||||
} from './js/startupShell.js';
|
||||
import markdownModule from './js/markdown.js';
|
||||
import chatRenderer from './js/chatRenderer.js?v=20260722emailfastindex1';
|
||||
import sessionModule from './js/sessions.js';
|
||||
@@ -1217,12 +1223,13 @@ function initializeEventListeners() {
|
||||
'/library': () => sessionModule && sessionModule.openLibrary && sessionModule.openLibrary(),
|
||||
};
|
||||
const _opener = _routeOpen[urlPath];
|
||||
// Defer the opener — at this point in init, the modules whose handlers
|
||||
// we trigger (#rail-new-session click handler, the email-section header
|
||||
// click handler in emailInbox, sessionModule's loaded session list) are
|
||||
// still being wired up further down in this same function. Stash the
|
||||
// opener so it runs from sessionModule.loadSessions().finally() below.
|
||||
if (_opener) window._odysseusRouteOpener = _opener;
|
||||
// Defer the opener — at this point in init, the modules whose handlers we
|
||||
// trigger (#rail-new-session click handler, the email-section header click
|
||||
// handler in emailInbox, sessionModule) are still being wired up further
|
||||
// down in this same function. startupShell decides when it can run: as soon
|
||||
// as wiring completes, or — for the routes that read the session list —
|
||||
// once /api/sessions has settled.
|
||||
deferRouteOpener(urlPath, _opener);
|
||||
|
||||
// Archive browser tool button
|
||||
const toolLibraryBtn = el('tool-library-btn');
|
||||
@@ -4315,6 +4322,10 @@ function startOdysseusApp() {
|
||||
// Load initial data
|
||||
presetsModule.loadPresets(uiModule.showError);
|
||||
|
||||
// Core wiring is complete for this turn — reveal the shell independently of
|
||||
// the session-list request.
|
||||
revealApplicationShellAfterPaint();
|
||||
|
||||
if (sessionModule) {
|
||||
sessionModule.initDependencies({
|
||||
API_BASE: API_BASE,
|
||||
@@ -4326,21 +4337,19 @@ function startOdysseusApp() {
|
||||
scrollHistory: uiModule.scrollHistoryInstant
|
||||
});
|
||||
|
||||
// Load sessions first (critical path) — remove loader when done
|
||||
sessionModule.loadSessions()
|
||||
.catch(e => console.warn('loadSessions error:', e))
|
||||
.finally(() => {
|
||||
const loader = document.getElementById('app-loader');
|
||||
if (loader) { loader.style.opacity = '0'; setTimeout(() => loader.remove(), 300); }
|
||||
// Fire any URL route opener now that sessions + module wiring are
|
||||
// ready. Deferred from up top of init for exactly this reason.
|
||||
if (window._odysseusRouteOpener) {
|
||||
try { window._odysseusRouteOpener(); } catch (_) {}
|
||||
window._odysseusRouteOpener = null;
|
||||
}
|
||||
});
|
||||
// sessionModule is now wired, so every route opener has the modules it
|
||||
// drives. The ones that read no session data open here rather than
|
||||
// queueing behind /api/sessions.
|
||||
runDeferredRouteOpener();
|
||||
|
||||
// The shell is already usable at this point; session hydration is
|
||||
// sidebar-local and settles on its own schedule.
|
||||
settleSessionHydration(() => sessionModule.loadSessions());
|
||||
} else {
|
||||
console.error('Session module not loaded!');
|
||||
// Nothing will hydrate. Settle immediately so the sidebar exposes the
|
||||
// failure; session-dependent routes must remain unopened without data.
|
||||
settleSessionHydration(null);
|
||||
}
|
||||
|
||||
const runNonCriticalStartup = (fn, delay = 4000) => {
|
||||
|
||||
Reference in New Issue
Block a user