feat(boot): écran de chargement inline + staging backend/frontend pour le bundle desktop
CI / lint (push) Failing after 16s
CI / test (push) Skipped
CI / build (push) Skipped
CI / e2e (push) Skipped
CI / security (push) Successful in 18s
Desktop Build / build-windows (push) Canceled after 0s
Desktop Build / build-linux (push) Canceled after 0s
CI / lint (push) Failing after 16s
CI / test (push) Skipped
CI / build (push) Skipped
CI / e2e (push) Skipped
CI / security (push) Successful in 18s
Desktop Build / build-windows (push) Canceled after 0s
Desktop Build / build-linux (push) Canceled after 0s
- frontend/index.html : splash #boot-splash 100% inline (CSS+JS), scripts CDN en defer pour ne pas bloquer le premier paint - frontend/js/app.js : signale le boot terminé via __OBSIGATE_BOOTED (try/finally) - desktop/src/main.rs : met à jour le statut du splash avant la redirection vers le backend - ci: stage backend/ + frontend/ sous desktop/ avant tauri build (resources backend/** et frontend/**) dans desktop-build.yml et build-linux.sh - desktop/gen/schemas/windows-schema.json : régénéré (permissions store/updater) - docs: README, README.fr, ROADMAP
This commit is contained in:
+69
-3
@@ -47,6 +47,33 @@
|
||||
href="/static/icons/icon-192x192.svg"
|
||||
/>
|
||||
|
||||
<!-- Boot splash CSS — inline so it applies BEFORE /static/style.css is
|
||||
available (desktop: embedded page served from tauri:// has no /static) -->
|
||||
<style id="boot-splash-css">
|
||||
body:not(.app-booted) > *:not(#boot-splash) { display: none !important; }
|
||||
#boot-splash {
|
||||
position: fixed; inset: 0; z-index: 2147483647;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
background: radial-gradient(1200px 600px at 50% -10%, #1b2030 0%, #0e1117 60%);
|
||||
color: #e6e8ee; font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
|
||||
}
|
||||
body.app-booted #boot-splash { display: none; }
|
||||
.bs-card { display: flex; flex-direction: column; align-items: center; gap: 14px; }
|
||||
.bs-logo {
|
||||
width: 72px; height: 72px; display: flex; align-items: center; justify-content: center;
|
||||
font-size: 38px; background: #171c26; border: 1px solid #2a3242; border-radius: 18px;
|
||||
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
.bs-title { font-size: 22px; font-weight: 600; letter-spacing: 0.3px; }
|
||||
.bs-spinner {
|
||||
width: 34px; height: 34px; border-radius: 50%;
|
||||
border: 3px solid rgba(124, 58, 237, 0.25); border-top-color: #7c3aed;
|
||||
animation: bs-spin 0.9s linear infinite;
|
||||
}
|
||||
@keyframes bs-spin { to { transform: rotate(360deg); } }
|
||||
.bs-status { font-size: 13px; color: #9aa3b2; min-height: 18px; }
|
||||
@media (prefers-reduced-motion: reduce) { .bs-spinner { animation-duration: 1.8s; } }
|
||||
</style>
|
||||
<link rel="stylesheet" href="/static/style.css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
@@ -59,9 +86,10 @@
|
||||
id="hljs-theme-light"
|
||||
disabled
|
||||
/>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
||||
<script src="https://unpkg.com/[email protected]/dist/umd/lucide.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
|
||||
<!-- defer: ne bloque pas le premier paint (le splash inline s'affiche immédiatement) -->
|
||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
||||
<script defer src="https://unpkg.com/[email protected]/dist/umd/lucide.min.js"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
@@ -172,6 +200,44 @@
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Boot splash : visible tant que l'app n'a pas booté avec son CSS.
|
||||
Sur desktop, la page embarquée (tauri://) n'a pas /static/style.css →
|
||||
sans ce splash, le squelette HTML brut serait visible pendant le
|
||||
démarrage du backend (FOUC 3-10 s). Styles 100% inline. -->
|
||||
<div id="boot-splash" role="status" aria-live="polite">
|
||||
<div class="bs-card">
|
||||
<div class="bs-logo">📖</div>
|
||||
<div class="bs-title">ObsiGate</div>
|
||||
<div class="bs-spinner" aria-hidden="true"></div>
|
||||
<div class="bs-status" id="boot-splash-status">Démarrage…</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
(function () {
|
||||
var done = false;
|
||||
function bootReady() {
|
||||
if (done) return;
|
||||
done = true;
|
||||
document.body.classList.add("app-booted");
|
||||
var s = document.getElementById("boot-splash");
|
||||
if (s && s.parentNode) s.parentNode.removeChild(s);
|
||||
}
|
||||
window.__obsigateBootReady = bootReady;
|
||||
window.__setBootStatus = function (txt) {
|
||||
var el = document.getElementById("boot-splash-status");
|
||||
if (el) el.textContent = txt;
|
||||
};
|
||||
var poll = setInterval(function () {
|
||||
if (window.__OBSIGATE_BOOTED) { clearInterval(poll); bootReady(); }
|
||||
}, 80);
|
||||
// Filet de sécurité : si le CSS principal a chargé (origine backend réelle)
|
||||
// mais que le JS a échoué, révéler l'app après 10 s au lieu d'un splash infini.
|
||||
setTimeout(function () {
|
||||
var link = document.querySelector('link[href*="style.css"]');
|
||||
if (link && link.sheet) { clearInterval(poll); bootReady(); }
|
||||
}, 10000);
|
||||
})();
|
||||
</script>
|
||||
<div class="search-progress-bar" id="search-progress-bar">
|
||||
<div class="search-progress-bar__fill"></div>
|
||||
</div>
|
||||
|
||||
+9
-2
@@ -102,8 +102,15 @@ async function init() {
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
init();
|
||||
Sync.init();
|
||||
try {
|
||||
init();
|
||||
Sync.init();
|
||||
} finally {
|
||||
// Signale au splash de démarrage (index.html #boot-splash) que l'app est
|
||||
// initialisée : le splash est retiré et le squelette stylé révélé.
|
||||
window.__OBSIGATE_BOOTED = true;
|
||||
if (typeof window.__obsigateBootReady === "function") window.__obsigateBootReady();
|
||||
}
|
||||
// Show version in header
|
||||
fetch('/api/health')
|
||||
.then(r => r.json())
|
||||
|
||||
Reference in New Issue
Block a user