aboutsummaryrefslogtreecommitdiff
path: root/modules/core/module-loader.js
blob: 74e3a864a3e9c205c392c06da6b9d88bc5db9174 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
(function() {
    'use strict';

    // Core module bundle loaded synchronously in main.html.
    // This loader only handles version cache-busting, splash, terminal init, and optional ext modules.

    const LATEST_VER = 'v4.6.81';
    const CACHE = '?v=' + LATEST_VER;
    const stored = localStorage.getItem('webx11_cache_ver');
    if (stored !== LATEST_VER) {
        localStorage.setItem('webx11_cache_ver', LATEST_VER);
    }

    function setSplash(phase, current, total, filename) {
        const fill = document.getElementById('splash-progress-fill');
        const phaseEl = document.getElementById('splash-phase');
        const fileEl = document.getElementById('splash-filename');
        if (fill && total > 0) {
            fill.style.width = Math.round((current / total) * 100) + '%';
        }
        if (phaseEl) phaseEl.textContent = phase;
        if (fileEl) fileEl.textContent = filename || '';
    }

    function hideSplash() {
        const overlay = document.getElementById('splash-overlay');
        if (overlay) {
            overlay.classList.add('hidden');
            setTimeout(() => { overlay.style.display = 'none'; }, 350);
        }
    }

    function showSplashError(msg) {
        const el = document.getElementById('splash-error');
        const fill = document.getElementById('splash-progress-fill');
        if (el) { el.textContent = msg; el.classList.add('show'); }
        if (fill) fill.style.background = 'var(--error-color)';
    }

    // Create webx11 synchronously so critical-ext-bundle.js (loaded right after us)
    // can call registerModule() without waiting for DOMContentLoaded
    const webx11 = new WebX11Terminal();
    window.webx11 = webx11;

    async function init() {
        try {
            const total = 3;
            let count = 0;

            setSplash('Core bundle loaded (1/3)', ++count, total, 'core-bundle.js');
            setSplash('Critical ext bundle loaded (2/3)', ++count, total, 'critical-ext-bundle.js');

            setSplash('Initializing terminal (3/3)', total, total, '');
            // webx11 already created synchronously above — just init ext modules
            if (typeof webx11._loadExtModules === 'function') {
                let extKeys = ['calc', 'voice', 'debug-panel', 'cron', 'theme', 'wpm', 'mindmap', 'webdav', 'skill-pack-core', 'cryptogzip', 'tutorial', 'floating', 'console', 'media', 'three', 'kanban', 'course'];
                const saved = localStorage.getItem('webx11_startup_modules');
                let selected = null;
                try { if (saved) selected = JSON.parse(saved); } catch (e) {}
                if (selected && Array.isArray(selected)) {
                    extKeys = extKeys.filter(k => selected.includes(k + '.js'));
                }
                let disabledMods = [];
                try { disabledMods = JSON.parse(localStorage.getItem('webx11_module_disabled') || '[]'); } catch (e) {}
                extKeys = extKeys.filter(k => !disabledMods.includes(k));
                if (extKeys.length > 0) {
                    setTimeout(() => webx11._loadExtModules(extKeys), 800);
                }
            }

            hideSplash();
            console.log('[ModuleLoader] Core loader initialized');
        } catch (err) {
            console.error('[ModuleLoader] Fatal error:', err);
            showSplashError('Loading failed — ' + err.message);
        }
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();