This commit is contained in:
2026-04-20 15:32:19 +02:00
commit 0858b72e31
36 changed files with 6359 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type SplashOrder = { order: string, msg: string | null, status: string | null, };

View File

@@ -0,0 +1,52 @@
// file: kb_app/frontend/ts/main.ts
import * as bootstrap from "bootstrap";
import "simplebar";
import ResizeObserver from "resize-observer-polyfill";
//import { invoke } from "@tauri-apps/api/core";
//import { listen, type UnlistenFn } from "@tauri-apps/api/event";
//import { error } from "@fltsci/tauri-plugin-tracing";
//import { info } from "@fltsci/tauri-plugin-tracing";
import { trace } from "@fltsci/tauri-plugin-tracing";
(window as Window & typeof globalThis & { bootstrap?: typeof bootstrap }).bootstrap = bootstrap;
(window as Window & typeof globalThis & { ResizeObserver?: typeof ResizeObserver }).ResizeObserver = ResizeObserver;
document.addEventListener("DOMContentLoaded", () => {
const sidebarToggle = document.querySelector<HTMLButtonElement>('#sidebarToggle');
if (sidebarToggle) {
// restaurer létat depuis localStorage
if (localStorage.getItem('sidebar-toggle') === 'true') {
document.body.classList.add('sidenav-toggled');
}
sidebarToggle.addEventListener('click', (event) => {
event.preventDefault();
document.body.classList.toggle('sidenav-toggled');
localStorage.setItem('sidebar-toggle', document.body.classList.contains('sidenav-toggled') ? 'true' : 'false');
});
}
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
Array.from(tooltipTriggerList).map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
const toastElList = document.querySelectorAll('.toast');
Array.from(toastElList).map(toastEl => new bootstrap.Toast(toastEl));
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]');
Array.from(popoverTriggerList).map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl));
const gobackto = location.pathname + location.search;
document.querySelectorAll<HTMLAnchorElement>('a[data-setlang]').forEach((a) => {
const href = a.getAttribute("href");
if (!href) return; // pas de href => on ignore
const url = new URL(href, location.origin);
url.searchParams.set("gobackto", gobackto);
// conserve une URL relative (path + query)
a.setAttribute("href", url.pathname + "?" + url.searchParams.toString());
});
trace("window loaded");
});

View File

@@ -0,0 +1,96 @@
// file: kb_app/frontend/ts/splash.ts
import { error } from "@fltsci/tauri-plugin-tracing";
import { info } from "@fltsci/tauri-plugin-tracing";
import { listen } from '@tauri-apps/api/event';
import { SplashOrder } from './bindings/SplashOrder.ts';
// Fonction d'animation d'opacité
async function animateOpacity(
element: HTMLElement,
fromOpacity: number,
toOpacity: number,
durationMs: number
): Promise<void> {
console.log(`Animating from ${fromOpacity} to ${toOpacity} over ${durationMs}ms`);
//debug(`Animating from ${fromOpacity} to ${toOpacity} over ${durationMs}ms`);
return new Promise((resolve) => {
const startTime = performance.now();
const startOpacity = fromOpacity;
const changeOpacity = toOpacity - fromOpacity;
function update(currentTime: number) {
const elapsed = currentTime - startTime;
if (elapsed >= durationMs) {
element.style.opacity = toOpacity.toString();
resolve();
return;
}
const progress = elapsed / durationMs;
element.style.opacity = (startOpacity + changeOpacity * progress).toString();
requestAnimationFrame(update);
}
requestAnimationFrame(update);
});
}
// Journalisation
function addLogMessage(message: string): void {
console.log(`Splash: ${message}`);
const debugInfo = document.getElementById('debug-info');
if (debugInfo) {
const time = new Date().toLocaleTimeString();
let msg = `${time}: ${message}<br>`;
debugInfo.innerHTML += msg;
}
}
// Pour ajouter des messages directement (sans événements)
function addMessage(message: string, status: string): void {
const messagesContainer = document.getElementById('messages-container');
if (!messagesContainer) return;
const messageElement = document.createElement('div');
messageElement.className = `splash-message ${status}`;
messageElement.textContent = message;
messagesContainer.appendChild(messageElement);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
listen("splash", (event) => {
const splashorder = event.payload as SplashOrder;
if (splashorder.order == "fadein") {
const container = document.getElementById('splash-container');
if (container) {
animateOpacity(container, 0, 1, 3000);
} else {
error("no container");
}
} else if (splashorder.order == "fadeout") {
const container = document.getElementById('splash-container');
if (container) {
animateOpacity(container, 1, 0, 3000);
} else {
error("no container");
}
} else if (splashorder.order == "add_msg" && splashorder.msg && splashorder.status) {
addMessage(splashorder.msg, splashorder.status);
} else if (splashorder.order == "add_log" && splashorder.msg) {
addLogMessage(splashorder.msg);
} else {
error("unknown order:"+splashorder.order);
}
});
// Démarrer l'initialisation au chargement du DOM
//window.addEventListener('DOMContentLoaded', initialize);
document.addEventListener("DOMContentLoaded", () => {
info("window loaded");
});