From fd41175ad82e1b761794db7e731d5073580dcea1 Mon Sep 17 00:00:00 2001 From: bruno Date: Sun, 26 Jul 2026 11:06:53 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20revue=20compl=C3=A8te=20obsigate-desktop?= =?UTF-8?q?=20=E2=80=94=206=20correctifs=20pour=20le=20prochain=20build?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. main.rs: .current_dir(exe_dir) pour que Python trouve backend/ (pas le cwd hérité) 2. build-windows.bat: dir bundles pointe vers target/x86_64-.../release (était target/release) 3. build-windows.bat: supprimer étape 3 inutile (frontend-static) — Tauri utilise ../frontend 4. capabilities/default.json: requis par Tauri v2 (permissions plugins) 5. tauri.conf.json + Cargo.toml: retirer updater (placeholder sans clé) 6. .gitignore: ajouter desktop/target/, python-embed/, frontend-static/ 7. build-linux.sh: mêmes corrections (bundles path, simplification) --- .gitignore | 6 + desktop/Cargo.toml | 1 - desktop/build-linux.sh | 30 +- desktop/build-windows.bat | 40 +- desktop/capabilities/default.json | 14 + desktop/frontend-static/app.js | 8905 ----------------- desktop/frontend-static/editor-poc.html | 1998 ---- desktop/frontend-static/icons/README.md | 42 - .../frontend-static/icons/icon-128x128.svg | 27 - .../frontend-static/icons/icon-144x144.svg | 27 - .../frontend-static/icons/icon-152x152.svg | 27 - .../icons/icon-192x192-maskable.svg | 27 - .../frontend-static/icons/icon-192x192.svg | 27 - .../frontend-static/icons/icon-384x384.svg | 27 - .../icons/icon-512x512-maskable.svg | 27 - .../frontend-static/icons/icon-512x512.svg | 27 - desktop/frontend-static/icons/icon-72x72.svg | 27 - desktop/frontend-static/icons/icon-96x96.svg | 27 - .../frontend-static/icons/search-96x96.svg | 18 - desktop/frontend-static/index.html | 4827 --------- desktop/frontend-static/js/ai.js | 457 - desktop/frontend-static/js/app.js | 107 - desktop/frontend-static/js/auth.js | 579 -- desktop/frontend-static/js/autocomplete.js | 350 - desktop/frontend-static/js/backup-manager.js | 324 - desktop/frontend-static/js/backups.js | 501 - desktop/frontend-static/js/config.js | 1570 --- desktop/frontend-static/js/dashboard.js | 484 - desktop/frontend-static/js/dragdrop.js | 329 - desktop/frontend-static/js/graph.js | 949 -- desktop/frontend-static/js/i18n.js | 193 - desktop/frontend-static/js/legacy.js | 417 - desktop/frontend-static/js/mermaid-viewer.js | 845 -- desktop/frontend-static/js/mobile-toolbar.js | 149 - desktop/frontend-static/js/offline-db.js | 377 - desktop/frontend-static/js/offline.js | 209 - desktop/frontend-static/js/package.json | 1 - desktop/frontend-static/js/palette.js | 590 -- desktop/frontend-static/js/pane-manager.js | 263 - desktop/frontend-static/js/search.js | 1154 --- desktop/frontend-static/js/sidebar.js | 1124 --- desktop/frontend-static/js/sidebar_raw.js | 1087 -- desktop/frontend-static/js/state.js | 59 - desktop/frontend-static/js/sync.js | 643 -- desktop/frontend-static/js/themes.js | 566 -- desktop/frontend-static/js/ui.js | 2351 ----- desktop/frontend-static/js/utils.js | 679 -- desktop/frontend-static/js/vaulthome.js | 384 - desktop/frontend-static/js/viewer.js | 1550 --- desktop/frontend-static/locales/en.json | 1499 --- desktop/frontend-static/locales/fr.json | 1499 --- desktop/frontend-static/manifest.json | 89 - desktop/frontend-static/popout.html | 1635 --- desktop/frontend-static/style.css | 8573 ---------------- desktop/frontend-static/sw.js | 197 - desktop/python-embed/LICENSE.txt | 702 -- desktop/python-embed/_asyncio.pyd | Bin 65304 -> 0 bytes desktop/python-embed/_bz2.pyd | Bin 84760 -> 0 bytes desktop/python-embed/_ctypes.pyd | Bin 124696 -> 0 bytes desktop/python-embed/_decimal.pyd | Bin 255768 -> 0 bytes desktop/python-embed/_elementtree.pyd | Bin 128792 -> 0 bytes desktop/python-embed/_hashlib.pyd | Bin 65304 -> 0 bytes desktop/python-embed/_lzma.pyd | Bin 159512 -> 0 bytes desktop/python-embed/_msi.pyd | Bin 44824 -> 0 bytes desktop/python-embed/_multiprocessing.pyd | Bin 34584 -> 0 bytes desktop/python-embed/_overlapped.pyd | Bin 51480 -> 0 bytes desktop/python-embed/_queue.pyd | Bin 32024 -> 0 bytes desktop/python-embed/_socket.pyd | Bin 79640 -> 0 bytes desktop/python-embed/_sqlite3.pyd | Bin 120600 -> 0 bytes desktop/python-embed/_ssl.pyd | Bin 178456 -> 0 bytes desktop/python-embed/_uuid.pyd | Bin 25368 -> 0 bytes desktop/python-embed/_zoneinfo.pyd | Bin 45848 -> 0 bytes desktop/python-embed/libcrypto-3.dll | Bin 5191960 -> 0 bytes desktop/python-embed/libffi-8.dll | Bin 39696 -> 0 bytes desktop/python-embed/libssl-3.dll | Bin 787224 -> 0 bytes desktop/python-embed/pyexpat.pyd | Bin 199448 -> 0 bytes desktop/python-embed/python.cat | Bin 643161 -> 0 bytes desktop/python-embed/python.exe | Bin 103192 -> 0 bytes desktop/python-embed/python3.dll | Bin 67352 -> 0 bytes desktop/python-embed/python311._pth | 2 - desktop/python-embed/python311.dll | Bin 5800216 -> 0 bytes desktop/python-embed/python311.zip | Bin 4285636 -> 0 bytes desktop/python-embed/pythonw.exe | Bin 101656 -> 0 bytes desktop/python-embed/select.pyd | Bin 30488 -> 0 bytes desktop/python-embed/sidecar.py | 72 - desktop/python-embed/sqlite3.dll | Bin 1540888 -> 0 bytes desktop/python-embed/unicodedata.pyd | Bin 1140504 -> 0 bytes desktop/python-embed/vcruntime140.dll | Bin 119192 -> 0 bytes desktop/python-embed/vcruntime140_1.dll | Bin 49528 -> 0 bytes desktop/python-embed/winsound.pyd | Bin 31512 -> 0 bytes desktop/src/main.rs | 3 +- desktop/tauri.conf.json | 6 - 92 files changed, 46 insertions(+), 48673 deletions(-) create mode 100644 desktop/capabilities/default.json delete mode 100644 desktop/frontend-static/app.js delete mode 100644 desktop/frontend-static/editor-poc.html delete mode 100644 desktop/frontend-static/icons/README.md delete mode 100644 desktop/frontend-static/icons/icon-128x128.svg delete mode 100644 desktop/frontend-static/icons/icon-144x144.svg delete mode 100644 desktop/frontend-static/icons/icon-152x152.svg delete mode 100644 desktop/frontend-static/icons/icon-192x192-maskable.svg delete mode 100644 desktop/frontend-static/icons/icon-192x192.svg delete mode 100644 desktop/frontend-static/icons/icon-384x384.svg delete mode 100644 desktop/frontend-static/icons/icon-512x512-maskable.svg delete mode 100644 desktop/frontend-static/icons/icon-512x512.svg delete mode 100644 desktop/frontend-static/icons/icon-72x72.svg delete mode 100644 desktop/frontend-static/icons/icon-96x96.svg delete mode 100644 desktop/frontend-static/icons/search-96x96.svg delete mode 100644 desktop/frontend-static/index.html delete mode 100644 desktop/frontend-static/js/ai.js delete mode 100644 desktop/frontend-static/js/app.js delete mode 100644 desktop/frontend-static/js/auth.js delete mode 100644 desktop/frontend-static/js/autocomplete.js delete mode 100644 desktop/frontend-static/js/backup-manager.js delete mode 100644 desktop/frontend-static/js/backups.js delete mode 100644 desktop/frontend-static/js/config.js delete mode 100644 desktop/frontend-static/js/dashboard.js delete mode 100644 desktop/frontend-static/js/dragdrop.js delete mode 100644 desktop/frontend-static/js/graph.js delete mode 100644 desktop/frontend-static/js/i18n.js delete mode 100644 desktop/frontend-static/js/legacy.js delete mode 100644 desktop/frontend-static/js/mermaid-viewer.js delete mode 100644 desktop/frontend-static/js/mobile-toolbar.js delete mode 100644 desktop/frontend-static/js/offline-db.js delete mode 100644 desktop/frontend-static/js/offline.js delete mode 100644 desktop/frontend-static/js/package.json delete mode 100644 desktop/frontend-static/js/palette.js delete mode 100644 desktop/frontend-static/js/pane-manager.js delete mode 100644 desktop/frontend-static/js/search.js delete mode 100644 desktop/frontend-static/js/sidebar.js delete mode 100644 desktop/frontend-static/js/sidebar_raw.js delete mode 100644 desktop/frontend-static/js/state.js delete mode 100644 desktop/frontend-static/js/sync.js delete mode 100644 desktop/frontend-static/js/themes.js delete mode 100644 desktop/frontend-static/js/ui.js delete mode 100644 desktop/frontend-static/js/utils.js delete mode 100644 desktop/frontend-static/js/vaulthome.js delete mode 100644 desktop/frontend-static/js/viewer.js delete mode 100644 desktop/frontend-static/locales/en.json delete mode 100644 desktop/frontend-static/locales/fr.json delete mode 100644 desktop/frontend-static/manifest.json delete mode 100644 desktop/frontend-static/popout.html delete mode 100644 desktop/frontend-static/style.css delete mode 100644 desktop/frontend-static/sw.js delete mode 100644 desktop/python-embed/LICENSE.txt delete mode 100644 desktop/python-embed/_asyncio.pyd delete mode 100644 desktop/python-embed/_bz2.pyd delete mode 100644 desktop/python-embed/_ctypes.pyd delete mode 100644 desktop/python-embed/_decimal.pyd delete mode 100644 desktop/python-embed/_elementtree.pyd delete mode 100644 desktop/python-embed/_hashlib.pyd delete mode 100644 desktop/python-embed/_lzma.pyd delete mode 100644 desktop/python-embed/_msi.pyd delete mode 100644 desktop/python-embed/_multiprocessing.pyd delete mode 100644 desktop/python-embed/_overlapped.pyd delete mode 100644 desktop/python-embed/_queue.pyd delete mode 100644 desktop/python-embed/_socket.pyd delete mode 100644 desktop/python-embed/_sqlite3.pyd delete mode 100644 desktop/python-embed/_ssl.pyd delete mode 100644 desktop/python-embed/_uuid.pyd delete mode 100644 desktop/python-embed/_zoneinfo.pyd delete mode 100644 desktop/python-embed/libcrypto-3.dll delete mode 100644 desktop/python-embed/libffi-8.dll delete mode 100644 desktop/python-embed/libssl-3.dll delete mode 100644 desktop/python-embed/pyexpat.pyd delete mode 100644 desktop/python-embed/python.cat delete mode 100644 desktop/python-embed/python.exe delete mode 100644 desktop/python-embed/python3.dll delete mode 100644 desktop/python-embed/python311._pth delete mode 100644 desktop/python-embed/python311.dll delete mode 100644 desktop/python-embed/python311.zip delete mode 100644 desktop/python-embed/pythonw.exe delete mode 100644 desktop/python-embed/select.pyd delete mode 100644 desktop/python-embed/sidecar.py delete mode 100644 desktop/python-embed/sqlite3.dll delete mode 100644 desktop/python-embed/unicodedata.pyd delete mode 100644 desktop/python-embed/vcruntime140.dll delete mode 100644 desktop/python-embed/vcruntime140_1.dll delete mode 100644 desktop/python-embed/winsound.pyd diff --git a/.gitignore b/.gitignore index 253adc3..4775b35 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,9 @@ odysseus/ node_modules/ test-results/ playwright-report/ + +# Desktop build artifacts +desktop/target/ +desktop/python-embed/ +desktop/frontend-static/ + diff --git a/desktop/Cargo.toml b/desktop/Cargo.toml index 6eb7fa6..98a1b53 100644 --- a/desktop/Cargo.toml +++ b/desktop/Cargo.toml @@ -15,7 +15,6 @@ tauri-plugin-dialog = "2" tauri-plugin-notification = "2" tauri-plugin-fs = "2" tauri-plugin-process = "2" -tauri-plugin-updater = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" reqwest = { version = "0.12", features = ["json"] } diff --git a/desktop/build-linux.sh b/desktop/build-linux.sh index 3871116..1ca9dea 100755 --- a/desktop/build-linux.sh +++ b/desktop/build-linux.sh @@ -11,7 +11,7 @@ echo "========================================" echo "" # ── 1. Vérifier les prérequis ───────────────────────────────── -echo "[1/6] Verifying prerequisites..." +echo "[1/4] Verifying prerequisites..." command -v cargo >/dev/null 2>&1 || { echo "❌ Rust/Cargo not found. Install: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"; exit 1; } command -v tauri >/dev/null 2>&1 || cargo install tauri-cli @@ -22,32 +22,22 @@ fi echo "✅ Dependencies OK" # ── 2. Préparer Python 3.11 ──────────────────────────────────── -echo "[2/6] Preparing Python environment..." +echo "[2/4] Preparing Python environment..." python3 -m venv python-embed/venv source python-embed/venv/bin/activate pip install --upgrade pip -q pip install -r ../backend/requirements.txt -q echo "✅ Python environment ready" -# ── 3. Copier le frontend ───────────────────────────────────── -echo "[3/6] Copying frontend..." -rm -rf frontend-static -cp -r ../frontend frontend-static -echo "✅ Frontend copied" - -# ── 4. Icônes ────────────────────────────────────────────────── -echo "[4/6] Generating icons..." -# Placeholder — tauri icon generator -echo "✅ Icons OK" - -# ── 5. Build Tauri ──────────────────────────────────────────── -echo "[5/6] Building Tauri application..." +# ── 3. Build Tauri ──────────────────────────────────────────── +echo "[3/4] Building Tauri application..." cargo tauri build --target x86_64-unknown-linux-gnu --bundles deb,appimage echo "✅ Build successful" -# ── 6. Résultats ─────────────────────────────────────────────── -echo "[6/6] Results:" -ls -lh target/release/bundle/deb/*.deb 2>/dev/null -ls -lh target/release/bundle/appimage/*.AppImage 2>/dev/null +# ── 4. Résultats ─────────────────────────────────────────────── +OUTDIR="target/x86_64-unknown-linux-gnu/release" +echo "[4/4] Results:" +ls -lh "$OUTDIR/bundle/deb/"*.deb 2>/dev/null +ls -lh "$OUTDIR/bundle/appimage/"*.AppImage 2>/dev/null echo "" -echo "✅ Done! Check target/release/bundle/" +echo "✅ Done! Check $OUTDIR/bundle/" diff --git a/desktop/build-windows.bat b/desktop/build-windows.bat index 1a61675..ed34ecb 100644 --- a/desktop/build-windows.bat +++ b/desktop/build-windows.bat @@ -11,41 +11,30 @@ echo ======================================== echo. REM ── 1. Vérifier les prérequis ───────────────────────────────── -echo [1/6] Verifying prerequisites... +echo [1/5] Verifying prerequisites... where cargo >nul 2>&1 || (echo ❌ Rust/Cargo not found. Install from https://rustup.rs & exit /b 1) where tauri >nul 2>&1 || cargo install tauri-cli echo ✅ Rust + Tauri OK REM ── 2. Préparer Python 3.11 embed ───────────────────────────── -echo [2/6] Preparing Python embed... +echo [2/5] Preparing Python embed... if not exist "python-embed\python.exe" ( echo 📥 Downloading Python 3.11 embed... if exist "python-embed" rmdir /s /q "python-embed" curl -L -o python-embed.zip "https://www.python.org/ftp/python/3.11.9/python-3.11.9-embed-amd64.zip" powershell Expand-Archive -Path python-embed.zip -DestinationPath python-embed\ del python-embed.zip - + REM Enable pip in embedded Python echo import site >> python-embed\python311._pth - + REM Install dependencies python-embed\python.exe -m pip install --no-cache-dir -r ..\backend\requirements.txt ) echo ✅ Python embed ready -REM ── 3. Copier le frontend ───────────────────────────────────── -echo [3/6] Copying frontend... -if exist "frontend-static" rmdir /s /q "frontend-static" -xcopy /E /I /Q "..\frontend" "frontend-static" -echo ✅ Frontend copied - -REM ── 4. Mettre à jour les icônes ─────────────────────────────── -echo [4/6] Generating icons... -REM Placeholder — will use tauri icon generator when icons are ready -echo ✅ Icons OK (using defaults) - -REM ── 5. Build Tauri ──────────────────────────────────────────── -echo [5/6] Building Tauri application... +REM ── 3. Build Tauri ──────────────────────────────────────────── +echo [3/5] Building Tauri application... cargo tauri build --target x86_64-pc-windows-msvc --bundles msi,nsis if errorlevel 1 ( echo ❌ Build failed! @@ -53,20 +42,19 @@ if errorlevel 1 ( ) echo ✅ Build successful -REM ── 5b. Copier python-embed à côté de l'exécutable pour le dev ───── -echo [5b/6] Copying python-embed to output dir... +REM ── 4. Copier le runtime à côté de l'exécutable ─────────────── +echo [4/5] Copying runtime to output dir... set "OUTDIR=target\x86_64-pc-windows-msvc\release" if exist "%OUTDIR%\python-embed" rmdir /s /q "%OUTDIR%\python-embed" +if exist "%OUTDIR%\backend" rmdir /s /q "%OUTDIR%\backend" xcopy /E /I /Q "python-embed" "%OUTDIR%\python-embed" -REM Copier aussi le backend Python -if not exist "%OUTDIR%\backend" mkdir "%OUTDIR%\backend" xcopy /E /I /Q "..\backend" "%OUTDIR%\backend" echo ✅ Runtime copied -REM ── 6. Résultats ─────────────────────────────────────────────────── -echo [6/6] Results: -dir /b target\release\bundle\msi\*.msi 2>nul -dir /b target\release\bundle\nsis\*.exe 2>nul +REM ── 5. Résultats ─────────────────────────────────────────────── +echo [5/5] Results: +dir /b "%OUTDIR%\bundle\msi\*.msi" 2>nul +dir /b "%OUTDIR%\bundle\nsis\*.exe" 2>nul echo. -echo ✅ Done! Check target\release\bundle\ +echo ✅ Done! Check %OUTDIR%\bundle\ endlocal diff --git a/desktop/capabilities/default.json b/desktop/capabilities/default.json new file mode 100644 index 0000000..34c5404 --- /dev/null +++ b/desktop/capabilities/default.json @@ -0,0 +1,14 @@ +{ + "identifier": "default", + "description": "Default capabilities for ObsiGate Desktop", + "windows": ["main"], + "permissions": [ + "core:default", + "shell:allow-open", + "shell:allow-execute", + "dialog:default", + "notification:default", + "fs:default", + "process:default" + ] +} diff --git a/desktop/frontend-static/app.js b/desktop/frontend-static/app.js deleted file mode 100644 index 6a51793..0000000 --- a/desktop/frontend-static/app.js +++ /dev/null @@ -1,8905 +0,0 @@ -/* ObsiGate — Vanilla JS SPA */ - -(function () { - "use strict"; - - const APP_VERSION = "1.5.0"; - - // --------------------------------------------------------------------------- - // State - // --------------------------------------------------------------------------- - let currentVault = null; - let currentPath = null; - let searchTimeout = null; - let searchAbortController = null; - let showingSource = false; - let cachedRawSource = null; - let allVaults = []; - let selectedContextVault = "all"; - let selectedTags = []; - let editorView = null; - let editorVault = null; - let editorPath = null; - let fallbackEditorEl = null; - let sidebarFilterCaseSensitive = false; - let searchCaseSensitive = false; - let searchWholeWord = false; - let searchRegex = false; - let searchFilterVisible = false; - let _iconDebounceTimer = null; - let activeSidebarTab = "vaults"; - let filterDebounce = null; - - // Vault settings cache for hideHiddenFiles - let vaultSettings = {}; - - // Advanced search state - let advancedSearchOffset = 0; - let advancedSearchTotal = 0; - let advancedSearchSort = "relevance"; - let advancedSearchLastQuery = ""; - let suggestAbortController = null; - let dropdownActiveIndex = -1; - let dropdownItems = []; - let currentSearchId = 0; - - // Advanced search constants - const SEARCH_HISTORY_KEY = "obsigate_search_history"; - const MAX_HISTORY_ENTRIES = 50; - const SUGGEST_DEBOUNCE_MS = 150; - const ADVANCED_SEARCH_LIMIT = 50; - const MIN_SEARCH_LENGTH = 2; - const SEARCH_TIMEOUT_MS = 30000; - - // Outline/TOC state - let outlineObserver = null; - let activeHeadingId = null; - let headingsCache = []; - let rightSidebarVisible = false; - let rightSidebarWidth = 280; - - // --------------------------------------------------------------------------- - // File extension → Lucide icon mapping - // --------------------------------------------------------------------------- - const EXT_ICONS = { - // Text files - ".md": "file-text", - ".txt": "file-text", - ".log": "file-text", - ".readme": "file-text", - ".rst": "file-text", - ".adoc": "file-text", - - // Web development - ".html": "file-code", - ".htm": "file-code", - ".css": "file-code", - ".scss": "file-code", - ".sass": "file-code", - ".less": "file-code", - ".js": "file-code", - ".jsx": "file-code", - ".ts": "file-code", - ".tsx": "file-code", - ".vue": "file-code", - ".svelte": "file-code", - - // Programming languages - ".py": "file-code", - ".java": "file-code", - ".c": "file-code", - ".cpp": "file-code", - ".cc": "file-code", - ".cxx": "file-code", - ".h": "file-code", - ".hpp": "file-code", - ".cs": "file-code", - ".go": "file-code", - ".rs": "file-code", - ".rb": "file-code", - ".php": "file-code", - ".swift": "file-code", - ".kt": "file-code", - ".scala": "file-code", - ".r": "file-code", - ".m": "file-code", - ".pl": "file-code", - ".lua": "file-code", - ".dart": "file-code", - ".nim": "file-code", - ".zig": "file-code", - ".odin": "file-code", - ".v": "file-code", - ".cr": "file-code", - ".ex": "file-code", - ".exs": "file-code", - ".elm": "file-code", - ".purs": "file-code", - ".hs": "file-code", - ".ml": "file-code", - ".ocaml": "file-code", - ".fs": "file-code", - ".fsx": "file-code", - ".vb": "file-code", - ".pas": "file-code", - ".pp": "file-code", - ".inc": "file-code", - - // Data formats - ".json": "file-json", - ".yaml": "file-cog", - ".yml": "file-cog", - ".toml": "file-cog", - ".xml": "file-code", - ".csv": "table", - ".tsv": "table", - ".sql": "database", - ".db": "database", - ".sqlite": "database", - ".sqlite3": "database", - ".parquet": "database", - ".avro": "database", - - // Configuration files - ".ini": "file-cog", - ".cfg": "file-cog", - ".conf": "file-cog", - ".env": "file-cog", - ".dockerfile": "file-cog", - ".gitignore": "file-cog", - ".gitattributes": "file-cog", - ".editorconfig": "file-cog", - ".eslintrc": "file-cog", - ".prettierrc": "file-cog", - ".babelrc": "file-cog", - ".tsconfig": "file-cog", - "package.json": "file-cog", - "package-lock.json": "file-cog", - "yarn.lock": "file-cog", - "composer.json": "file-cog", - "requirements.txt": "file-cog", - "pipfile": "file-cog", - "gemfile": "file-cog", - "cargo.toml": "file-cog", - "go.mod": "file-cog", - "go.sum": "file-cog", - "pom.xml": "file-cog", - "build.gradle": "file-cog", - "cmakelists.txt": "file-cog", - "makefile": "file-cog", - - // Shell scripts - ".sh": "terminal", - ".bash": "terminal", - ".zsh": "terminal", - ".fish": "terminal", - ".bat": "terminal", - ".cmd": "terminal", - ".ps1": "terminal", - ".psm1": "terminal", - ".psd1": "terminal", - - // Document formats - ".pdf": "file-text", - ".doc": "file-text", - ".docx": "file-text", - ".rtf": "file-text", - ".odt": "file-text", - ".tex": "file-text", - ".latex": "file-text", - - // Image files - ".png": "file-image", - ".jpg": "file-image", - ".jpeg": "file-image", - ".gif": "file-image", - ".svg": "file-image", - ".webp": "file-image", - ".bmp": "file-image", - ".ico": "file-image", - ".tiff": "file-image", - ".tif": "file-image", - - // Audio files - ".mp3": "file-music", - ".wav": "file-music", - ".flac": "file-music", - ".aac": "file-music", - ".ogg": "file-music", - ".m4a": "file-music", - ".wma": "file-music", - - // Video files - ".mp4": "play", - ".avi": "play", - ".mov": "play", - ".wmv": "play", - ".flv": "play", - ".webm": "play", - ".mkv": "play", - ".m4v": "play", - ".3gp": "play", - - // Archive files - ".zip": "file-archive", - ".rar": "file-archive", - ".7z": "file-archive", - ".tar": "file-archive", - ".gz": "file-archive", - ".tgz": "file-archive", - ".bz2": "file-archive", - ".xz": "file-archive", - ".deb": "file-archive", - ".rpm": "file-archive", - ".dmg": "file-archive", - ".pkg": "file-archive", - ".msi": "file-archive", - ".exe": "file-archive", - - // Font files - ".ttf": "file-type", - ".otf": "file-type", - ".woff": "file-type", - ".woff2": "file-type", - ".eot": "file-type", - - // Other common files - ".key": "file-cog", - ".pem": "file-cog", - ".crt": "file-cog", - ".cert": "file-cog", - ".p12": "file-cog", - ".pfx": "file-cog", - ".lock": "file-cog", - ".tmp": "file", - ".bak": "file", - ".old": "file", - ".orig": "file", - ".save": "file", - }; - - function getFileIcon(name) { - const ext = "." + name.split(".").pop().toLowerCase(); - return EXT_ICONS[ext] || "file"; - } - - // --------------------------------------------------------------------------- - // Search History Service (localStorage, LIFO, max 50, dedup) - // --------------------------------------------------------------------------- - const SearchHistory = { - _load() { - try { - const raw = localStorage.getItem(SEARCH_HISTORY_KEY); - return raw ? JSON.parse(raw) : []; - } catch { - return []; - } - }, - _save(entries) { - try { - localStorage.setItem(SEARCH_HISTORY_KEY, JSON.stringify(entries)); - } catch {} - }, - getAll() { - return this._load(); - }, - add(query) { - if (!query || !query.trim()) return; - const q = query.trim(); - let entries = this._load().filter((e) => e !== q); - entries.unshift(q); - if (entries.length > MAX_HISTORY_ENTRIES) entries = entries.slice(0, MAX_HISTORY_ENTRIES); - this._save(entries); - }, - remove(query) { - const entries = this._load().filter((e) => e !== query); - this._save(entries); - }, - clear() { - this._save([]); - }, - filter(prefix) { - if (!prefix) return this.getAll().slice(0, 8); - const lp = prefix.toLowerCase(); - return this._load() - .filter((e) => e.toLowerCase().includes(lp)) - .slice(0, 8); - }, - }; - - // --------------------------------------------------------------------------- - // Query Parser — extracts operators (tag:, #, vault:, title:, path:, ext:) - // --------------------------------------------------------------------------- - const QueryParser = { - parse(raw) { - const result = { tags: [], vault: null, title: null, path: null, ext: null, freeText: "" }; - if (!raw) return result; - const tokens = this._tokenize(raw); - const freeTokens = []; - for (const tok of tokens) { - const lower = tok.toLowerCase(); - if (lower.startsWith("tag:")) { - const v = tok.slice(4).replace(/"/g, "").trim().replace(/^#/, ""); - if (v) result.tags.push(v); - } else if (lower.startsWith("#") && tok.length > 1) { - result.tags.push(tok.slice(1)); - } else if (lower.startsWith("vault:")) { - result.vault = tok.slice(6).replace(/"/g, "").trim(); - } else if (lower.startsWith("title:")) { - result.title = tok.slice(6).replace(/"/g, "").trim(); - } else if (lower.startsWith("path:")) { - result.path = tok.slice(5).replace(/"/g, "").trim(); - } else if (lower.startsWith("ext:")) { - result.ext = tok.slice(4).replace(/"/g, "").trim().replace(/^\./, "").toLowerCase(); - } else { - freeTokens.push(tok); - } - } - result.freeText = freeTokens.join(" "); - return result; - }, - _tokenize(raw) { - const tokens = []; - let i = 0; - const n = raw.length; - while (i < n) { - while (i < n && raw[i] === " ") i++; - if (i >= n) break; - if (raw[i] !== '"') { - let j = i; - while (j < n && raw[j] !== " ") { - if (raw[j] === '"') { - j++; - while (j < n && raw[j] !== '"') j++; - if (j < n) j++; - } else j++; - } - tokens.push(raw.slice(i, j).replace(/"/g, "")); - i = j; - } else { - i++; - let j = i; - while (j < n && raw[j] !== '"') j++; - tokens.push(raw.slice(i, j)); - i = j + 1; - } - } - return tokens; - }, - /** Detect the current operator context at cursor for autocomplete */ - getContext(raw, cursorPos) { - const before = raw.slice(0, cursorPos); - // Check if we're typing a tag: or # value - const tagMatch = before.match(/(?:tag:|#)([\w-]*)$/i); - if (tagMatch) return { type: "tag", prefix: tagMatch[1] }; - // Check if typing title: - const titleMatch = before.match(/title:([\w-]*)$/i); - if (titleMatch) return { type: "title", prefix: titleMatch[1] }; - // Default: free text - const words = before.trim().split(/\s+/); - const lastWord = words[words.length - 1] || ""; - return { type: "text", prefix: lastWord }; - }, - }; - - // --------------------------------------------------------------------------- - // Autocomplete Dropdown Controller - // --------------------------------------------------------------------------- - const AutocompleteDropdown = { - _dropdown: null, - _historySection: null, - _titlesSection: null, - _tagsSection: null, - _historyList: null, - _titlesList: null, - _tagsList: null, - _emptyEl: null, - _suggestTimer: null, - - init() { - this._dropdown = document.getElementById("search-dropdown"); - this._historySection = document.getElementById("search-dropdown-history"); - this._titlesSection = document.getElementById("search-dropdown-titles"); - this._tagsSection = document.getElementById("search-dropdown-tags"); - this._historyList = document.getElementById("search-dropdown-history-list"); - this._titlesList = document.getElementById("search-dropdown-titles-list"); - this._tagsList = document.getElementById("search-dropdown-tags-list"); - this._emptyEl = document.getElementById("search-dropdown-empty"); - - // Clear history button - const clearBtn = document.getElementById("search-dropdown-clear-history"); - if (clearBtn) { - clearBtn.addEventListener("click", (e) => { - e.stopPropagation(); - SearchHistory.clear(); - this.hide(); - }); - } - - // Close dropdown on outside click - document.addEventListener("click", (e) => { - if (this._dropdown && !this._dropdown.contains(e.target) && e.target.id !== "search-input") { - this.hide(); - } - }); - }, - - show() { - if (this._dropdown) this._dropdown.hidden = false; - }, - - hide() { - if (this._dropdown) this._dropdown.hidden = true; - dropdownActiveIndex = -1; - dropdownItems = []; - }, - - isVisible() { - return this._dropdown && !this._dropdown.hidden; - }, - - /** Populate and show the dropdown with history, title suggestions, and tag suggestions */ - async populate(inputValue, cursorPos) { - if (this._suppressNext) { this._suppressNext = false; return; } - // Cancel previous suggestion request - if (suggestAbortController) { - suggestAbortController.abort(); - suggestAbortController = null; - } - - const ctx = QueryParser.getContext(inputValue, cursorPos); - const vault = document.getElementById("vault-filter").value; - - // History — always show filtered history - const historyItems = SearchHistory.filter(inputValue).slice(0, 5); - this._renderHistory(historyItems, inputValue); - - // Title and tag suggestions from API (debounced) — always fetch both - clearTimeout(this._suggestTimer); - const prefix = ctx.prefix; - if (prefix && prefix.length >= 2) { - // Only show placeholder if lists are empty (avoid flashing on fast typing) - const hasTitles = this._titlesList.children.length > 0 && !this._titlesList.querySelector(".search-dropdown__item--loading"); - const hasTags = this._tagsList.children.length > 0 && !this._tagsList.querySelector(".search-dropdown__item--loading"); - if (!hasTitles) { - this._titlesList.innerHTML = '
  • Recherche...
  • '; - } - if (!hasTags) { - this._tagsList.innerHTML = '
  • Recherche...
  • '; - } - this._titlesSection.hidden = false; - this._tagsSection.hidden = false; - this.show(); - this._suggestTimer = setTimeout(() => this._fetchSuggestions(prefix, vault), 150); - } else { - this._renderTitles([], ""); - this._renderTags([], ""); - this._titlesSection.hidden = true; - this._tagsSection.hidden = true; - } - - // Show/hide sections - this._historySection.hidden = historyItems.length === 0; - const hasContent = historyItems.length > 0; - if (hasContent || (prefix && prefix.length >= 2)) { - this.show(); - } else { - this.hide(); - } - - this._collectItems(); - }, - - async _fetchSuggestions(prefix, vault) { - suggestAbortController = new AbortController(); - // Fetch titles - try { - const titlesRes = await api(`/api/suggest?q=${encodeURIComponent(prefix)}&vault=${encodeURIComponent(vault)}&limit=5`, { signal: suggestAbortController.signal }); - this._renderTitles(titlesRes.suggestions || [], prefix); - this._titlesSection.hidden = !(titlesRes.suggestions || []).length; - if (titlesRes.suggestions?.length) this.show(); - } catch (err) { - if (err.name === "AbortError") return; - this._titlesSection.hidden = true; - } - // Fetch tags — keep section always visible to confirm it works - try { - const tagsRes = await api(`/api/tags/suggest?q=${encodeURIComponent(prefix)}&vault=${encodeURIComponent(vault)}&limit=5`, { signal: suggestAbortController.signal }); - const items = tagsRes.suggestions || []; - if (items.length > 0) { - this._renderTags(items, prefix); - } else { - this._tagsList.innerHTML = '
  • Aucun tag
  • '; - } - this._tagsSection.hidden = false; - this.show(); - } catch (err) { - if (err.name === "AbortError") return; - this._tagsList.innerHTML = '
  • Erreur chargement
  • '; - this._tagsSection.hidden = false; - } - this._collectItems(); - }, - - _renderHistory(items, query) { - this._historyList.innerHTML = ""; - items.forEach((entry) => { - const li = el("li", { class: "search-dropdown__item search-dropdown__item--history", role: "option" }); - const iconEl = el("span", { class: "search-dropdown__icon" }); - iconEl.innerHTML = ''; - const textEl = el("span", { class: "search-dropdown__text" }); - textEl.textContent = entry; - li.appendChild(iconEl); - li.appendChild(textEl); - li.addEventListener("click", () => { - const input = document.getElementById("search-input"); - input.value = entry; - this._suppressNext = true; - input.dispatchEvent(new Event("input", { bubbles: true })); - this.hide(); - _triggerAdvancedSearch(entry); - }); - this._historyList.appendChild(li); - }); - }, - - _renderTitles(items, prefix) { - this._titlesList.innerHTML = ""; - items.forEach((item) => { - const li = el("li", { class: "search-dropdown__item search-dropdown__item--title", role: "option" }); - const iconEl = el("span", { class: "search-dropdown__icon" }); - iconEl.innerHTML = ''; - const textEl = el("span", { class: "search-dropdown__text" }); - if (prefix) { - this._highlightText(textEl, item.title, prefix); - } else { - textEl.textContent = item.title; - } - const metaEl = el("span", { class: "search-dropdown__meta" }); - metaEl.textContent = item.vault; - li.appendChild(iconEl); - li.appendChild(textEl); - li.appendChild(metaEl); - li.addEventListener("click", () => { - this.hide(); - TabManager.openPreview(item.vault, item.path); - }); - this._titlesList.appendChild(li); - }); - }, - - _renderTags(items, prefix) { - this._tagsList.innerHTML = ""; - items.forEach((item) => { - const li = el("li", { class: "search-dropdown__item search-dropdown__item--tag", role: "option" }); - const iconEl = el("span", { class: "search-dropdown__icon" }); - iconEl.innerHTML = ''; - const textEl = el("span", { class: "search-dropdown__text" }); - if (prefix) { - this._highlightText(textEl, item.tag, prefix); - } else { - textEl.textContent = item.tag; - } - const badge = el("span", { class: "search-dropdown__badge" }); - badge.textContent = item.count; - li.appendChild(iconEl); - li.appendChild(textEl); - li.appendChild(badge); - li.addEventListener("click", () => { - const input = document.getElementById("search-input"); - const current = input.value; - const cursorPos = input.selectionStart; - const ctx = QueryParser.getContext(current, cursorPos); - if (ctx.type === "tag") { - // Replace the partial tag prefix - const before = current.slice(0, cursorPos - ctx.prefix.length); - input.value = before + item.tag + " "; - } else { - // Replace the last word with tag: operator - const words = current.trim().split(/\s+/); - if (words.length > 0 && ctx.prefix && ctx.prefix.length > 0) { - words[words.length - 1] = ""; // remove last partial word - } - const base = words.filter(w => w).join(" "); - input.value = (base ? base + " " : "") + "tag:" + item.tag + " "; - } - this._suppressNext = true; - input.dispatchEvent(new Event("input", { bubbles: true })); - this.hide(); - input.focus(); - _triggerAdvancedSearch(input.value); - }); - this._tagsList.appendChild(li); - }); - }, - - _highlightText(container, text, query) { - const lower = text.toLowerCase(); - const needle = query.toLowerCase(); - const pos = lower.indexOf(needle); - if (pos === -1) { - container.textContent = text; - return; - } - container.appendChild(document.createTextNode(text.slice(0, pos))); - const markEl = el("mark", {}, [document.createTextNode(text.slice(pos, pos + query.length))]); - container.appendChild(markEl); - container.appendChild(document.createTextNode(text.slice(pos + query.length))); - }, - - _collectItems() { - dropdownItems = Array.from(this._dropdown.querySelectorAll(".search-dropdown__item")); - dropdownActiveIndex = -1; - dropdownItems.forEach((item) => item.classList.remove("active")); - }, - - navigateDown() { - if (!this.isVisible() || dropdownItems.length === 0) return; - if (dropdownActiveIndex >= 0) dropdownItems[dropdownActiveIndex].classList.remove("active"); - dropdownActiveIndex = (dropdownActiveIndex + 1) % dropdownItems.length; - dropdownItems[dropdownActiveIndex].classList.add("active"); - dropdownItems[dropdownActiveIndex].scrollIntoView({ block: "nearest" }); - }, - - navigateUp() { - if (!this.isVisible() || dropdownItems.length === 0) return; - if (dropdownActiveIndex >= 0) dropdownItems[dropdownActiveIndex].classList.remove("active"); - dropdownActiveIndex = dropdownActiveIndex <= 0 ? dropdownItems.length - 1 : dropdownActiveIndex - 1; - dropdownItems[dropdownActiveIndex].classList.add("active"); - dropdownItems[dropdownActiveIndex].scrollIntoView({ block: "nearest" }); - }, - - selectActive() { - if (dropdownActiveIndex >= 0 && dropdownActiveIndex < dropdownItems.length) { - dropdownItems[dropdownActiveIndex].click(); - return true; - } - return false; - }, - }; - - // --------------------------------------------------------------------------- - // Search Chips Controller — renders active filter chips from parsed query - // --------------------------------------------------------------------------- - const SearchChips = { - _container: null, - init() { - this._container = document.getElementById("search-chips"); - }, - update(parsed) { - if (!this._container) return; - this._container.innerHTML = ""; - let hasChips = false; - parsed.tags.forEach((tag) => { - this._addChip("tag", `tag:${tag}`, tag); - hasChips = true; - }); - if (parsed.vault) { - this._addChip("vault", `vault:${parsed.vault}`, parsed.vault); - hasChips = true; - } - if (parsed.title) { - this._addChip("title", `title:${parsed.title}`, parsed.title); - hasChips = true; - } - if (parsed.path) { - this._addChip("path", `path:${parsed.path}`, parsed.path); - hasChips = true; - } - if (parsed.ext) { - this._addChip("ext", `ext:${parsed.ext}`, parsed.ext); - hasChips = true; - } - this._container.hidden = !hasChips; - }, - clear() { - if (!this._container) return; - this._container.innerHTML = ""; - this._container.hidden = true; - }, - _addChip(type, fullOperator, displayText) { - const chip = el("span", { class: `search-chip search-chip--${type}` }); - const label = el("span", { class: "search-chip__label" }); - label.textContent = fullOperator; - const removeBtn = el("button", { class: "search-chip__remove", title: "Retirer ce filtre", type: "button" }); - removeBtn.innerHTML = ''; - removeBtn.addEventListener("click", () => { - // Remove this operator from the input - const input = document.getElementById("search-input"); - const raw = input.value; - // Remove the operator text from the query - const escaped = fullOperator.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - input.value = raw.replace(new RegExp("\\s*" + escaped + "\\s*", "i"), " ").trim(); - _triggerAdvancedSearch(input.value); - }); - chip.appendChild(label); - chip.appendChild(removeBtn); - this._container.appendChild(chip); - safeCreateIcons(); - }, - }; - - // --------------------------------------------------------------------------- - // Helper: trigger advanced search from input value - // --------------------------------------------------------------------------- - function _triggerAdvancedSearch(rawQuery) { - const q = (rawQuery || "").trim(); - const vault = document.getElementById("vault-filter").value; - const tagFilter = selectedTags.length > 0 ? selectedTags.join(",") : null; - advancedSearchOffset = 0; - if (q.length > 0 || tagFilter) { - SearchHistory.add(q); - performAdvancedSearch(q, vault, tagFilter); - } else { - SearchChips.clear(); - showWelcome(); - } - } - - // --------------------------------------------------------------------------- - // Safe CDN helpers - // --------------------------------------------------------------------------- - - /** - * Debounced icon creation — batches multiple rapid calls into one - * DOM scan to avoid excessive reflows when building large trees. - */ - function safeCreateIcons() { - if (typeof lucide === "undefined" || !lucide.createIcons) return; - if (_iconDebounceTimer) return; // already scheduled - _iconDebounceTimer = requestAnimationFrame(() => { - _iconDebounceTimer = null; - try { - lucide.createIcons(); - } catch (e) { - /* CDN not loaded */ - } - }); - } - - /** Force-flush icon creation immediately (use sparingly). */ - function flushIcons() { - if (_iconDebounceTimer) { - cancelAnimationFrame(_iconDebounceTimer); - _iconDebounceTimer = null; - } - if (typeof lucide !== "undefined" && lucide.createIcons) { - try { - lucide.createIcons(); - } catch (e) { - /* CDN not loaded */ - } - } - } - - function safeHighlight(block) { - if (typeof hljs !== "undefined" && hljs.highlightElement) { - try { - hljs.highlightElement(block); - } catch (e) { - /* CDN not loaded */ - } - } - } - - // --------------------------------------------------------------------------- - // Outline/TOC Manager - // --------------------------------------------------------------------------- - - const OutlineManager = { - /** - * Slugify text to create valid IDs - */ - slugify(text) { - return ( - text - .toLowerCase() - .normalize("NFD") - .replace(/[\u0300-\u036f]/g, "") - .replace(/[^\p{L}\p{N}\s-]/gu, "") - .replace(/\s+/g, "-") - .replace(/-+/g, "-") - .trim() || "heading" - ); - }, - - /** - * Parse headings from markdown content - */ - parseHeadings() { - const contentArea = document.querySelector(".md-content"); - if (!contentArea) return []; - - const headings = []; - const h2s = contentArea.querySelectorAll("h2"); - const h3s = contentArea.querySelectorAll("h3"); - const allHeadings = [...h2s, ...h3s].sort((a, b) => { - return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1; - }); - - const usedIds = new Map(); - - allHeadings.forEach((heading) => { - const text = heading.textContent.trim(); - if (!text) return; - - const level = parseInt(heading.tagName[1]); - let id = this.slugify(text); - - // Handle duplicate IDs - if (usedIds.has(id)) { - const count = usedIds.get(id) + 1; - usedIds.set(id, count); - id = `${id}-${count}`; - } else { - usedIds.set(id, 1); - } - - // Inject ID into heading if not present - if (!heading.id) { - heading.id = id; - } else { - id = heading.id; - } - - headings.push({ - id, - level, - text, - element: heading, - }); - }); - - return headings; - }, - - /** - * Render outline list - */ - renderOutline(headings) { - const outlineList = document.getElementById("outline-list"); - const outlineEmpty = document.getElementById("outline-empty"); - - if (!outlineList) return; - - outlineList.innerHTML = ""; - - if (!headings || headings.length === 0) { - outlineList.hidden = true; - if (outlineEmpty) { - outlineEmpty.hidden = false; - safeCreateIcons(); - } - return; - } - - outlineList.hidden = false; - if (outlineEmpty) outlineEmpty.hidden = true; - - headings.forEach((heading) => { - const item = el( - "a", - { - class: `outline-item level-${heading.level}`, - href: `#${heading.id}`, - "data-heading-id": heading.id, - role: "link", - }, - [document.createTextNode(heading.text)], - ); - - item.addEventListener("click", (e) => { - e.preventDefault(); - this.scrollToHeading(heading.id); - }); - - outlineList.appendChild(item); - }); - - headingsCache = headings; - }, - - /** - * Scroll to heading with smooth behavior - */ - scrollToHeading(headingId) { - const heading = document.getElementById(headingId); - if (!heading) return; - - const contentArea = document.getElementById("content-area"); - if (!contentArea) return; - - // Calculate offset for fixed header (if any) - const headerHeight = 80; - const headingTop = heading.offsetTop; - - contentArea.scrollTo({ - top: headingTop - headerHeight, - behavior: "smooth", - }); - - // Update active state immediately - this.setActiveHeading(headingId); - }, - - /** - * Set active heading in outline - */ - setActiveHeading(headingId) { - if (activeHeadingId === headingId) return; - - activeHeadingId = headingId; - - const items = document.querySelectorAll(".outline-item"); - items.forEach((item) => { - if (item.getAttribute("data-heading-id") === headingId) { - item.classList.add("active"); - item.setAttribute("aria-current", "location"); - // Scroll outline item into view - item.scrollIntoView({ block: "nearest", behavior: "smooth" }); - } else { - item.classList.remove("active"); - item.removeAttribute("aria-current"); - } - }); - }, - - /** - * Initialize outline for current document - */ - init() { - const headings = this.parseHeadings(); - this.renderOutline(headings); - ScrollSpyManager.init(headings); - ReadingProgressManager.init(); - }, - - /** - * Cleanup - */ - destroy() { - ScrollSpyManager.destroy(); - ReadingProgressManager.destroy(); - headingsCache = []; - activeHeadingId = null; - }, - }; - - // --------------------------------------------------------------------------- - // Scroll Spy Manager - // --------------------------------------------------------------------------- - - const ScrollSpyManager = { - observer: null, - headings: [], - - init(headings) { - this.destroy(); - this.headings = headings; - - if (!headings || headings.length === 0) return; - - const contentArea = document.getElementById("content-area"); - if (!contentArea) return; - - const options = { - root: contentArea, - rootMargin: "-20% 0px -70% 0px", - threshold: [0, 0.3, 0.5, 1.0], - }; - - this.observer = new IntersectionObserver((entries) => { - // Find the most visible heading - let mostVisible = null; - let maxRatio = 0; - - entries.forEach((entry) => { - if (entry.isIntersecting && entry.intersectionRatio > maxRatio) { - maxRatio = entry.intersectionRatio; - mostVisible = entry.target; - } - }); - - if (mostVisible && mostVisible.id) { - OutlineManager.setActiveHeading(mostVisible.id); - } - }, options); - - // Observe all headings - headings.forEach((heading) => { - if (heading.element) { - this.observer.observe(heading.element); - } - }); - }, - - destroy() { - if (this.observer) { - this.observer.disconnect(); - this.observer = null; - } - this.headings = []; - }, - }; - - // --------------------------------------------------------------------------- - // Reading Progress Manager - // --------------------------------------------------------------------------- - - const ReadingProgressManager = { - scrollHandler: null, - - init() { - this.destroy(); - - const contentArea = document.getElementById("content-area"); - if (!contentArea) return; - - this.scrollHandler = this.throttle(() => { - this.updateProgress(); - }, 100); - - contentArea.addEventListener("scroll", this.scrollHandler); - this.updateProgress(); - }, - - updateProgress() { - const contentArea = document.getElementById("content-area"); - const progressFill = document.getElementById("reading-progress-fill"); - const progressText = document.getElementById("reading-progress-text"); - - if (!contentArea || !progressFill || !progressText) return; - - const scrollTop = contentArea.scrollTop; - const scrollHeight = contentArea.scrollHeight; - const clientHeight = contentArea.clientHeight; - - const maxScroll = scrollHeight - clientHeight; - const percentage = maxScroll > 0 ? Math.round((scrollTop / maxScroll) * 100) : 0; - - progressFill.style.width = `${percentage}%`; - progressText.textContent = `${percentage}%`; - }, - - throttle(func, delay) { - let lastCall = 0; - return function (...args) { - const now = Date.now(); - if (now - lastCall >= delay) { - lastCall = now; - func.apply(this, args); - } - }; - }, - - destroy() { - const contentArea = document.getElementById("content-area"); - if (contentArea && this.scrollHandler) { - contentArea.removeEventListener("scroll", this.scrollHandler); - } - this.scrollHandler = null; - - // Reset progress - const progressFill = document.getElementById("reading-progress-fill"); - const progressText = document.getElementById("reading-progress-text"); - if (progressFill) progressFill.style.width = "0%"; - if (progressText) progressText.textContent = "0%"; - }, - }; - - // --------------------------------------------------------------------------- - // Right Sidebar Manager - // --------------------------------------------------------------------------- - - const RightSidebarManager = { - init() { - this.loadState(); - this.initToggle(); - this.initResize(); - }, - - loadState() { - // Always start closed on login/refresh — user must explicitly toggle TOC - const savedWidth = localStorage.getItem("obsigate-right-sidebar-width"); - - if (savedWidth) { - rightSidebarWidth = parseInt(savedWidth) || 280; - } - - this.applyState(); - }, - - applyState() { - const sidebar = document.getElementById("right-sidebar"); - const handle = document.getElementById("right-sidebar-resize-handle"); - const tocBtn = document.getElementById("toc-toggle-btn"); - const headerToggleBtn = document.getElementById("right-sidebar-toggle-btn"); - - if (!sidebar) return; - - if (rightSidebarVisible) { - sidebar.classList.remove("hidden"); - sidebar.style.width = `${rightSidebarWidth}px`; - if (handle) handle.classList.remove("hidden"); - if (tocBtn) { - tocBtn.classList.add("active"); - tocBtn.title = "Masquer le sommaire"; - } - if (headerToggleBtn) { - headerToggleBtn.title = "Masquer le panneau"; - headerToggleBtn.setAttribute("aria-label", "Masquer le panneau"); - } - } else { - sidebar.classList.add("hidden"); - if (handle) handle.classList.add("hidden"); - if (tocBtn) { - tocBtn.classList.remove("active"); - tocBtn.title = "Afficher le sommaire"; - } - if (headerToggleBtn) { - headerToggleBtn.title = "Afficher le panneau"; - headerToggleBtn.setAttribute("aria-label", "Afficher le panneau"); - } - } - - // Update icons - safeCreateIcons(); - }, - - toggle() { - rightSidebarVisible = !rightSidebarVisible; - localStorage.setItem("obsigate-right-sidebar-visible", rightSidebarVisible); - this.applyState(); - }, - - initToggle() { - const toggleBtn = document.getElementById("right-sidebar-toggle-btn"); - if (toggleBtn) { - toggleBtn.addEventListener("click", () => this.toggle()); - } - }, - - initResize() { - const handle = document.getElementById("right-sidebar-resize-handle"); - const sidebar = document.getElementById("right-sidebar"); - - if (!handle || !sidebar) return; - - let isResizing = false; - let startX = 0; - let startWidth = 0; - - const onMouseDown = (e) => { - isResizing = true; - startX = e.clientX; - startWidth = sidebar.offsetWidth; - handle.classList.add("active"); - document.body.style.cursor = "ew-resize"; - document.body.style.userSelect = "none"; - }; - - const onMouseMove = (e) => { - if (!isResizing) return; - - const delta = startX - e.clientX; - let newWidth = startWidth + delta; - - // Constrain width - newWidth = Math.max(200, Math.min(400, newWidth)); - - sidebar.style.width = `${newWidth}px`; - rightSidebarWidth = newWidth; - }; - - const onMouseUp = () => { - if (!isResizing) return; - - isResizing = false; - handle.classList.remove("active"); - document.body.style.cursor = ""; - document.body.style.userSelect = ""; - - localStorage.setItem("obsigate-right-sidebar-width", rightSidebarWidth); - }; - - handle.addEventListener("mousedown", onMouseDown); - document.addEventListener("mousemove", onMouseMove); - document.addEventListener("mouseup", onMouseUp); - }, - }; - - // --------------------------------------------------------------------------- - // Theme - // --------------------------------------------------------------------------- - function initTheme() { - const saved = localStorage.getItem("obsigate-theme") || "dark"; - applyTheme(saved); - } - - function applyTheme(theme) { - document.documentElement.setAttribute("data-theme", theme); - localStorage.setItem("obsigate-theme", theme); - - // Update theme button icon and label - const themeBtn = document.getElementById("theme-toggle"); - const themeLabel = document.getElementById("theme-label"); - if (themeBtn && themeLabel) { - const icon = themeBtn.querySelector("i"); - if (icon) { - icon.setAttribute("data-lucide", theme === "dark" ? "moon" : "sun"); - } - themeLabel.textContent = theme === "dark" ? "Sombre" : "Clair"; - safeCreateIcons(); - } - - // Swap highlight.js theme - const darkSheet = document.getElementById("hljs-theme-dark"); - const lightSheet = document.getElementById("hljs-theme-light"); - if (darkSheet && lightSheet) { - darkSheet.disabled = theme !== "dark"; - lightSheet.disabled = theme !== "light"; - } - } - - function toggleTheme() { - const current = document.documentElement.getAttribute("data-theme"); - applyTheme(current === "dark" ? "light" : "dark"); - } - - function initHeaderMenu() { - const menuBtn = document.getElementById("header-menu-btn"); - const menuDropdown = document.getElementById("header-menu-dropdown"); - - if (!menuBtn || !menuDropdown) return; - - menuBtn.addEventListener("click", (e) => { - e.stopPropagation(); - menuBtn.classList.toggle("active"); - menuDropdown.classList.toggle("active"); - }); - - // Close menu when clicking outside - document.addEventListener("click", (e) => { - if (!menuDropdown.contains(e.target) && e.target !== menuBtn) { - menuBtn.classList.remove("active"); - menuDropdown.classList.remove("active"); - } - }); - - // Prevent menu from closing when clicking inside - menuDropdown.addEventListener("click", (e) => { - e.stopPropagation(); - }); - } - - function closeHeaderMenu() { - const menuBtn = document.getElementById("header-menu-btn"); - const menuDropdown = document.getElementById("header-menu-dropdown"); - if (!menuBtn || !menuDropdown) return; - menuBtn.classList.remove("active"); - menuDropdown.classList.remove("active"); - } - - // --------------------------------------------------------------------------- - // Custom Dropdowns - // --------------------------------------------------------------------------- - function initCustomDropdowns() { - document.querySelectorAll(".custom-dropdown").forEach((dropdown) => { - const trigger = dropdown.querySelector(".custom-dropdown-trigger"); - const options = dropdown.querySelectorAll(".custom-dropdown-option"); - const hiddenInput = dropdown.querySelector('input[type="hidden"]'); - const selectedText = dropdown.querySelector(".custom-dropdown-selected"); - const menu = dropdown.querySelector(".custom-dropdown-menu"); - - if (!trigger) return; - - // Toggle dropdown - trigger.addEventListener("click", (e) => { - e.stopPropagation(); - const isOpen = dropdown.classList.contains("open"); - - // Close all other dropdowns - document.querySelectorAll(".custom-dropdown.open").forEach((d) => { - if (d !== dropdown) d.classList.remove("open"); - }); - - dropdown.classList.toggle("open", !isOpen); - trigger.setAttribute("aria-expanded", !isOpen); - - // Position fixed menu for sidebar dropdowns - if (!isOpen && dropdown.classList.contains("sidebar-dropdown") && menu) { - const rect = trigger.getBoundingClientRect(); - menu.style.top = `${rect.bottom + 4}px`; - menu.style.left = `${rect.left}px`; - menu.style.width = `${rect.width}px`; - } - }); - - // Handle option selection - options.forEach((option) => { - option.addEventListener("click", (e) => { - e.stopPropagation(); - const value = option.getAttribute("data-value"); - const text = option.textContent; - - // Update hidden input - if (hiddenInput) { - hiddenInput.value = value; - // Trigger change event - hiddenInput.dispatchEvent(new Event("change", { bubbles: true })); - } - - // Update selected text - if (selectedText) { - selectedText.textContent = text; - } - - // Update visual selection - options.forEach((opt) => opt.classList.remove("selected")); - option.classList.add("selected"); - - // Close dropdown - dropdown.classList.remove("open"); - trigger.setAttribute("aria-expanded", "false"); - }); - }); - }); - - // Close dropdowns when clicking outside - document.addEventListener("click", () => { - document.querySelectorAll(".custom-dropdown.open").forEach((dropdown) => { - dropdown.classList.remove("open"); - const trigger = dropdown.querySelector(".custom-dropdown-trigger"); - if (trigger) trigger.setAttribute("aria-expanded", "false"); - }); - }); - } - - // Helper to populate custom dropdown options - function populateCustomDropdown(dropdownId, optionsList, defaultValue) { - const dropdown = document.getElementById(dropdownId); - if (!dropdown) return; - - const optionsContainer = dropdown.querySelector(".custom-dropdown-menu"); - const hiddenInput = dropdown.querySelector('input[type="hidden"]'); - const selectedText = dropdown.querySelector(".custom-dropdown-selected"); - - if (!optionsContainer) return; - - // Clear existing options (keep the first one if it's the default) - optionsContainer.innerHTML = ""; - - // Add new options - optionsList.forEach((opt) => { - const li = document.createElement("li"); - li.className = "custom-dropdown-option"; - li.setAttribute("role", "option"); - li.setAttribute("data-value", opt.value); - li.textContent = opt.text; - if (opt.value === defaultValue) { - li.classList.add("selected"); - if (selectedText) selectedText.textContent = opt.text; - if (hiddenInput) hiddenInput.value = opt.value; - } - optionsContainer.appendChild(li); - }); - - // Re-initialize click handlers - optionsContainer.querySelectorAll(".custom-dropdown-option").forEach((option) => { - option.addEventListener("click", (e) => { - e.stopPropagation(); - const value = option.getAttribute("data-value"); - const text = option.textContent; - - if (hiddenInput) { - hiddenInput.value = value; - hiddenInput.dispatchEvent(new Event("change", { bubbles: true })); - } - - if (selectedText) { - selectedText.textContent = text; - } - - optionsContainer.querySelectorAll(".custom-dropdown-option").forEach((opt) => opt.classList.remove("selected")); - option.classList.add("selected"); - - dropdown.classList.remove("open"); - const trigger = dropdown.querySelector(".custom-dropdown-trigger"); - if (trigger) trigger.setAttribute("aria-expanded", "false"); - }); - }); - } - - // --------------------------------------------------------------------------- - // Toast notifications - // --------------------------------------------------------------------------- - - /** Display a brief toast message at the bottom of the viewport. */ - function showToast(message, type) { - console.log("showToast called with:", message, type); - type = type || "info"; - let container = document.getElementById("toast-container"); - if (!container) { - container = document.createElement("div"); - container.id = "toast-container"; - container.className = "toast-container"; - container.setAttribute("aria-live", "polite"); - document.body.appendChild(container); - } - var toast = document.createElement("div"); - toast.className = "toast toast-" + type; - toast.textContent = message; - container.appendChild(toast); - // Trigger entrance animation - requestAnimationFrame(function () { - toast.classList.add("show"); - }); - setTimeout(function () { - toast.classList.remove("show"); - toast.addEventListener("transitionend", function () { - toast.remove(); - }); - }, 3500); - } - - // --------------------------------------------------------------------------- - // API helpers - // --------------------------------------------------------------------------- - - /** - * Fetch JSON from an API endpoint with optional AbortSignal support. - * Surfaces errors to the user via toast instead of silently failing. - * - * @param {string} path - API URL path. - * @param {object} [opts] - Fetch options (may include signal). - * @returns {Promise} Parsed JSON response. - */ - async function api(path, opts) { - var res; - try { - // Inject auth header if authenticated - const authHeaders = AuthManager.getAuthHeaders(); - const mergedOpts = opts || {}; - // Auto-set Content-Type for JSON bodies - if (mergedOpts.body && typeof mergedOpts.body === "string" && !mergedOpts.headers?.["Content-Type"]) { - mergedOpts.headers = { ...mergedOpts.headers, "Content-Type": "application/json" }; - } - if (authHeaders) { - mergedOpts.headers = { ...mergedOpts.headers, ...authHeaders }; - } - mergedOpts.credentials = "include"; - res = await fetch(path, mergedOpts); - } catch (err) { - if (err.name === "AbortError") throw err; // let callers handle abort - showToast("Erreur réseau — vérifiez votre connexion", "error"); - throw err; - } - if (res.status === 401 && AuthManager._authEnabled) { - // Token expired — try refresh - try { - await AuthManager.refreshAccessToken(); - // Retry the request with new token - const retryHeaders = AuthManager.getAuthHeaders(); - const retryOpts = opts || {}; - retryOpts.headers = { ...retryOpts.headers, ...retryHeaders }; - retryOpts.credentials = "include"; - res = await fetch(path, retryOpts); - } catch (refreshErr) { - AuthManager.clearSession(); - AuthManager.showLoginScreen(); - throw new Error("Session expirée"); - } - } - if (!res.ok) { - var detail = ""; - try { - var body = await res.json(); - detail = body.detail || ""; - } catch (_) { - /* no json body */ - } - showToast(detail || "Erreur API : " + res.status, "error"); - throw new Error(detail || "API error: " + res.status); - } - return res.json(); - } - - // --------------------------------------------------------------------------- - // AuthManager — Authentication state & token management - // --------------------------------------------------------------------------- - - const AuthManager = { - ACCESS_TOKEN_KEY: "obsigate_access_token", - TOKEN_EXPIRY_KEY: "obsigate_token_expiry", - USER_KEY: "obsigate_user", - _authEnabled: false, - - // ── Token storage (sessionStorage) ───────────────────────────── - - saveToken(tokenData) { - const expiresAt = Date.now() + tokenData.expires_in * 1000; - sessionStorage.setItem(this.ACCESS_TOKEN_KEY, tokenData.access_token); - sessionStorage.setItem(this.TOKEN_EXPIRY_KEY, expiresAt.toString()); - if (tokenData.user) { - sessionStorage.setItem(this.USER_KEY, JSON.stringify(tokenData.user)); - } - }, - - getToken() { - return sessionStorage.getItem(this.ACCESS_TOKEN_KEY); - }, - - getUser() { - const raw = sessionStorage.getItem(this.USER_KEY); - return raw ? JSON.parse(raw) : null; - }, - - isTokenExpired() { - const expiry = sessionStorage.getItem(this.TOKEN_EXPIRY_KEY); - if (!expiry) return true; - // Renew 60s before expiration - return Date.now() > parseInt(expiry) - 60000; - }, - - clearSession() { - sessionStorage.removeItem(this.ACCESS_TOKEN_KEY); - sessionStorage.removeItem(this.TOKEN_EXPIRY_KEY); - sessionStorage.removeItem(this.USER_KEY); - }, - - getAuthHeaders() { - const token = this.getToken(); - if (!token || !this._authEnabled) return null; - return { Authorization: "Bearer " + token }; - }, - - // ── API calls ────────────────────────────────────────────────── - - async login(username, password, rememberMe) { - const response = await fetch("/api/auth/login", { - method: "POST", - headers: { "Content-Type": "application/json" }, - credentials: "include", - body: JSON.stringify({ username, password, remember_me: rememberMe || false }), - }); - if (!response.ok) { - const err = await response.json(); - throw new Error(err.detail || "Erreur de connexion"); - } - const data = await response.json(); - this.saveToken(data); - return data.user; - }, - - async logout() { - try { - const token = this.getToken(); - await fetch("/api/auth/logout", { - method: "POST", - headers: token ? { Authorization: "Bearer " + token } : {}, - credentials: "include", - }); - } catch (e) { - /* continue even if API fails */ - } - this.clearSession(); - this.showLoginScreen(); - }, - - async refreshAccessToken() { - const response = await fetch("/api/auth/refresh", { - method: "POST", - credentials: "include", - }); - if (!response.ok) { - this.clearSession(); - throw new Error("Session expirée"); - } - const data = await response.json(); - const expiry = Date.now() + data.expires_in * 1000; - sessionStorage.setItem(this.ACCESS_TOKEN_KEY, data.access_token); - sessionStorage.setItem(this.TOKEN_EXPIRY_KEY, expiry.toString()); - return data.access_token; - }, - - // ── UI controls ──────────────────────────────────────────────── - - showLoginScreen() { - const app = document.getElementById("app"); - const login = document.getElementById("login-screen"); - if (app) app.classList.add("hidden"); - if (login) { - login.classList.remove("hidden"); - const usernameInput = document.getElementById("login-username"); - if (usernameInput) usernameInput.focus(); - } - }, - - showApp() { - const login = document.getElementById("login-screen"); - const app = document.getElementById("app"); - if (login) login.classList.add("hidden"); - if (app) app.classList.remove("hidden"); - this.renderUserMenu(); - }, - - renderUserMenu() { - const user = this.getUser(); - const userMenu = document.getElementById("user-menu"); - if (!userMenu) return; - if (!user || !this._authEnabled) { - userMenu.innerHTML = ""; - return; - } - userMenu.innerHTML = '' + (user.display_name || user.username) + "" + ''; - safeCreateIcons(); - - const logoutBtn = document.getElementById("logout-btn"); - if (logoutBtn) logoutBtn.addEventListener("click", () => AuthManager.logout()); - - const adminRow = document.getElementById("admin-menu-row"); - if (adminRow) { - if (user.role === "admin") { - adminRow.classList.remove("hidden"); - // Important: use an inline function to ensure we don't bind multiple identical listeners on rerenders, or clean up before - adminRow.onclick = () => { - closeHeaderMenu(); - AdminPanel.show(); - }; - } else { - adminRow.classList.add("hidden"); - } - } - }, - - // ── Initialization ────────────────────────────────────────────── - - async checkAuthStatus() { - try { - const res = await fetch("/api/auth/status"); - const data = await res.json(); - this._authEnabled = data.auth_enabled; - return data; - } catch (e) { - this._authEnabled = false; - return { auth_enabled: false }; - } - }, - - async initAuth() { - const status = await this.checkAuthStatus(); - if (!status.auth_enabled) { - // Auth disabled — show app immediately - this.showApp(); - return true; - } - - // Auth enabled — check for existing session - if (this.getToken() && !this.isTokenExpired()) { - this.showApp(); - return true; - } - - // Try silent refresh - try { - await this.refreshAccessToken(); - // Fetch user info - const token = this.getToken(); - const res = await fetch("/api/auth/me", { - headers: { Authorization: "Bearer " + token }, - credentials: "include", - }); - if (res.ok) { - const user = await res.json(); - sessionStorage.setItem(this.USER_KEY, JSON.stringify(user)); - this.showApp(); - return true; - } - } catch (e) { - /* silent refresh failed */ - } - - // No valid session — show login - this.showLoginScreen(); - return false; - }, - }; - - // --------------------------------------------------------------------------- - // Login form handler - // --------------------------------------------------------------------------- - - function initLoginForm() { - const form = document.getElementById("login-form"); - if (!form) return; - - form.addEventListener("submit", async (e) => { - e.preventDefault(); - const username = document.getElementById("login-username").value; - const password = document.getElementById("login-password").value; - const rememberMe = document.getElementById("remember-me").checked; - const errorEl = document.getElementById("login-error"); - const btn = document.getElementById("login-btn"); - - btn.disabled = true; - btn.querySelector(".btn-spinner").classList.remove("hidden"); - btn.querySelector(".btn-text").textContent = "Connexion..."; - errorEl.classList.add("hidden"); - - try { - await AuthManager.login(username, password, rememberMe); - AuthManager.showApp(); - // Load app data after successful login - try { - await Promise.all([loadVaults(), loadTags()]); - // Start SSE sync now that auth cookie is set - IndexUpdateManager.connect(); - // Show dashboard - showWelcome(); - } catch (err) { - console.error("Failed to load data after login:", err); - } - safeCreateIcons(); - } catch (err) { - errorEl.textContent = err.message; - errorEl.classList.remove("hidden"); - document.getElementById("login-password").value = ""; - document.getElementById("login-password").focus(); - } finally { - btn.disabled = false; - btn.querySelector(".btn-spinner").classList.add("hidden"); - btn.querySelector(".btn-text").textContent = "Se connecter"; - } - }); - - // Toggle password visibility - const toggleBtn = document.getElementById("toggle-password"); - if (toggleBtn) { - toggleBtn.addEventListener("click", () => { - const input = document.getElementById("login-password"); - input.type = input.type === "password" ? "text" : "password"; - }); - } - } - - // --------------------------------------------------------------------------- - // Admin Panel — User management (admin only) - // --------------------------------------------------------------------------- - - const AdminPanel = { - _modal: null, - _allVaults: [], - - show() { - this._createModal(); - this._modal.classList.add("active"); - this._loadUsers(); - }, - - hide() { - if (this._modal) this._modal.classList.remove("active"); - }, - - _createModal() { - if (this._modal) return; - this._modal = document.createElement("div"); - this._modal.className = "editor-modal"; - this._modal.id = "admin-modal"; - this._modal.innerHTML = ` -
    -
    -
    ⚙️ Administration — Utilisateurs
    -
    - -
    -
    -
    -
    - -
    -
    -
    -
    - `; - document.body.appendChild(this._modal); - safeCreateIcons(); - - document.getElementById("admin-close").addEventListener("click", () => this.hide()); - document.getElementById("admin-add-user").addEventListener("click", () => this._showUserForm(null)); - }, - - async _loadUsers() { - try { - const users = await api("/api/auth/admin/users"); - // Also load available vaults - try { - const vaultsData = await api("/api/vaults"); - this._allVaults = vaultsData.map((v) => v.name); - } catch (e) { - this._allVaults = []; - } - this._renderUsers(users); - } catch (err) { - document.getElementById("admin-users-list").innerHTML = '

    Erreur : ' + err.message + "

    "; - } - }, - - _renderUsers(users) { - const container = document.getElementById("admin-users-list"); - if (!users.length) { - container.innerHTML = '

    Aucun utilisateur.

    '; - return; - } - let html = '' + "" + ""; - users.forEach((u) => { - const vaults = u.vaults.includes("*") ? "Toutes" : u.vaults.join(", ") || "Aucune"; - const status = u.active ? "✅" : "🔴"; - const lastLogin = u.last_login ? new Date(u.last_login).toLocaleDateString("fr-FR", { day: "numeric", month: "short", year: "numeric", hour: "2-digit", minute: "2-digit" }) : "Jamais"; - html += - "" + - "" + - '" + - '" + - "" + - "" + - '"; - }); - html += "
    UtilisateurRôleVaultsStatutDernière connexionActions
    " + - u.username + - "" + - (u.display_name && u.display_name !== u.username ? "
    " + u.display_name + "" : "") + - "
    ' + - u.role + - "' + - vaults + - "" + - status + - "" + - lastLogin + - "' + - '' + - '' + - "
    "; - container.innerHTML = html; - - // Bind action buttons - container.querySelectorAll('[data-action="edit"]').forEach((btn) => { - btn.addEventListener("click", () => { - const user = users.find((u) => u.username === btn.dataset.username); - if (user) this._showUserForm(user); - }); - }); - container.querySelectorAll('[data-action="delete"]').forEach((btn) => { - btn.addEventListener("click", () => this._deleteUser(btn.dataset.username)); - }); - }, - - _showUserForm(user) { - const isEdit = !!user; - const title = isEdit ? "Modifier : " + user.username : "Nouvel utilisateur"; - const vaultCheckboxes = this._allVaults - .map((v) => { - const checked = user && (user.vaults.includes(v) || user.vaults.includes("*")) ? "checked" : ""; - return '"; - }) - .join(""); - const allVaultsChecked = user && user.vaults.includes("*") ? "checked" : ""; - - // Create form modal overlay - const overlay = document.createElement("div"); - overlay.className = "admin-form-overlay"; - overlay.innerHTML = ` -
    -

    ${title}

    -
    - ${!isEdit ? '
    ' : ""} -
    -
    -
    -
    - -
    ${vaultCheckboxes}
    - -
    - ${isEdit ? '
    " : ""} -
    - - -
    -
    -
    - `; - this._modal.appendChild(overlay); - - document.getElementById("admin-form-cancel").addEventListener("click", () => overlay.remove()); - - document.getElementById("admin-user-form").addEventListener("submit", async (e) => { - e.preventDefault(); - const form = e.target; - const allVaults = document.getElementById("admin-all-vaults").checked; - const selectedVaults = allVaults ? ["*"] : Array.from(form.querySelectorAll('input[name="vault"]:checked')).map((cb) => cb.value); - - try { - if (isEdit) { - const updates = { - display_name: form.display_name.value || null, - role: form.role.value, - vaults: selectedVaults, - }; - if (form.password.value) updates.password = form.password.value; - const activeCheckbox = form.querySelector('input[name="active"]'); - if (activeCheckbox) updates.active = activeCheckbox.checked; - await api("/api/auth/admin/users/" + user.username, { - method: "PATCH", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(updates), - }); - } else { - await api("/api/auth/admin/users", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - username: form.username.value, - password: form.password.value, - display_name: form.display_name.value || null, - role: form.role.value, - vaults: selectedVaults, - }), - }); - } - overlay.remove(); - this._loadUsers(); - showToast(isEdit ? "Utilisateur modifié" : "Utilisateur créé", "success"); - } catch (err) { - showToast(err.message, "error"); - } - }); - }, - - async _deleteUser(username) { - const currentUser = AuthManager.getUser(); - if (currentUser && currentUser.username === username) { - showToast("Impossible de supprimer son propre compte", "error"); - return; - } - if (!confirm("Supprimer l'utilisateur \"" + username + '" ?')) return; - try { - await api("/api/auth/admin/users/" + username, { method: "DELETE" }); - this._loadUsers(); - showToast("Utilisateur supprimé", "success"); - } catch (err) { - showToast(err.message, "error"); - } - }, - }; - - // --------------------------------------------------------------------------- - // Sidebar toggle (desktop) - // --------------------------------------------------------------------------- - function initSidebarToggle() { - const toggleBtn = document.getElementById("sidebar-toggle-btn"); - const sidebar = document.getElementById("sidebar"); - const resizeHandle = document.getElementById("sidebar-resize-handle"); - - if (!toggleBtn || !sidebar || !resizeHandle) return; - - // Restore saved state - const savedState = localStorage.getItem("obsigate-sidebar-hidden"); - if (savedState === "true") { - sidebar.classList.add("hidden"); - resizeHandle.classList.add("hidden"); - toggleBtn.classList.add("active"); - } - - toggleBtn.addEventListener("click", () => { - const isHidden = sidebar.classList.toggle("hidden"); - resizeHandle.classList.toggle("hidden", isHidden); - toggleBtn.classList.toggle("active", isHidden); - localStorage.setItem("obsigate-sidebar-hidden", isHidden ? "true" : "false"); - }); - } - - // --------------------------------------------------------------------------- - // Mobile sidebar - // --------------------------------------------------------------------------- - function initMobile() { - const hamburger = document.getElementById("hamburger-btn"); - const overlay = document.getElementById("sidebar-overlay"); - const sidebar = document.getElementById("sidebar"); - - hamburger.addEventListener("click", () => { - sidebar.classList.toggle("mobile-open"); - overlay.classList.toggle("active"); - }); - - overlay.addEventListener("click", () => { - sidebar.classList.remove("mobile-open"); - overlay.classList.remove("active"); - }); - } - - function closeMobileSidebar() { - const sidebar = document.getElementById("sidebar"); - const overlay = document.getElementById("sidebar-overlay"); - if (sidebar) sidebar.classList.remove("mobile-open"); - if (overlay) overlay.classList.remove("active"); - } - - // --------------------------------------------------------------------------- - // Vault context switching - // --------------------------------------------------------------------------- - function initVaultContext() { - const filter = document.getElementById("vault-filter"); - const quickSelect = document.getElementById("vault-quick-select"); - if (!filter || !quickSelect) return; - - filter.addEventListener("change", async () => { - await setSelectedVaultContext(filter.value, { focusVault: filter.value !== "all" }); - }); - - quickSelect.addEventListener("change", async () => { - await setSelectedVaultContext(quickSelect.value, { focusVault: quickSelect.value !== "all" }); - }); - } - - async function setSelectedVaultContext(vaultName, options) { - selectedContextVault = vaultName; - showingSource = false; - cachedRawSource = null; - syncVaultSelectors(); - await refreshSidebarForContext(); - await refreshTagsForContext(); - - // Synchroniser le dashboard et les fichiers récents - if (typeof DashboardRecentWidget !== "undefined" && DashboardRecentWidget.load) { - DashboardRecentWidget.load(vaultName); - } - if (typeof DashboardBookmarkWidget !== "undefined" && DashboardBookmarkWidget.load) { - DashboardBookmarkWidget.load(vaultName); - } - if (activeSidebarTab === "recent") { - loadRecentFiles(vaultName === "all" ? null : vaultName); - } - - showWelcome(); - if (options && options.focusVault && vaultName !== "all") { - await focusVaultInSidebar(vaultName); - } - } - - function syncVaultSelectors() { - const filter = document.getElementById("vault-filter"); - const quickSelect = document.getElementById("vault-quick-select"); - const recentFilter = document.getElementById("recent-vault-filter"); - const dashboardFilter = document.getElementById("dashboard-vault-filter"); - const contextText = document.getElementById("vault-context-text"); - - if (filter) filter.value = selectedContextVault; - if (quickSelect) quickSelect.value = selectedContextVault; - if (recentFilter) recentFilter.value = selectedContextVault === "all" ? "" : selectedContextVault; - if (dashboardFilter) dashboardFilter.value = selectedContextVault; - - // Mise à jour visuelle des dropdowns personnalisés - updateCustomDropdownVisual("vault-filter-dropdown", selectedContextVault); - updateCustomDropdownVisual("vault-quick-select-dropdown", selectedContextVault); - - // Update vault context indicator - if (contextText) { - contextText.textContent = selectedContextVault === "all" ? "All" : selectedContextVault; - } - } - - /** - * Updates the visual state of a custom dropdown based on its current value. - */ - function updateCustomDropdownVisual(dropdownId, value) { - const dropdown = document.getElementById(dropdownId); - if (!dropdown) return; - - const selectedText = dropdown.querySelector(".custom-dropdown-selected"); - const options = dropdown.querySelectorAll(".custom-dropdown-option"); - - options.forEach((opt) => { - const optValue = opt.getAttribute("data-value"); - if (optValue === value) { - opt.classList.add("selected"); - if (selectedText) selectedText.textContent = opt.textContent; - } else { - opt.classList.remove("selected"); - } - }); - } - - function scrollTreeItemIntoView(element, alignToTop) { - if (!element) return; - const scrollContainer = document.getElementById("sidebar-panel-vaults"); - if (!scrollContainer) return; - - const containerRect = scrollContainer.getBoundingClientRect(); - const elementRect = element.getBoundingClientRect(); - const isAbove = elementRect.top < containerRect.top; - const isBelow = elementRect.bottom > containerRect.bottom; - - if (!isAbove && !isBelow && !alignToTop) return; - - const currentTop = scrollContainer.scrollTop; - const offsetTop = element.offsetTop; - const shouldCenter = alignToTop === "center"; - const centeredTop = Math.max(0, currentTop + (elementRect.top - containerRect.top) - (containerRect.height / 2) + (elementRect.height / 2)); - const targetTop = shouldCenter - ? centeredTop - : alignToTop - ? Math.max(0, offsetTop - 60) - : Math.max(0, currentTop + (elementRect.top - containerRect.top) - containerRect.height * 0.35); - - scrollContainer.scrollTo({ - top: targetTop, - behavior: "smooth", - }); - } - - async function refreshSidebarForContext() { - const container = document.getElementById("vault-tree"); - container.innerHTML = ""; - - const vaultsToShow = selectedContextVault === "all" ? allVaults : allVaults.filter((v) => v.name === selectedContextVault); - - vaultsToShow.forEach((v) => { - const vaultItem = el("div", { class: "tree-item vault-item", "data-vault": v.name }, [icon("chevron-right", 14), getVaultIcon(v.name, 16), el("span", { class: "tree-item-text" }, [document.createTextNode(v.name)]), smallBadge(v.file_count)]); - vaultItem.addEventListener("click", () => toggleVault(vaultItem, v.name)); - - vaultItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - const isReadonly = false; - ContextMenuManager.show(e.clientX, e.clientY, v.name, '', 'vault', isReadonly); - }); - attachTreeItemActionButton(vaultItem, v.name, "", "vault", false); - attachTreeItemLongPress(vaultItem, () => ({ vault: v.name, path: "", type: "vault", isReadonly: false })); - - container.appendChild(vaultItem); - - const childContainer = el("div", { class: "tree-children collapsed", id: `vault-children-${v.name}` }); - container.appendChild(childContainer); - }); - - safeCreateIcons(); - } - - async function focusVaultInSidebar(vaultName) { - switchSidebarTab("vaults"); - const vaultItem = document.querySelector(`.vault-item[data-vault="${CSS.escape(vaultName)}"]`); - if (!vaultItem) return; - document.querySelectorAll(".vault-item.focused").forEach((el) => el.classList.remove("focused")); - vaultItem.classList.add("focused"); - const childContainer = document.getElementById(`vault-children-${vaultName}`); - if (childContainer && childContainer.classList.contains("collapsed")) { - await toggleVault(vaultItem, vaultName, true); - } - scrollTreeItemIntoView(vaultItem, false); - } - - async function refreshTagsForContext() { - const vaultParam = selectedContextVault === "all" ? "" : `?vault=${encodeURIComponent(selectedContextVault)}`; - const data = await api(`/api/tags${vaultParam}`); - const filteredTags = TagFilterService.filterTags(data.tags); - renderTagCloud(filteredTags); - } - - // --------------------------------------------------------------------------- - // Helper: Check if path should be displayed based on hideHiddenFiles setting - // --------------------------------------------------------------------------- - function shouldDisplayPath(path, vaultName) { - // Get hideHiddenFiles setting for this vault (default: false = show all) - const settings = vaultSettings[vaultName] || { hideHiddenFiles: false }; - - if (!settings.hideHiddenFiles) { - // Show all files - return true; - } - - // Check if any segment of the path starts with a dot (hidden) - const segments = path.split("/").filter(Boolean); - for (const segment of segments) { - if (segment.startsWith(".")) { - return false; // Hide this path - } - } - - return true; // Show this path - } - - async function loadVaultSettings() { - try { - const settings = await api("/api/vaults/settings/all"); - vaultSettings = settings; - } catch (err) { - console.error("Failed to load vault settings:", err); - vaultSettings = {}; - } - } - - // --------------------------------------------------------------------------- - // Sidebar — Vault tree - // --------------------------------------------------------------------------- - async function loadVaults() { - const vaults = await api("/api/vaults"); - allVaults = vaults; - const container = document.getElementById("vault-tree"); - container.innerHTML = ""; - - // Prepare dropdown options - const dropdownOptions = [{ value: "all", text: "Tous les vaults" }, ...vaults.map((v) => ({ value: v.name, text: v.name }))]; - - // Populate custom dropdowns - populateCustomDropdown("vault-filter-dropdown", dropdownOptions, "all"); - populateCustomDropdown("vault-quick-select-dropdown", dropdownOptions, "all"); - - // Populate standard selects - _populateRecentVaultFilter(); - if (typeof DashboardRecentWidget !== "undefined" && DashboardRecentWidget.populateVaultFilter) { - DashboardRecentWidget.populateVaultFilter(); - } - - vaults.forEach((v) => { - // Sidebar tree entry - const vaultItem = el("div", { class: "tree-item vault-item", "data-vault": v.name }, [icon("chevron-right", 14), getVaultIcon(v.name, 16), el("span", { class: "tree-item-text" }, [document.createTextNode(v.name)]), smallBadge(v.file_count)]); - vaultItem.addEventListener("click", () => toggleVault(vaultItem, v.name)); - - vaultItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - const isReadonly = false; - ContextMenuManager.show(e.clientX, e.clientY, v.name, '', 'vault', isReadonly); - }); - attachTreeItemActionButton(vaultItem, v.name, "", "vault", false); - attachTreeItemLongPress(vaultItem, () => ({ vault: v.name, path: "", type: "vault", isReadonly: false })); - - container.appendChild(vaultItem); - - const childContainer = el("div", { class: "tree-children collapsed", id: `vault-children-${v.name}` }); - container.appendChild(childContainer); - }); - - syncVaultSelectors(); - safeCreateIcons(); - } - - /** - * Refreshes the sidebar tree while preserving the expanded state of vaults and folders. - * Optimized to avoid a full sidebar wipe and minimize visible loading states. - */ - /** - * Incrementally update a directory container without wiping existing DOM. - * Only adds new items, removes deleted ones, and updates changed ones. - */ - async function incrementalLoadDirectory(vaultName, dirPath, container) { - let data; - try { - const url = `/api/browse/${encodeURIComponent(vaultName)}?path=${encodeURIComponent(dirPath)}`; - data = await api(url); - } catch (err) { - // Server unavailable — keep existing content - return; - } - - // Build a map of existing DOM elements by path - const existingItems = {}; - const existingChildren = {}; // path -> child container (for directories) - for (let i = 0; i < container.children.length; i++) { - const child = container.children[i]; - if (child.classList.contains("tree-item") && child.dataset.path) { - existingItems[child.dataset.path] = child; - // The next sibling should be the tree-children container for this directory - if (i + 1 < container.children.length) { - const next = container.children[i + 1]; - if (next.classList.contains("tree-children")) { - existingChildren[child.dataset.path] = next; - } - } - } - } - - const fragment = document.createDocumentFragment(); - - data.items.forEach((item) => { - if (!shouldDisplayPath(item.path, vaultName)) return; - - const existing = existingItems[item.path]; - - if (existing) { - // Item already exists — reuse it, but update text/badge if needed - const textEl = existing.querySelector(".tree-item-text"); - const displayName = item.type === "file" && item.name.match(/\.md$/i) - ? item.name.replace(/\.md$/i, "") - : item.name; - if (textEl && textEl.textContent !== displayName) { - textEl.textContent = displayName; - } - // Update badge for directories - if (item.type === "directory") { - const badge = existing.querySelector(".badge-small"); - const newBadge = `(${item.children_count})`; - if (badge && badge.textContent !== newBadge) { - badge.textContent = newBadge; - } else if (!badge) { - existing.appendChild(smallBadge(item.children_count)); - } - } - fragment.appendChild(existing); - // Also re-add the child container for directories - if (item.type === "directory" && existingChildren[item.path]) { - fragment.appendChild(existingChildren[item.path]); - } else if (item.type === "directory") { - // Directory existed but no child container — create one - const subContainer = el("div", { class: "tree-children collapsed", id: `dir-${vaultName}-${item.path}` }); - fragment.appendChild(subContainer); - } - } else { - // New item — create it - if (item.type === "directory") { - const dirItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path }, [icon("chevron-right", 14), icon("folder", 16), el("span", { class: "tree-item-text" }, [document.createTextNode(item.name)]), smallBadge(item.children_count)]); - attachTreeItemActionButton(dirItem, vaultName, item.path, "directory", false); - attachTreeItemLongPress(dirItem, () => ({ vault: vaultName, path: item.path, type: "directory", isReadonly: false })); - fragment.appendChild(dirItem); - - const subContainer = el("div", { class: "tree-children collapsed", id: `dir-${vaultName}-${item.path}` }); - fragment.appendChild(subContainer); - - dirItem.addEventListener("click", async () => { - scrollTreeItemIntoView(dirItem, false); - if (subContainer.classList.contains("collapsed")) { - if (subContainer.children.length === 0) { - await loadDirectory(vaultName, item.path, subContainer); - } - subContainer.classList.remove("collapsed"); - const chev = dirItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-down"); - safeCreateIcons(); - } else { - subContainer.classList.add("collapsed"); - const chev = dirItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-right"); - safeCreateIcons(); - } - }); - - dirItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, "directory", false); - }); - } else { - const fileIconName = getFileIcon(item.name); - const displayName = item.name.match(/\.md$/i) ? item.name.replace(/\.md$/i, "") : item.name; - const fileItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path }, [icon(fileIconName, 16), el("span", { class: "tree-item-text" }, [document.createTextNode(displayName)])]); - attachTreeItemActionButton(fileItem, vaultName, item.path, "file", false); - attachTreeItemLongPress(fileItem, () => ({ vault: vaultName, path: item.path, type: "file", isReadonly: false })); - fileItem.addEventListener("click", () => { - scrollTreeItemIntoView(fileItem, false); - TabManager.openPreview(vaultName, item.path); - closeMobileSidebar(); - }); - - fileItem.addEventListener("dblclick", (e) => { - e.preventDefault(); - TabManager.openPersistent(vaultName, item.path); - }); - - fileItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, "file", false); - }); - - fragment.appendChild(fileItem); - } - } - }); - - // Replace container content in a single batch operation to avoid flash - container.textContent = ""; - container.appendChild(fragment); - } - - async function refreshSidebarTreePreservingState() { - // 1. Capture expanded states - const expandedVaults = Array.from(document.querySelectorAll(".vault-item")) - .filter((v) => { - const children = document.getElementById(`vault-children-${v.dataset.vault}`); - return children && !children.classList.contains("collapsed"); - }) - .map((v) => v.dataset.vault); - - const expandedDirs = Array.from(document.querySelectorAll(".tree-item[data-path]")) - .filter((item) => { - const vault = item.dataset.vault; - const path = item.dataset.path; - const children = document.getElementById(`dir-${vault}-${path}`); - return children && !children.classList.contains("collapsed"); - }) - .map((item) => ({ vault: item.dataset.vault, path: item.dataset.path })); - - const selectedItem = document.querySelector(".tree-item.path-selected"); - const selectedState = selectedItem ? { vault: selectedItem.dataset.vault, path: selectedItem.dataset.path } : null; - - // 2. Soft update: vault names/counts without wiping the tree - try { - const vaults = await api("/api/vaults"); - allVaults = vaults; - vaults.forEach((v) => { - const vItem = document.querySelector(`.vault-item[data-vault="${CSS.escape(v.name)}"]`); - if (vItem) { - const badge = vItem.querySelector(".badge-small"); - if (badge) badge.textContent = `(${v.file_count})`; - } - }); - } catch (e) { - console.warn("Soft vault refresh failed, falling back to full reload", e); - await loadVaults(); - return; - } - - // 3. Incrementally update expanded vaults (no DOM wipe) - for (const vName of expandedVaults) { - const container = document.getElementById(`vault-children-${vName}`); - if (container) { - await incrementalLoadDirectory(vName, "", container); - } - } - - // 4. Incrementally update expanded directories (parents first, no DOM wipe) - expandedDirs.sort((a, b) => a.path.split("/").length - b.path.split("/").length); - for (const dir of expandedDirs) { - const container = document.getElementById(`dir-${dir.vault}-${dir.path}`); - if (container) { - try { - await incrementalLoadDirectory(dir.vault, dir.path, container); - container.classList.remove("collapsed"); - const dItem = document.querySelector(`.tree-item[data-vault="${CSS.escape(dir.vault)}"][data-path="${CSS.escape(dir.path)}"]`); - if (dItem) { - const chev = dItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-down"); - } - } catch (e) { - console.error(`Failed to refresh directory ${dir.vault}/${dir.path}`, e); - } - } - } - - // 5. Restore selection - if (selectedState) { - await focusPathInSidebar(selectedState.vault, selectedState.path, { alignToTop: false }); - } - - safeCreateIcons(); - } - - async function toggleVault(itemEl, vaultName, forceExpand) { - const childContainer = document.getElementById(`vault-children-${vaultName}`); - if (!childContainer) return; - - scrollTreeItemIntoView(itemEl, false); - - const shouldExpand = forceExpand || childContainer.classList.contains("collapsed"); - - if (shouldExpand) { - // Expand — load children if empty - if (childContainer.children.length === 0) { - await loadDirectory(vaultName, "", childContainer); - } - childContainer.classList.remove("collapsed"); - // Swap chevron - const chevron = itemEl.querySelector("[data-lucide]"); - if (chevron) chevron.setAttribute("data-lucide", "chevron-down"); - safeCreateIcons(); - } else { - childContainer.classList.add("collapsed"); - const chevron = itemEl.querySelector("[data-lucide]"); - if (chevron) chevron.setAttribute("data-lucide", "chevron-right"); - safeCreateIcons(); - } - } - - async function expandDirectoryInSidebar(vaultName, dirPath, dirItem) { - const subContainer = document.getElementById(`dir-${vaultName}-${dirPath}`); - if (!subContainer) return null; - - if (subContainer.children.length === 0) { - await loadDirectory(vaultName, dirPath, subContainer); - } - - subContainer.classList.remove("collapsed"); - if (dirItem) { - const chevron = dirItem.querySelector("[data-lucide]"); - if (chevron) chevron.setAttribute("data-lucide", "chevron-down"); - } - safeCreateIcons(); - return subContainer; - } - - async function focusPathInSidebar(vaultName, targetPath, options) { - switchSidebarTab("vaults"); - - const vaultItem = document.querySelector(`.vault-item[data-vault="${CSS.escape(vaultName)}"]`); - if (!vaultItem) return; - - document.querySelectorAll(".vault-item.focused").forEach((el) => el.classList.remove("focused")); - vaultItem.classList.add("focused"); - - const vaultContainer = document.getElementById(`vault-children-${vaultName}`); - if (!vaultContainer) return; - - if (vaultContainer.classList.contains("collapsed")) { - await toggleVault(vaultItem, vaultName, true); - } - - if (!targetPath) { - // Clear any previous path selection - document.querySelectorAll(".tree-item.path-selected").forEach((el) => el.classList.remove("path-selected")); - scrollTreeItemIntoView(vaultItem, options && options.alignToTop); - return; - } - - const segments = targetPath.split("/").filter(Boolean); - let currentContainer = vaultContainer; - let cumulativePath = ""; - let lastTargetItem = null; - - for (let index = 0; index < segments.length; index++) { - cumulativePath += (cumulativePath ? "/" : "") + segments[index]; - - let targetItem = null; - try { - targetItem = currentContainer.querySelector(`.tree-item[data-vault="${CSS.escape(vaultName)}"][data-path="${CSS.escape(cumulativePath)}"]`); - } catch (e) { - targetItem = null; - } - - if (!targetItem) { - return; - } - - lastTargetItem = targetItem; - - const isLastSegment = index === segments.length - 1; - if (!isLastSegment) { - const nextContainer = await expandDirectoryInSidebar(vaultName, cumulativePath, targetItem); - if (nextContainer) { - currentContainer = nextContainer; - } - } - } - - if (lastTargetItem && options && options.expandTarget) { - await expandDirectoryInSidebar(vaultName, targetPath, lastTargetItem); - } - - // Clear previous path selections and highlight the final target - document.querySelectorAll(".tree-item.path-selected").forEach((el) => el.classList.remove("path-selected")); - if (lastTargetItem) { - lastTargetItem.classList.add("path-selected"); - } - - scrollTreeItemIntoView(lastTargetItem, options && options.alignToTop); - } - - function getParentDirectoryPath(filePath) { - if (!filePath) return ""; - const segments = filePath.split("/").filter(Boolean); - if (segments.length <= 1) return ""; - segments.pop(); - return segments.join("/"); - } - - function syncActiveFileTreeItem(vaultName, filePath) { - document.querySelectorAll(".tree-item.active").forEach((el) => el.classList.remove("active")); - if (!vaultName || !filePath) return; - const selector = `.tree-item[data-vault="${CSS.escape(vaultName)}"][data-path="${CSS.escape(filePath)}"]`; - try { - const active = document.querySelector(selector); - if (active) active.classList.add("active"); - } catch (e) { - /* selector might fail on special chars */ - } - } - - async function loadDirectory(vaultName, dirPath, container) { - // Only show the loading spinner if the container is currently empty - const isEmpty = container.children.length === 0; - if (isEmpty) { - container.innerHTML = '
    '; - } - - var data; - try { - const url = `/api/browse/${encodeURIComponent(vaultName)}?path=${encodeURIComponent(dirPath)}`; - data = await api(url); - } catch (err) { - container.innerHTML = '
    Erreur de chargement
    '; - return; - } - container.innerHTML = ""; - - const fragment = document.createDocumentFragment(); - - data.items.forEach((item) => { - // Apply client-side filtering for hidden files - if (!shouldDisplayPath(item.path, vaultName)) { - return; // Skip this item - } - - if (item.type === "directory") { - const dirItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path }, [icon("chevron-right", 14), icon("folder", 16), el("span", { class: "tree-item-text" }, [document.createTextNode(item.name)]), smallBadge(item.children_count)]); - attachTreeItemActionButton(dirItem, vaultName, item.path, "directory", false); - attachTreeItemLongPress(dirItem, () => ({ vault: vaultName, path: item.path, type: "directory", isReadonly: false })); - fragment.appendChild(dirItem); - - const subContainer = el("div", { class: "tree-children collapsed", id: `dir-${vaultName}-${item.path}` }); - fragment.appendChild(subContainer); - - dirItem.addEventListener("click", async () => { - scrollTreeItemIntoView(dirItem, false); - if (subContainer.classList.contains("collapsed")) { - if (subContainer.children.length === 0) { - await loadDirectory(vaultName, item.path, subContainer); - } - subContainer.classList.remove("collapsed"); - const chev = dirItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-down"); - safeCreateIcons(); - } else { - subContainer.classList.add("collapsed"); - const chev = dirItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-right"); - safeCreateIcons(); - } - }); - - dirItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - const isReadonly = false; - ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, 'directory', isReadonly); - }); - } else { - const fileIconName = getFileIcon(item.name); - const displayName = item.name.match(/\.md$/i) ? item.name.replace(/\.md$/i, "") : item.name; - const fileItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path }, [icon(fileIconName, 16), el("span", { class: "tree-item-text" }, [document.createTextNode(displayName)])]); - attachTreeItemActionButton(fileItem, vaultName, item.path, "file", false); - attachTreeItemLongPress(fileItem, () => ({ vault: vaultName, path: item.path, type: "file", isReadonly: false })); - fileItem.addEventListener("click", () => { - scrollTreeItemIntoView(fileItem, false); - TabManager.openPreview(vaultName, item.path); - closeMobileSidebar(); - }); - - fileItem.addEventListener("dblclick", (e) => { - e.preventDefault(); - TabManager.openPersistent(vaultName, item.path); - }); - - fileItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - const isReadonly = false; - ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, 'file', isReadonly); - }); - - fragment.appendChild(fileItem); - } - }); - - container.appendChild(fragment); - safeCreateIcons(); - } - - // --------------------------------------------------------------------------- - // Sidebar filter - // --------------------------------------------------------------------------- - function initSidebarFilter() { - const input = document.getElementById("sidebar-filter-input"); - const caseBtn = document.getElementById("sidebar-filter-case-btn"); - const clearBtn = document.getElementById("sidebar-filter-clear-btn"); - - input.addEventListener("input", () => { - const hasText = input.value.length > 0; - clearBtn.style.display = hasText ? "flex" : "none"; - clearTimeout(filterDebounce); - filterDebounce = setTimeout(async () => { - const q = sidebarFilterCaseSensitive ? input.value.trim() : input.value.trim().toLowerCase(); - if (hasText) { - if (activeSidebarTab === "vaults") { - await performTreeSearch(q); - } else { - filterTagCloud(q); - } - } else { - if (activeSidebarTab === "vaults") { - await restoreSidebarTree(); - } else { - filterTagCloud(""); - } - } - }, 220); - }); - - caseBtn.addEventListener("click", async () => { - sidebarFilterCaseSensitive = !sidebarFilterCaseSensitive; - caseBtn.classList.toggle("active"); - const q = sidebarFilterCaseSensitive ? input.value.trim() : input.value.trim().toLowerCase(); - if (input.value.trim()) { - if (activeSidebarTab === "vaults") { - await performTreeSearch(q); - } else { - filterTagCloud(q); - } - } - }); - - clearBtn.addEventListener("click", async () => { - input.value = ""; - clearBtn.style.display = "none"; - sidebarFilterCaseSensitive = false; - caseBtn.classList.remove("active"); - clearTimeout(filterDebounce); - if (activeSidebarTab === "vaults") { - await restoreSidebarTree(); - } else { - filterTagCloud(""); - } - }); - - clearBtn.style.display = "none"; - } - - async function performTreeSearch(query) { - if (!query) { - await restoreSidebarTree(); - return; - } - - try { - const vaultParam = selectedContextVault === "all" ? "all" : selectedContextVault; - const url = `/api/tree-search?q=${encodeURIComponent(query)}&vault=${encodeURIComponent(vaultParam)}`; - const data = await api(url); - renderFilteredSidebarResults(query, data.results); - } catch (err) { - console.error("Tree search error:", err); - renderFilteredSidebarResults(query, []); - } - } - - async function restoreSidebarTree() { - await refreshSidebarForContext(); - if (currentVault) { - focusPathInSidebar(currentVault, currentPath || "", { alignToTop: false }).catch(() => {}); - } - } - - function renderFilteredSidebarResults(query, results) { - const container = document.getElementById("vault-tree"); - container.innerHTML = ""; - - const grouped = new Map(); - results.forEach((result) => { - if (!grouped.has(result.vault)) { - grouped.set(result.vault, []); - } - grouped.get(result.vault).push(result); - }); - - if (grouped.size === 0) { - container.appendChild(el("div", { class: "sidebar-filter-empty" }, [document.createTextNode("Aucun répertoire ou fichier correspondant.")])); - return; - } - - grouped.forEach((entries, vaultName) => { - entries.sort((a, b) => a.path.localeCompare(b.path, undefined, { sensitivity: "base" })); - - const vaultHeader = el("div", { class: "tree-item vault-item filter-results-header", "data-vault": vaultName }, [getVaultIcon(vaultName, 16), document.createTextNode(` ${vaultName} `), smallBadge(entries.length)]); - container.appendChild(vaultHeader); - - const resultsWrapper = el("div", { class: "filter-results-group" }); - entries.forEach((entry) => { - const resultItem = el( - "div", - { - class: `tree-item filter-result-item filter-result-${entry.type}`, - "data-vault": entry.vault, - "data-path": entry.path, - "data-type": entry.type, - }, - [icon(entry.type === "directory" ? "folder" : getFileIcon(entry.name), 16)], - ); - - const textWrap = el("div", { class: "filter-result-text" }); - const primary = el("div", { class: "filter-result-primary" }); - appendHighlightedText(primary, entry.name, query, sidebarFilterCaseSensitive); - const secondary = el("div", { class: "filter-result-secondary" }); - appendHighlightedText(secondary, entry.path, query, sidebarFilterCaseSensitive); - textWrap.appendChild(primary); - textWrap.appendChild(secondary); - resultItem.appendChild(textWrap); - - resultItem.addEventListener("click", async () => { - const input = document.getElementById("sidebar-filter-input"); - const clearBtn = document.getElementById("sidebar-filter-clear-btn"); - if (input) input.value = ""; - if (clearBtn) clearBtn.style.display = "none"; - await restoreSidebarTree(); - if (entry.type === "directory") { - await focusPathInSidebar(entry.vault, entry.path, { alignToTop: true, expandTarget: true }); - } else { - await TabManager.openPreview(entry.vault, entry.path); - await focusPathInSidebar(entry.vault, getParentDirectoryPath(entry.path), { alignToTop: true, expandTarget: true }); - syncActiveFileTreeItem(entry.vault, entry.path); - } - closeMobileSidebar(); - }); - - resultsWrapper.appendChild(resultItem); - }); - - container.appendChild(resultsWrapper); - }); - - flushIcons(); - } - - function filterSidebarTree(query) { - const tree = document.getElementById("vault-tree"); - const items = tree.querySelectorAll(".tree-item"); - const containers = tree.querySelectorAll(".tree-children"); - - if (!query) { - items.forEach((item) => item.classList.remove("filtered-out")); - containers.forEach((c) => { - c.classList.remove("filtered-out"); - // Keep current collapsed state when clearing filter - }); - return; - } - - // First pass: mark all as filtered out - items.forEach((item) => item.classList.add("filtered-out")); - containers.forEach((c) => c.classList.add("filtered-out")); - - // Second pass: find matching items and mark them + ancestors + descendants - const matchingItems = new Set(); - - items.forEach((item) => { - const text = sidebarFilterCaseSensitive ? item.textContent : item.textContent.toLowerCase(); - const searchQuery = sidebarFilterCaseSensitive ? query : query.toLowerCase(); - if (text.includes(searchQuery)) { - matchingItems.add(item); - item.classList.remove("filtered-out"); - - // Show all ancestor containers - let parent = item.parentElement; - while (parent && parent !== tree) { - parent.classList.remove("filtered-out"); - if (parent.classList.contains("tree-children")) { - parent.classList.remove("collapsed"); - } - parent = parent.parentElement; - } - - // If this is a directory (has a children container after it), show all descendants - const nextEl = item.nextElementSibling; - if (nextEl && nextEl.classList.contains("tree-children")) { - nextEl.classList.remove("filtered-out"); - nextEl.classList.remove("collapsed"); - // Recursively show all children in this container - showAllDescendants(nextEl); - } - } - }); - - // Third pass: show items that are descendants of matching directories - // and ensure their containers are visible - matchingItems.forEach((item) => { - const nextEl = item.nextElementSibling; - if (nextEl && nextEl.classList.contains("tree-children")) { - const children = nextEl.querySelectorAll(".tree-item"); - children.forEach((child) => child.classList.remove("filtered-out")); - } - }); - } - - function showAllDescendants(container) { - const items = container.querySelectorAll(".tree-item"); - items.forEach((item) => { - item.classList.remove("filtered-out"); - // If this item has children, also show them - const nextEl = item.nextElementSibling; - if (nextEl && nextEl.classList.contains("tree-children")) { - nextEl.classList.remove("filtered-out"); - nextEl.classList.remove("collapsed"); - } - }); - // Also ensure all nested containers are visible - const nestedContainers = container.querySelectorAll(".tree-children"); - nestedContainers.forEach((c) => { - c.classList.remove("filtered-out"); - c.classList.remove("collapsed"); - }); - } - - function filterTagCloud(query) { - const tags = document.querySelectorAll("#tag-cloud .tag-item"); - tags.forEach((tag) => { - const text = sidebarFilterCaseSensitive ? tag.textContent : tag.textContent.toLowerCase(); - const searchQuery = sidebarFilterCaseSensitive ? query : query.toLowerCase(); - if (!query || text.includes(searchQuery)) { - tag.classList.remove("filtered-out"); - } else { - tag.classList.add("filtered-out"); - } - }); - } - - // --------------------------------------------------------------------------- - // Tag Filter Service - // --------------------------------------------------------------------------- - const TagFilterService = { - defaultFilters: [ - { pattern: "#<% ... %>", regex: "#<%.*%>", enabled: true }, - { pattern: "#{{ ... }}", regex: "#\\{\\{.*\\}\\}", enabled: true }, - { pattern: "#{ ... }", regex: "#\\{.*\\}", enabled: true }, - ], - - getConfig() { - const stored = localStorage.getItem("obsigate-tag-filters"); - if (stored) { - try { - return JSON.parse(stored); - } catch (e) { - return { tagFilters: this.defaultFilters }; - } - } - return { tagFilters: this.defaultFilters }; - }, - - saveConfig(config) { - localStorage.setItem("obsigate-tag-filters", JSON.stringify(config)); - }, - - patternToRegex(pattern) { - // 1. Escape ALL special regex characters - // We use a broader set including * and . - let regex = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - - // 2. Convert escaped '*' to '.*' (wildcard) - regex = regex.replace(/\\\*/g, ".*"); - - // 3. Convert escaped '...' (or any sequence of 2+ dots like ..) to '.*' - // We also handle optional whitespace around it to make it more user-friendly - regex = regex.replace(/\s*\\\.{2,}\s*/g, ".*"); - - return regex; - }, - - isTagFiltered(tag) { - const config = this.getConfig(); - const filters = config.tagFilters || this.defaultFilters; - const tagWithHash = `#${tag}`; - - for (const filter of filters) { - if (!filter.enabled) continue; - try { - // Robustly handle regex with or without ^/$ - let patternStr = filter.regex; - if (!patternStr.startsWith("^")) patternStr = "^" + patternStr; - if (!patternStr.endsWith("$")) patternStr = patternStr + "$"; - - const regex = new RegExp(patternStr); - if (regex.test(tagWithHash)) { - return true; - } - } catch (e) { - console.warn("Invalid regex:", filter.regex, e); - } - } - return false; - }, - - filterTags(tags) { - const filtered = {}; - Object.entries(tags).forEach(([tag, count]) => { - if (!this.isTagFiltered(tag)) { - filtered[tag] = count; - } - }); - return filtered; - }, - }; - - // --------------------------------------------------------------------------- - // Tags - // --------------------------------------------------------------------------- - async function loadTags() { - const data = await api("/api/tags"); - const filteredTags = TagFilterService.filterTags(data.tags); - renderTagCloud(filteredTags); - } - - function renderTagCloud(tags) { - const cloud = document.getElementById("tag-cloud"); - cloud.innerHTML = ""; - - const counts = Object.values(tags); - if (counts.length === 0) return; - - const maxCount = Math.max(...counts); - const minSize = 0.7; - const maxSize = 1.25; - - Object.entries(tags).forEach(([tag, count]) => { - const ratio = maxCount > 1 ? (count - 1) / (maxCount - 1) : 0; - const size = minSize + ratio * (maxSize - minSize); - const tagEl = el("span", { class: "tag-item", style: `font-size:${size}rem` }, [document.createTextNode(`#${tag}`)]); - tagEl.addEventListener("click", () => searchByTag(tag)); - cloud.appendChild(tagEl); - }); - } - - function addTagFilter(tag) { - if (!selectedTags.includes(tag)) { - selectedTags.push(tag); - performTagSearch(); - } - } - - function removeTagFilter(tag) { - selectedTags = selectedTags.filter((t) => t !== tag); - if (selectedTags.length > 0) { - performTagSearch(); - } else { - const input = document.getElementById("search-input"); - if (input.value.trim()) { - performAdvancedSearch(input.value.trim(), document.getElementById("vault-filter").value, null); - } else { - showWelcome(); - } - } - } - - function performTagSearch() { - const input = document.getElementById("search-input"); - const query = input.value.trim(); - const vault = document.getElementById("vault-filter").value; - performAdvancedSearch(query, vault, selectedTags.length > 0 ? selectedTags.join(",") : null); - } - - function buildSearchResultsHeader(data, query, tagFilter) { - const header = el("div", { class: "search-results-header" }); - const summaryText = el("span", { class: "search-results-summary-text" }); - - if (query && tagFilter) { - summaryText.textContent = `${data.count} résultat(s) pour "${query}" avec les tags`; - } else if (query) { - summaryText.textContent = `${data.count} résultat(s) pour "${query}"`; - } else if (tagFilter) { - summaryText.textContent = `${data.count} fichier(s) avec les tags`; - } else { - summaryText.textContent = `${data.count} résultat(s)`; - } - - header.appendChild(summaryText); - - if (selectedTags.length > 0) { - const activeTags = el("div", { class: "search-results-active-tags" }); - selectedTags.forEach((tag) => { - const removeBtn = el( - "button", - { - class: "search-results-active-tag-remove", - title: `Retirer ${tag} du filtre`, - "aria-label": `Retirer ${tag} du filtre`, - }, - [document.createTextNode("×")], - ); - removeBtn.addEventListener("click", (e) => { - e.stopPropagation(); - removeTagFilter(tag); - }); - - const chip = el("span", { class: "search-results-active-tag" }, [document.createTextNode(`#${tag}`), removeBtn]); - activeTags.appendChild(chip); - }); - header.appendChild(activeTags); - } - - return header; - } - - function searchByTag(tag) { - addTagFilter(tag); - } - - // --------------------------------------------------------------------------- - // File viewer - // --------------------------------------------------------------------------- - async function openFile(vaultName, filePath) { - currentVault = vaultName; - currentPath = filePath; - showingSource = false; - cachedRawSource = null; - - // Highlight active - syncActiveFileTreeItem(vaultName, filePath); - - // Show loading state while fetching - const area = document.getElementById("content-area"); - area.innerHTML = '
    Chargement...
    '; - - try { - const url = `/api/file/${encodeURIComponent(vaultName)}?path=${encodeURIComponent(filePath)}`; - const data = await api(url); - renderFile(data); - } catch (err) { - area.innerHTML = '

    Impossible de charger le fichier.

    '; - } - } - - async function renderBacklinksPanel(vault, path, container) { - try { - const data = await api(`/api/file/${encodeURIComponent(vault)}/backlinks?path=${encodeURIComponent(path)}`); - if (!data.backlinks || data.backlinks.length === 0) return; - - const panel = el("div", { class: "backlinks-panel" }); - const header = el("div", { class: "backlinks-header" }, [ - icon("link", 14), - document.createTextNode(` ${data.total} lien(s) entrant(s)`), - ]); - panel.appendChild(header); - - const list = el("div", { class: "backlinks-list" }); - data.backlinks.forEach((bl) => { - const item = el("div", { class: "backlink-item" }); - const vaultBadge = el("span", { class: "backlink-vault" }, [document.createTextNode(bl.vault)]); - const titleEl = el("span", { class: "backlink-title" }, [document.createTextNode(bl.title || bl.path.split("/").pop().replace(/\.md$/i, ""))]); - item.appendChild(icon(getFileIcon(bl.path), 12)); - item.appendChild(vaultBadge); - item.appendChild(titleEl); - item.addEventListener("click", () => TabManager.openPreview(bl.vault, bl.path)); - item.addEventListener("dblclick", (e) => { e.preventDefault(); TabManager.openPersistent(bl.vault, bl.path); }); - list.appendChild(item); - }); - panel.appendChild(list); - container.appendChild(panel); - } catch (err) { - // Silently ignore — backlinks are optional - console.debug("Backlinks fetch failed:", err); - } - } - - function renderFile(data) { - const area = document.getElementById("content-area"); - - // Handle unsupported (binary) files - if (data.unsupported) { - const sizeStr = data.size_bytes - ? data.size_bytes < 1024 ? `${data.size_bytes} o` - : data.size_bytes < 1048576 ? `${(data.size_bytes / 1024).toFixed(1)} Ko` - : `${(data.size_bytes / 1048576).toFixed(1)} Mo` - : ""; - area.innerHTML = ` -
    - -
    ${escapeHtml(data.path.split("/").pop())}
    -
    Ce fichier est binaire et ne peut pas être affiché.
    - ${sizeStr ? `
    Taille : ${sizeStr}
    ` : ""} - -
    `; - lucide.createIcons(); - document.getElementById("unsupported-download-btn").addEventListener("click", () => { - const dlUrl = `/api/file/${encodeURIComponent(data.vault)}/download?path=${encodeURIComponent(data.path)}`; - window.open(dlUrl, "_blank"); - }); - return; - } - - // Breadcrumb - const parts = data.path.split("/"); - const breadcrumbEls = []; - breadcrumbEls.push( - makeBreadcrumbSpan(data.vault, () => { - focusPathInSidebar(data.vault, "", { alignToTop: "center" }); - }), - ); - let accumulated = ""; - parts.forEach((part, i) => { - breadcrumbEls.push(el("span", { class: "sep" }, [document.createTextNode(" / ")])); - accumulated += (accumulated ? "/" : "") + part; - const p = accumulated; - if (i < parts.length - 1) { - breadcrumbEls.push( - makeBreadcrumbSpan(part, () => { - focusPathInSidebar(data.vault, p, { alignToTop: "center" }); - }), - ); - } else { - breadcrumbEls.push( - makeBreadcrumbSpan(part.replace(/\.md$/i, ""), () => { - focusPathInSidebar(data.vault, data.path, { alignToTop: "center" }); - }), - ); - } - }); - - const breadcrumb = el("div", { class: "breadcrumb" }, breadcrumbEls); - - // Tags - const tagsDiv = el("div", { class: "file-tags" }); - (data.tags || []).forEach((tag) => { - if (!TagFilterService.isTagFiltered(tag)) { - const t = el("span", { class: "file-tag" }, [document.createTextNode(`#${tag}`)]); - t.addEventListener("click", () => searchByTag(tag)); - tagsDiv.appendChild(t); - } - }); - - // Action buttons - const copyBtn = el("button", { class: "btn-action", title: "Copier la source" }, [icon("copy", 14), document.createTextNode("Copier")]); - copyBtn.addEventListener("click", async () => { - try { - // Fetch raw content if not already cached - if (!cachedRawSource) { - const rawUrl = `/api/file/${encodeURIComponent(data.vault)}/raw?path=${encodeURIComponent(data.path)}`; - const rawData = await api(rawUrl); - cachedRawSource = rawData.raw; - } - await navigator.clipboard.writeText(cachedRawSource); - copyBtn.lastChild.textContent = "Copié !"; - setTimeout(() => (copyBtn.lastChild.textContent = "Copier"), 1500); - } catch (err) { - console.error("Copy error:", err); - showToast("Erreur lors de la copie", "error"); - } - }); - - const sourceBtn = el("button", { class: "btn-action", title: "Voir la source" }, [icon("code", 14), document.createTextNode("Source")]); - - // MD download button - const mdBtn = el("button", { class: "btn-action", title: "Télécharger en .md" }, [icon("file-text", 14), document.createTextNode(".md")]); - mdBtn.addEventListener("click", () => { - const dlUrl = `/api/file/${encodeURIComponent(data.vault)}/download?path=${encodeURIComponent(data.path)}`; - const a = document.createElement("a"); - a.href = dlUrl; - a.download = data.path.split("/").pop(); - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - }); - - // PDF download button - const pdfBtn = el("button", { class: "btn-action", title: "Télécharger en PDF" }, [icon("file", 14), document.createTextNode("PDF")]); - pdfBtn.addEventListener("click", () => { - const pdfUrl = `/api/file/${encodeURIComponent(data.vault)}/pdf?path=${encodeURIComponent(data.path)}`; - window.open(pdfUrl, "_blank"); - }); - - const editBtn = el("button", { class: "btn-action", title: "Editer" }, [icon("edit", 14), document.createTextNode("Editer")]); - editBtn.addEventListener("click", () => { - openEditor(data.vault, data.path); - }); - - const forgeBtn = el("button", { class: "btn-action btn-forge", title: "Forge (nouvel editeur)" }, [icon("hammer", 14), document.createTextNode("Forge")]); - forgeBtn.addEventListener("click", () => { - var modal = document.getElementById("editor-modal"); - var titleEl = document.getElementById("editor-title"); - var bodyEl = document.getElementById("editor-body"); - titleEl.textContent = "Forge: " + data.path.split("/").pop(); - bodyEl.innerHTML = ""; - var iframe = document.createElement("iframe"); - iframe.id = "forge-iframe"; - iframe.src = "/editor-poc?vault=" + encodeURIComponent(data.vault) + "&path=" + encodeURIComponent(data.path) + "&_ts=" + Date.now(); - iframe.style.cssText = "width:100%;height:82vh;border:none;display:block;"; - bodyEl.appendChild(iframe); - modal.classList.add("active"); - safeCreateIcons(); - }); - - const openNewWindowBtn = el("button", { class: "btn-action", title: "Ouvrir dans une nouvelle fenetre" }, [icon("external-link", 14), document.createTextNode("pop-out")]); - openNewWindowBtn.addEventListener("click", () => { - const theme = document.documentElement.getAttribute('data-theme') || 'dark'; - const popoutUrl = `/popout/${encodeURIComponent(data.vault)}/${encodeURIComponent(data.path)}?theme=${theme}`; - window.open(popoutUrl, `popout_${data.vault}_${data.path.replace(/[^a-zA-Z0-9]/g, "_")}`, "width=1000,height=700,menubar=no,toolbar=no,location=no,status=no,resizable=yes,scrollbars=no"); - }); - - const tocBtn = el("button", { class: "btn-action", id: "toc-toggle-btn", title: "Afficher/Masquer le sommaire" }, [icon("list", 14), document.createTextNode("TOC")]); - tocBtn.addEventListener("click", () => { - RightSidebarManager.toggle(); - }); - - // Share button — check if already shared - const shareBtn = el("button", { class: "btn-action btn-share", title: "Partager ce document" }, [icon("share-2", 14), document.createTextNode("Partager")]); - // Check if already shared and color the button - (async () => { - try { - const shares = await api("/api/shares"); - if (shares.some(s => s.vault === data.vault && s.path === data.path)) { - shareBtn.classList.add("shared"); - shareBtn.title = "Document partagé — cliquer pour gérer"; - } - } catch (e) { /* ignore */ } - })(); - shareBtn.addEventListener("click", () => openShareDialog(data.vault, data.path)); - - // Bookmark button — check if already bookmarked - const bookmarkBtn = el("button", { class: "btn-action btn-bookmark", title: "Ajouter/Retirer des bookmarks" }, [icon("bookmark-plus", 14), document.createTextNode("Bookmark")]); - // Check bookmark status and color the button - (async () => { - try { - const bms = await api("/api/bookmarks"); - if (Array.isArray(bms) && bms.some(b => b.vault === data.vault && b.path === data.path)) { - bookmarkBtn.classList.add("active"); - bookmarkBtn.title = "Retirer des bookmarks"; - } - } catch (e) { /* ignore */ } - })(); - bookmarkBtn.addEventListener("click", async () => { - try { - const res = await api("/api/bookmarks/toggle", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ vault: data.vault, path: data.path, title: data.title }) }); - bookmarkBtn.classList.toggle("active", res.bookmarked); - bookmarkBtn.title = res.bookmarked ? "Retirer des bookmarks" : "Ajouter aux bookmarks"; - showToast(res.bookmarked ? "Ajouté aux bookmarks" : "Retiré des bookmarks", "success"); - if (typeof DashboardBookmarkWidget !== "undefined") DashboardBookmarkWidget.load(); - } catch (err) { showToast("Erreur: " + err.message, "error"); } - }); - - // Frontmatter — Accent Card - let fmSection = null; - if (data.frontmatter && Object.keys(data.frontmatter).length > 0) { - fmSection = buildFrontmatterCard(data.frontmatter); - } - - // Content container (rendered HTML) - const mdDiv = el("div", { class: "md-content", id: "file-rendered-content" }); - mdDiv.innerHTML = data.html; - - // Raw source container (hidden initially) - const rawDiv = el("div", { class: "raw-source-view", id: "file-raw-content", style: "display:none" }); - - // Source button toggle logic - sourceBtn.addEventListener("click", async () => { - const rendered = document.getElementById("file-rendered-content"); - const raw = document.getElementById("file-raw-content"); - if (!rendered || !raw) return; - - showingSource = !showingSource; - if (showingSource) { - sourceBtn.classList.add("active"); - if (!cachedRawSource) { - const rawUrl = `/api/file/${encodeURIComponent(data.vault)}/raw?path=${encodeURIComponent(data.path)}`; - const rawData = await api(rawUrl); - cachedRawSource = rawData.raw; - } - raw.textContent = cachedRawSource; - rendered.style.display = "none"; - raw.style.display = "block"; - } else { - sourceBtn.classList.remove("active"); - rendered.style.display = "block"; - raw.style.display = "none"; - } - }); - - // Assemble - area.innerHTML = ""; - area.appendChild(breadcrumb); - area.appendChild(el("div", { class: "file-header" }, [el("div", { class: "file-title" }, [document.createTextNode(data.title)]), tagsDiv, el("div", { class: "file-actions" }, [copyBtn, sourceBtn, mdBtn, pdfBtn, editBtn, forgeBtn, openNewWindowBtn, tocBtn, shareBtn, bookmarkBtn])])); - if (fmSection) area.appendChild(fmSection); - area.appendChild(mdDiv); - area.appendChild(rawDiv); - - // Backlinks panel - if (data.is_markdown) { - renderBacklinksPanel(data.vault, data.path, area); - } - - // Highlight code blocks - area.querySelectorAll("pre code").forEach((block) => { - safeHighlight(block); - }); - - // Wire up wikilinks - area.querySelectorAll(".wikilink").forEach((link) => { - link.addEventListener("click", (e) => { - e.preventDefault(); - const v = link.getAttribute("data-vault"); - const p = link.getAttribute("data-path"); - if (v && p) openFile(v, p); - }); - }); - - safeCreateIcons(); - area.scrollTop = 0; - - // Initialize outline/TOC for this document - OutlineManager.init(); - } - - // --------------------------------------------------------------------------- - // Recent files - // --------------------------------------------------------------------------- - let _recentRefreshTimer = null; - let _recentTimestampTimer = null; - let _recentFilesCache = []; - - // --------------------------------------------------------------------------- - // Dashboard Recent Files Widget - // --------------------------------------------------------------------------- - // ── Dashboard Stats Widget ── - const DashboardStatsWidget = { - async load() { - const grid = document.getElementById("dashboard-stats-grid"); - if (!grid) return; - grid.innerHTML = '
    Chargement...
    '; - try { - const data = await api("/api/dashboard"); - this.render(data); - } catch (err) { - grid.innerHTML = `
    Erreur: ${escapeHtml(err.message)}
    `; - } - }, - render(data) { - const grid = document.getElementById("dashboard-stats-grid"); - if (!grid) return; - const fmtSize = (bytes) => bytes < 1024 ? `${bytes} o` : bytes < 1048576 ? `${(bytes/1024).toFixed(1)} Ko` : bytes < 1073741824 ? `${(bytes/1048576).toFixed(1)} Mo` : `${(bytes/1073741824).toFixed(1)} Go`; - const items = [ - { icon: "files", label: "Fichiers", value: data.total_files.toLocaleString() }, - { icon: "tags", label: "Tags uniques", value: data.total_tags.toLocaleString() }, - { icon: "hard-drive", label: "Taille totale", value: fmtSize(data.total_size_bytes) }, - { icon: "folder-open", label: "Vaults", value: data.vaults.length.toString() }, - ]; - grid.innerHTML = items.map(i => ` -
    - - ${i.value} - ${i.label} -
    - `).join(""); - safeCreateIcons(); - } - }; - - // ── Dashboard Shared Widget ── - const DashboardSharedWidget = { - async load() { - const grid = document.getElementById("dashboard-shared-grid"); - const empty = document.getElementById("dashboard-shared-empty"); - if (!grid) return; - try { - const shares = await api("/api/shares"); - if (!shares.length) { if (empty) empty.style.display = ""; grid.innerHTML = ""; return; } - if (empty) empty.style.display = "none"; - grid.innerHTML = shares.map(s => ` -
    -
    - - ${escapeHtml(s.path.split("/").pop().replace(/\.md$/i, ""))} - ${escapeHtml(s.vault)} -
    -
    - ${s.access_count || 0} vue(s) - ${s.expires_at ? `Expire le ${new Date(s.expires_at).toLocaleDateString("fr-FR")}` : ""} -
    -
    - - - -
    -
    - `).join(""); - lucide.createIcons(); - grid.querySelectorAll(".shared-copy-btn").forEach(b => b.addEventListener("click", async (e) => { - e.stopPropagation(); - const url = b.dataset.url; - try { await navigator.clipboard.writeText(url); } catch { const ta = document.createElement("textarea"); ta.value=url; ta.style.position="fixed"; ta.style.left="-9999px"; document.body.appendChild(ta); ta.select(); document.execCommand("copy"); document.body.removeChild(ta); } - showToast("Lien copié !", "success"); - })); - grid.querySelectorAll(".shared-open-btn").forEach(b => b.addEventListener("click", (e) => { - e.stopPropagation(); - const card = b.closest(".shared-card"); - if (card) TabManager.openPreview(card.dataset.vault, card.dataset.path); - })); - grid.querySelectorAll(".shared-revoke-btn").forEach(b => b.addEventListener("click", async (e) => { - e.stopPropagation(); - await api(`/api/share/${b.dataset.id}`, { method: "DELETE" }); - showToast("Partage révoqué", "success"); - this.load(); - })); - grid.querySelectorAll(".shared-card").forEach(card => card.addEventListener("click", () => { - TabManager.openPreview(card.dataset.vault, card.dataset.path); - })); - } catch (err) { if (empty) empty.style.display = ""; } - } - }; - - // ── Dashboard Conflicts Widget ── - const DashboardConflictsWidget = { - async load() { - const container = document.getElementById("dashboard-conflicts-container"); - if (!container) return; - try { - const data = await api("/api/conflicts"); - if (data.total === 0) { container.innerHTML = ""; return; } - this.render(data.conflicts, container); - } catch (err) { container.innerHTML = ""; } - }, - render(conflicts, container) { - container.innerHTML = ` -
    -
    -
    - -

    Conflits de synchronisation

    - ${conflicts.length} -
    -
    -
    - ${conflicts.map(c => ` -
    -
    - ${escapeHtml(c.vault)} - ${escapeHtml(c.conflict_path.split("/").pop())} - Conflit du ${c.conflict_date.replace(/(\d{4})(\d{2})(\d{2})-(\d{2})(\d{2})/, "$3/$2/$1 $4:$5")} -
    -
    - - -
    -
    - `).join("")} -
    -
    `; - lucide.createIcons(); - container.querySelectorAll(".keep-local").forEach(btn => btn.addEventListener("click", () => this._resolve(btn.dataset, "keep_local"))); - container.querySelectorAll(".keep-conflict").forEach(btn => btn.addEventListener("click", () => this._resolve(btn.dataset, "keep_conflict"))); - }, - async _resolve(d, action) { - try { - await api("/api/conflicts/resolve", { method: "POST", body: JSON.stringify({ vault: d.vault, conflict_path: d.conflict, original_path: d.original, action }) }); - showToast("Conflit résolu", "success"); - this.load(); - } catch (err) { showToast("Erreur: " + err.message, "error"); } - } - }; - - const DashboardRecentWidget = { - _cache: [], - _currentFilter: "", - - async load(vaultFilter = "") { - const v = vaultFilter || selectedContextVault || "all"; - this._currentFilter = v; - this.showLoading(); - - let url = "/api/recent?mode=opened"; - if (v !== "all") url += `&vault=${encodeURIComponent(v)}`; - - try { - const data = await api(url); - this._cache = data.files || []; - this.render(); - } catch (err) { - console.error("Dashboard: Failed to load recent files:", err); - this.showError(); - } - }, - - async toggleBookmark(vault, path, title, card) { - try { - const data = await api("/api/bookmarks/toggle", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ vault, path, title }), - }); - - // Refresh both widgets to keep sync - DashboardBookmarkWidget.load(); - - // Update current card icon if it exists - if (card) { - const btn = card.querySelector(".dashboard-card-bookmark-btn"); - if (btn) { - btn.classList.toggle("active", data.bookmarked); - const icon = btn.querySelector("i"); - if (icon) icon.setAttribute("data-lucide", data.bookmarked ? "bookmark" : "bookmark-plus"); - safeCreateIcons(); - } - } - - // Check if we need to refresh the current list to reflect bookmark status across all cards - // To avoid flickering, just update the cache and re-render if needed or do a silent refresh - this._cache.forEach(f => { - if (f.vault === vault && f.path === path) f.bookmarked = data.bookmarked; - }); - } catch (err) { - console.error("Failed to toggle bookmark:", err); - showToast("Erreur lors de l'épinglage", "error"); - } - }, - - showLoading() { - const grid = document.getElementById("dashboard-recent-grid"); - const loading = document.getElementById("dashboard-loading"); - const empty = document.getElementById("dashboard-recent-empty"); - const count = document.getElementById("dashboard-count"); - - if (grid) grid.innerHTML = ""; - if (loading) loading.classList.add("active"); - if (empty) empty.classList.add("hidden"); - if (count) count.textContent = ""; - }, - - render() { - const grid = document.getElementById("dashboard-recent-grid"); - const loading = document.getElementById("dashboard-loading"); - const empty = document.getElementById("dashboard-recent-empty"); - const count = document.getElementById("dashboard-count"); - - if (loading) loading.classList.remove("active"); - - if (!this._cache || this._cache.length === 0) { - this.showEmpty(); - return; - } - - if (empty) empty.classList.add("hidden"); - if (count) count.textContent = `${this._cache.length} fichier${this._cache.length > 1 ? "s" : ""}`; - - if (!grid) return; - grid.innerHTML = ""; - - this._cache.forEach((f, index) => { - const card = this._createCard(f, index); - grid.appendChild(card); - }); - - safeCreateIcons(); - }, - - _createCard(file, index) { - const card = document.createElement("div"); - card.className = "dashboard-card"; - card.setAttribute("data-vault", file.vault); - card.setAttribute("data-path", file.path); - card.style.animationDelay = `${Math.min(index * 50, 400)}ms`; - - // Header with icon and vault badge - const header = document.createElement("div"); - header.className = "dashboard-card-header"; - - const iconContainer = document.createElement("div"); - iconContainer.className = "dashboard-card-icon"; - const fileIconName = getFileIcon(file.path); - try { - iconContainer.appendChild(icon(fileIconName, 24)); - } catch (e) { - console.error("Error creating icon:", fileIconName, e); - // Fallback to default file icon - iconContainer.appendChild(icon("file", 24)); - } - - const badge = document.createElement("span"); - badge.className = "dashboard-vault-badge"; - badge.textContent = file.vault; - - const bookmarkBtn = document.createElement("button"); - bookmarkBtn.className = `dashboard-card-bookmark-btn ${file.bookmarked ? "active" : ""}`; - bookmarkBtn.title = file.bookmarked ? "Retirer des bookmarks" : "Ajouter aux bookmarks"; - bookmarkBtn.innerHTML = ``; - - bookmarkBtn.addEventListener("click", (e) => { - e.stopPropagation(); - this.toggleBookmark(file.vault, file.path, file.title, card); - }); - - header.appendChild(iconContainer); - header.appendChild(badge); - header.appendChild(bookmarkBtn); - card.appendChild(header); - - // Title - const title = document.createElement("h3"); - title.className = "dashboard-card-title"; - title.textContent = file.title || file.path.split("/").pop(); - title.title = file.title || file.path; - card.appendChild(title); - - // Path (compact) - const pathParts = file.path.split("/"); - if (pathParts.length > 1) { - const path = document.createElement("div"); - path.className = "dashboard-card-path"; - path.textContent = pathParts.slice(0, -1).join(" / "); - path.title = file.path; - card.appendChild(path); - } - - // Footer with time and tags - const footer = document.createElement("div"); - footer.className = "dashboard-card-footer"; - - const time = document.createElement("span"); - time.className = "dashboard-card-time"; - time.innerHTML = ` ${file.mtime_human || this._humanizeDelta(file.mtime)}`; - - footer.appendChild(time); - - // Tags - if (file.tags && file.tags.length > 0) { - const tags = document.createElement("div"); - tags.className = "dashboard-card-tags"; - file.tags.slice(0, 3).forEach((tag) => { - const tagEl = document.createElement("span"); - tagEl.className = "tag-pill"; - tagEl.textContent = tag; - tags.appendChild(tagEl); - }); - footer.appendChild(tags); - } - - card.appendChild(footer); - - // Click handler - card.addEventListener("click", () => { - openFile(file.vault, file.path); - }); - - return card; - }, - - showEmpty() { - const grid = document.getElementById("dashboard-recent-grid"); - const loading = document.getElementById("dashboard-loading"); - const empty = document.getElementById("dashboard-recent-empty"); - const count = document.getElementById("dashboard-count"); - - if (grid) grid.innerHTML = ""; - if (loading) loading.classList.remove("active"); - if (empty) empty.classList.remove("hidden"); - if (count) count.textContent = "0 fichiers"; - safeCreateIcons(); - }, - - showError() { - this.showEmpty(); - const empty = document.getElementById("dashboard-recent-empty"); - if (empty) { - const msg = empty.querySelector("span"); - if (msg) msg.textContent = "Erreur de chargement"; - } - }, - - _humanizeDelta(mtime) { - const delta = Date.now() / 1000 - mtime; - if (delta < 60) return "à l'instant"; - if (delta < 3600) return `il y a ${Math.floor(delta / 60)} min`; - if (delta < 86400) return `il y a ${Math.floor(delta / 3600)} h`; - if (delta < 604800) return `il y a ${Math.floor(delta / 86400)} j`; - return new Date(mtime * 1000).toLocaleDateString("fr-FR", { day: "numeric", month: "short", year: "numeric" }); - }, - - populateVaultFilter() { - const select = document.getElementById("dashboard-vault-filter"); - if (!select) return; - - // Keep first option "Tous les vaults" - while (select.options.length > 1) select.remove(1); - - if (typeof allVaults !== "undefined" && Array.isArray(allVaults)) { - allVaults.forEach((v) => { - const opt = document.createElement("option"); - opt.value = v.name; - opt.textContent = v.name; - select.appendChild(opt); - }); - } - syncVaultSelectors(); - }, - - init() { - const select = document.getElementById("dashboard-vault-filter"); - if (select) { - select.addEventListener("change", async () => { - await setSelectedVaultContext(select.value, { focusVault: select.value !== "all" }); - }); - } - - this.populateVaultFilter(); - }, - }; - - // --------------------------------------------------------------------------- - // Dashboard Bookmarks Widget - // --------------------------------------------------------------------------- - const DashboardBookmarkWidget = { - _cache: [], - _currentFilter: "", - - async load(vaultFilter = "") { - const v = vaultFilter || selectedContextVault || "all"; - this._currentFilter = v; - this.showLoading(); - - let url = "/api/bookmarks"; - if (v !== "all") url += `?vault=${encodeURIComponent(v)}`; - - try { - const data = await api(url); - this._cache = data.files || []; - this.render(); - } catch (err) { - console.error("Dashboard: Failed to load bookmarks:", err); - this.showEmpty(); - } - }, - - showLoading() { - const grid = document.getElementById("dashboard-bookmarks-grid"); - const empty = document.getElementById("dashboard-bookmarks-empty"); - const section = document.getElementById("dashboard-bookmarks-section"); - - if (grid) grid.innerHTML = ""; - if (empty) empty.classList.add("hidden"); - }, - - render() { - const grid = document.getElementById("dashboard-bookmarks-grid"); - const empty = document.getElementById("dashboard-bookmarks-empty"); - const section = document.getElementById("dashboard-bookmarks-section"); - - if (!this._cache || this._cache.length === 0) { - if (grid) grid.innerHTML = ""; - if (empty) empty.classList.remove("hidden"); - return; - } - - if (empty) empty.classList.add("hidden"); - if (!grid) return; - grid.innerHTML = ""; - - this._cache.forEach((f, idx) => { - const card = DashboardRecentWidget._createCard(f, idx); - grid.appendChild(card); - }); - - safeCreateIcons(); - }, - - showEmpty() { - const grid = document.getElementById("dashboard-bookmarks-grid"); - const empty = document.getElementById("dashboard-bookmarks-empty"); - if (grid) grid.innerHTML = ""; - if (empty) empty.classList.remove("hidden"); - } - }; - - async function loadRecentFiles(vaultFilter) { - const listEl = document.getElementById("recent-list"); - const emptyEl = document.getElementById("recent-empty"); - if (!listEl) return; - - let url = "/api/recent?mode=modified"; - if (vaultFilter) url += `&vault=${encodeURIComponent(vaultFilter)}`; - try { - const data = await api(url); - _recentFilesCache = data.files || []; - renderRecentList(_recentFilesCache); - } catch (err) { - console.error("Failed to load recent files:", err); - listEl.innerHTML = ""; - if (emptyEl) { - emptyEl.classList.remove("hidden"); - } - } - } - - function renderRecentList(files) { - const listEl = document.getElementById("recent-list"); - const emptyEl = document.getElementById("recent-empty"); - if (!listEl) return; - listEl.innerHTML = ""; - - if (!files || files.length === 0) { - if (emptyEl) { - emptyEl.classList.remove("hidden"); - safeCreateIcons(); - } - return; - } - if (emptyEl) emptyEl.classList.add("hidden"); - - files.forEach((f) => { - const item = el("div", { class: "recent-item", "data-vault": f.vault, "data-path": f.path }); - - // Header row: time + vault badge - const header = el("div", { class: "recent-item-header" }); - const timeSpan = el("span", { class: "recent-time" }, [icon("clock", 11), document.createTextNode(f.mtime_human)]); - const badge = el("span", { class: "recent-vault-badge" }, [document.createTextNode(f.vault)]); - header.appendChild(timeSpan); - header.appendChild(badge); - item.appendChild(header); - - // Title - const titleEl = el("div", { class: "recent-item-title" }, [document.createTextNode(f.title || f.path.split("/").pop())]); - item.appendChild(titleEl); - - // Path breadcrumb - const pathParts = f.path.split("/"); - if (pathParts.length > 1) { - const pathEl = el("div", { class: "recent-item-path" }, [document.createTextNode(pathParts.slice(0, -1).join(" / "))]); - item.appendChild(pathEl); - } - - // Preview - if (f.preview) { - const previewEl = el("div", { class: "recent-item-preview" }, [document.createTextNode(f.preview)]); - item.appendChild(previewEl); - } - - // Tags - if (f.tags && f.tags.length > 0) { - const tagsEl = el("div", { class: "recent-item-tags" }); - f.tags.forEach((t) => { - tagsEl.appendChild(el("span", { class: "tag-pill" }, [document.createTextNode(t)])); - }); - item.appendChild(tagsEl); - } - - // Click handler - item.addEventListener("click", () => { - openFile(f.vault, f.path); - closeMobileSidebar(); - }); - - listEl.appendChild(item); - }); - safeCreateIcons(); - } - - function _humanizeDelta(mtime) { - const delta = Date.now() / 1000 - mtime; - if (delta < 60) return "à l'instant"; - if (delta < 3600) return `il y a ${Math.floor(delta / 60)} min`; - if (delta < 86400) return `il y a ${Math.floor(delta / 3600)} h`; - if (delta < 604800) return `il y a ${Math.floor(delta / 86400)} j`; - return new Date(mtime * 1000).toLocaleDateString("fr-FR", { day: "numeric", month: "short", year: "numeric" }); - } - - function _refreshRecentTimestamps() { - if (activeSidebarTab !== "recent" || !_recentFilesCache.length) return; - const items = document.querySelectorAll(".recent-item"); - items.forEach((item, i) => { - if (i < _recentFilesCache.length) { - const timeSpan = item.querySelector(".recent-time"); - if (timeSpan) { - // keep the icon, update text - const textNode = timeSpan.lastChild; - if (textNode && textNode.nodeType === Node.TEXT_NODE) { - textNode.textContent = _humanizeDelta(_recentFilesCache[i].mtime); - } - } - } - }); - } - - function _populateRecentVaultFilter() { - const select = document.getElementById("recent-vault-filter"); - if (!select) return; - // keep first option "Tous les vaults" - while (select.options.length > 1) select.remove(1); - allVaults.forEach((v) => { - const opt = document.createElement("option"); - opt.value = v.name; - opt.textContent = v.name; - select.appendChild(opt); - }); - syncVaultSelectors(); - } - - function initRecentTab() { - const select = document.getElementById("recent-vault-filter"); - if (select) { - select.addEventListener("change", async () => { - const val = select.value || "all"; - await setSelectedVaultContext(val, { focusVault: val !== "all" }); - }); - } - // Periodic timestamp refresh (every 60s) - _recentTimestampTimer = setInterval(_refreshRecentTimestamps, 60000); - } - - // --------------------------------------------------------------------------- - // Sidebar tabs - // --------------------------------------------------------------------------- - function initSidebarTabs() { - document.querySelectorAll(".sidebar-tab").forEach((tab) => { - tab.addEventListener("click", () => switchSidebarTab(tab.dataset.tab)); - }); - } - - function switchSidebarTab(tab) { - activeSidebarTab = tab; - document.querySelectorAll(".sidebar-tab").forEach((btn) => { - const isActive = btn.dataset.tab === tab; - btn.classList.toggle("active", isActive); - btn.setAttribute("aria-selected", isActive ? "true" : "false"); - }); - document.querySelectorAll(".sidebar-tab-panel").forEach((panel) => { - const isActive = panel.id === `sidebar-panel-${tab}`; - panel.classList.toggle("active", isActive); - }); - const filterInput = document.getElementById("sidebar-filter-input"); - if (filterInput) { - const placeholders = { vaults: "Filtrer fichiers...", tags: "Filtrer tags...", recent: "" }; - filterInput.placeholder = placeholders[tab] || ""; - } - const query = filterInput ? (sidebarFilterCaseSensitive ? filterInput.value.trim() : filterInput.value.trim().toLowerCase()) : ""; - if (query) { - if (tab === "vaults") performTreeSearch(query); - else if (tab === "tags") filterTagCloud(query); - } - // Auto-load recent files when switching to the recent tab - if (tab === "recent") { - _populateRecentVaultFilter(); - const vaultFilter = document.getElementById("recent-vault-filter"); - loadRecentFiles(vaultFilter ? vaultFilter.value || null : null); - } - } - - function initHelpModal() { - const openBtn = document.getElementById("help-open-btn"); - const closeBtn = document.getElementById("help-close"); - const modal = document.getElementById("help-modal"); - if (!openBtn || !closeBtn || !modal) return; - - openBtn.addEventListener("click", () => { - modal.classList.add("active"); - closeHeaderMenu(); - safeCreateIcons(); - initHelpNavigation(); - }); - - closeBtn.addEventListener("click", closeHelpModal); - modal.addEventListener("click", (e) => { - if (e.target === modal) { - closeHelpModal(); - } - }); - - document.addEventListener("keydown", (e) => { - if (e.key === "Escape" && modal.classList.contains("active")) { - closeHelpModal(); - } - }); - } - - function initEditorPocBtn() { - var btn = document.getElementById("editor-poc-btn"); - if (!btn) return; - btn.addEventListener("click", function() { - closeHeaderMenu(); - window.open("/editor-poc", "_blank"); - }); - } - - function initHelpNavigation() { - const helpContent = document.querySelector(".help-content"); - const helpBody = document.getElementById("help-body"); - const navLinks = document.querySelectorAll(".help-nav-link"); - - if (!helpContent || !helpBody || !navLinks.length) return; - - // Handle nav link clicks - navLinks.forEach((link) => { - link.addEventListener("click", (e) => { - e.preventDefault(); - const targetId = link.getAttribute("href").substring(1); - const targetSection = document.getElementById(targetId); - if (targetSection) { - targetSection.scrollIntoView({ behavior: "smooth", block: "start" }); - } - }); - }); - - // Scroll spy - update active nav link based on scroll position - const observer = new IntersectionObserver( - (entries) => { - entries.forEach((entry) => { - if (entry.isIntersecting) { - const id = entry.target.getAttribute("id"); - navLinks.forEach((link) => { - if (link.getAttribute("href") === `#${id}`) { - navLinks.forEach((l) => l.classList.remove("active")); - link.classList.add("active"); - } - }); - } - }); - }, - { - root: helpBody, - rootMargin: "-20% 0px -70% 0px", - threshold: 0, - }, - ); - - // Observe all sections - document.querySelectorAll(".help-section").forEach((section) => { - observer.observe(section); - }); - } - - function closeHelpModal() { - const modal = document.getElementById("help-modal"); - if (modal) modal.classList.remove("active"); - } - - function initConfigModal() { - const openBtn = document.getElementById("config-open-btn"); - const closeBtn = document.getElementById("config-close"); - const modal = document.getElementById("config-modal"); - const addBtn = document.getElementById("config-add-btn"); - const patternInput = document.getElementById("config-pattern-input"); - - if (!openBtn || !closeBtn || !modal) return; - - openBtn.addEventListener("click", async () => { - modal.classList.add("active"); - closeHeaderMenu(); - renderConfigFilters(); - loadConfigFields(); - loadDiagnostics(); - loadAbout(); - await loadHiddenFilesSettings(); - loadWebhooksUI(); - loadSharesUI(); - safeCreateIcons(); - }); - - closeBtn.addEventListener("click", closeConfigModal); - modal.addEventListener("click", (e) => { - if (e.target === modal) { - closeConfigModal(); - } - }); - - addBtn.addEventListener("click", addConfigFilter); - patternInput.addEventListener("keypress", (e) => { - if (e.key === "Enter") { - addConfigFilter(); - } - }); - - patternInput.addEventListener("input", updateRegexPreview); - - // Frontend config fields — save to localStorage on change - ["cfg-debounce", "cfg-results-per-page", "cfg-min-query", "cfg-timeout"].forEach((id) => { - const input = document.getElementById(id); - if (input) input.addEventListener("change", saveFrontendConfig); - }); - - // Backend save button - const saveBtn = document.getElementById("cfg-save-backend"); - if (saveBtn) saveBtn.addEventListener("click", saveBackendConfig); - - // Force reindex - const reindexBtn = document.getElementById("cfg-reindex"); - if (reindexBtn) reindexBtn.addEventListener("click", forceReindex); - - // Reset defaults - const resetBtn = document.getElementById("cfg-reset-defaults"); - if (resetBtn) resetBtn.addEventListener("click", resetConfigDefaults); - - // Refresh diagnostics - const diagBtn = document.getElementById("cfg-refresh-diag"); - if (diagBtn) diagBtn.addEventListener("click", loadDiagnostics); - - // Hidden files configuration - const saveHiddenBtn = document.getElementById("cfg-save-hidden-files"); - if (saveHiddenBtn) saveHiddenBtn.addEventListener("click", saveHiddenFilesSettings); - - document.addEventListener("keydown", (e) => { - if (e.key === "Escape" && modal.classList.contains("active")) { - closeConfigModal(); - } - }); - - // Load saved frontend config on startup - applyFrontendConfig(); - } - - function closeConfigModal() { - const modal = document.getElementById("config-modal"); - if (modal) modal.classList.remove("active"); - } - - // --- Config field helpers --- - const _FRONTEND_CONFIG_KEY = "obsigate-perf-config"; - - function _getFrontendConfig() { - try { - return JSON.parse(localStorage.getItem(_FRONTEND_CONFIG_KEY) || "{}"); - } catch { - return {}; - } - } - - function applyFrontendConfig() { - const cfg = _getFrontendConfig(); - if (cfg.debounce_ms) { - /* applied dynamically in debounce setTimeout */ - } - if (cfg.results_per_page) { - /* used as ADVANCED_SEARCH_LIMIT override */ - } - if (cfg.min_query_length) { - /* used as MIN_SEARCH_LENGTH override */ - } - if (cfg.search_timeout_ms) { - /* used as SEARCH_TIMEOUT_MS override */ - } - } - - function _getEffective(key, fallback) { - const cfg = _getFrontendConfig(); - return cfg[key] !== undefined ? cfg[key] : fallback; - } - - async function loadConfigFields() { - // Frontend fields from localStorage - const cfg = _getFrontendConfig(); - _setField("cfg-debounce", cfg.debounce_ms || 300); - _setField("cfg-results-per-page", cfg.results_per_page || 50); - _setField("cfg-min-query", cfg.min_query_length || 2); - _setField("cfg-timeout", cfg.search_timeout_ms || 30000); - - // Backend fields from API - try { - const data = await api("/api/config"); - _setField("cfg-workers", data.search_workers); - _setField("cfg-max-content", data.max_content_size); - _setField("cfg-title-boost", data.title_boost); - _setField("cfg-tag-boost", data.tag_boost); - _setField("cfg-prefix-exp", data.prefix_max_expansions); - _setField("cfg-recent-limit", data.recent_files_limit || 20); - // Watcher config - _setCheckbox("cfg-watcher-enabled", data.watcher_enabled !== false); - _setCheckbox("cfg-watcher-polling", data.watcher_use_polling === true); - _setField("cfg-watcher-interval", data.watcher_polling_interval || 5); - _setField("cfg-watcher-debounce", data.watcher_debounce || 2); - } catch (err) { - console.error("Failed to load backend config:", err); - } - } - - function _setField(id, value) { - const el = document.getElementById(id); - if (el && value !== undefined) el.value = value; - } - - function _setCheckbox(id, checked) { - const el = document.getElementById(id); - if (el) el.checked = !!checked; - } - - function _getCheckbox(id) { - const el = document.getElementById(id); - return el ? el.checked : false; - } - - function _getFieldNum(id, fallback) { - const el = document.getElementById(id); - if (!el) return fallback; - const v = parseFloat(el.value); - return isNaN(v) ? fallback : v; - } - - function saveFrontendConfig() { - const cfg = { - debounce_ms: _getFieldNum("cfg-debounce", 300), - results_per_page: _getFieldNum("cfg-results-per-page", 50), - min_query_length: _getFieldNum("cfg-min-query", 2), - search_timeout_ms: _getFieldNum("cfg-timeout", 30000), - }; - localStorage.setItem(_FRONTEND_CONFIG_KEY, JSON.stringify(cfg)); - showToast("Paramètres client sauvegardés", "success"); - } - - async function saveBackendConfig() { - const body = { - search_workers: _getFieldNum("cfg-workers", 2), - max_content_size: _getFieldNum("cfg-max-content", 100000), - title_boost: _getFieldNum("cfg-title-boost", 3.0), - tag_boost: _getFieldNum("cfg-tag-boost", 2.0), - prefix_max_expansions: _getFieldNum("cfg-prefix-exp", 50), - recent_files_limit: _getFieldNum("cfg-recent-limit", 20), - watcher_enabled: _getCheckbox("cfg-watcher-enabled"), - watcher_use_polling: _getCheckbox("cfg-watcher-polling"), - watcher_polling_interval: _getFieldNum("cfg-watcher-interval", 5.0), - watcher_debounce: _getFieldNum("cfg-watcher-debounce", 2.0), - }; - try { - const res = await fetch("/api/config", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(body), - }); - if (res.ok) { - showToast("Configuration backend sauvegardée", "success"); - } else { - const errorData = await res.json().catch(() => ({})); - showToast(errorData.detail || "Erreur de sauvegarde", "error"); - } - } catch (err) { - console.error("Failed to save backend config:", err); - showToast("Erreur de sauvegarde", "error"); - } - } - - async function forceReindex() { - const btn = document.getElementById("cfg-reindex"); - if (btn) { - btn.disabled = true; - btn.textContent = "Réindexation..."; - } - try { - await api("/api/index/reload"); - showToast("Réindexation terminée", "success"); - loadDiagnostics(); - await Promise.all([loadVaults(), loadTags()]); - } catch (err) { - console.error("Reindex error:", err); - showToast("Erreur de réindexation", "error"); - } finally { - if (btn) { - btn.disabled = false; - btn.textContent = "Forcer réindexation"; - } - } - } - - async function resetConfigDefaults() { - // Reset frontend - localStorage.removeItem(_FRONTEND_CONFIG_KEY); - // Reset backend - try { - await fetch("/api/config", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - search_workers: 2, - debounce_ms: 300, - results_per_page: 50, - min_query_length: 2, - search_timeout_ms: 30000, - max_content_size: 100000, - title_boost: 3.0, - path_boost: 1.5, - tag_boost: 2.0, - prefix_max_expansions: 50, - snippet_context_chars: 120, - max_snippet_highlights: 5, - }), - }); - } catch (err) { - console.error("Reset config error:", err); - } - loadConfigFields(); - showToast("Configuration réinitialisée", "success"); - } - - async function loadDiagnostics() { - const container = document.getElementById("config-diagnostics"); - if (!container) return; - container.innerHTML = '
    Chargement...
    '; - try { - const data = await api("/api/diagnostics"); - renderDiagnostics(container, data); - } catch (err) { - container.innerHTML = '
    Erreur de chargement
    '; - } - } - - function renderDiagnostics(container, data) { - container.innerHTML = ""; - const sections = [ - { - title: "Index", - rows: [ - ["Fichiers indexés", data.index.total_files], - ["Tags uniques", data.index.total_tags], - ["Vaults", Object.keys(data.index.vaults).join(", ")], - ], - }, - { - title: "Index inversé", - rows: [ - ["Tokens uniques", data.inverted_index.unique_tokens.toLocaleString()], - ["Postings total", data.inverted_index.total_postings.toLocaleString()], - ["Documents", data.inverted_index.documents], - ["Mémoire estimée", data.inverted_index.memory_estimate_mb + " MB"], - ["Stale", data.inverted_index.is_stale ? "Oui" : "Non"], - ], - }, - { - title: "Moteur de recherche", - rows: [ - ["Executor actif", data.search_executor.active ? "Oui" : "Non"], - ["Workers max", data.search_executor.max_workers], - ], - }, - ]; - sections.forEach((section) => { - const div = document.createElement("div"); - div.className = "config-diag-section"; - const title = document.createElement("div"); - title.className = "config-diag-section-title"; - title.textContent = section.title; - div.appendChild(title); - section.rows.forEach(([label, value]) => { - const row = document.createElement("div"); - row.className = "config-diag-row"; - row.innerHTML = `${label}${value}`; - div.appendChild(row); - }); - container.appendChild(div); - }); - } - - // --- About Section --- - - function loadAbout() { - const container = document.getElementById("config-about"); - if (!container) return; - - // Fetch health info for version - api("/api/health").then((health) => { - container.innerHTML = ""; - - const sections = [ - { - title: "Application", - rows: [ - ["Nom", "ObsiGate"], - ["Version", APP_VERSION], - ["Version API", health.version || "—"], - ["Statut", health.status || "—"], - ], - }, - { - title: "Environnement", - rows: [ - ["Vaults configurés", health.vaults || "—"], - ["Fichiers indexés", health.total_files || "—"], - ["Navigateur", navigator.userAgent.split(" ").pop()], - ["Plateforme", navigator.platform || "—"], - ["Langue", navigator.language || "—"], - ], - }, - { - title: "Composants", - rows: [ - ["Backend", "FastAPI (Python)"], - ["Rendu Markdown", "mistune"], - ["Surveillance fichiers", "watchdog"], - ["Frontend", "Vanilla JavaScript"], - ["Icônes", "Lucide Icons"], - ["Coloration syntaxe", "highlight.js"], - ["Éditeur", "CodeMirror 6"], - ], - }, - ]; - - sections.forEach((section) => { - const div = document.createElement("div"); - div.className = "config-diag-section"; - const title = document.createElement("div"); - title.className = "config-diag-section-title"; - title.textContent = section.title; - div.appendChild(title); - section.rows.forEach(([label, value]) => { - const row = document.createElement("div"); - row.className = "config-diag-row"; - row.innerHTML = `${label}${value}`; - div.appendChild(row); - }); - container.appendChild(div); - }); - }).catch(() => { - container.innerHTML = '
    Erreur de chargement
    '; - }); - } - - // --- Hidden Files Configuration --- - - async function loadHiddenFilesSettings() { - const container = document.getElementById("hidden-files-vault-list"); - if (!container) return; - - container.innerHTML = '
    Chargement...
    '; - - try { - const settings = await api("/api/vaults/settings/all"); - renderHiddenFilesSettings(container, settings); - } catch (err) { - console.error("Failed to load hidden files settings:", err); - container.innerHTML = '
    Erreur de chargement
    '; - } - } - - function renderHiddenFilesSettings(container, allSettings) { - container.innerHTML = ""; - - if (!allVaults || allVaults.length === 0) { - container.innerHTML = '
    Aucun vault configuré
    '; - return; - } - - allVaults.forEach((vault) => { - const settings = allSettings[vault.name] || { hideHiddenFiles: false }; - - const vaultCard = el("div", { class: "hidden-files-vault-card", "data-vault": vault.name }); - - // Vault header - const header = el("div", { class: "hidden-files-vault-header" }, [el("h3", {}, [document.createTextNode(vault.name)]), el("span", { class: "hidden-files-vault-type" }, [document.createTextNode(vault.type || "VAULT")])]); - - // Hide hidden files toggle - const toggleRow = el("div", { class: "config-row" }, [ - el("label", { class: "config-label", for: `hide-hidden-${vault.name}` }, [document.createTextNode("Masquer les fichiers/dossiers cachés")]), - el("label", { class: "config-toggle" }, [ - el("input", { - type: "checkbox", - id: `hide-hidden-${vault.name}`, - "data-vault": vault.name, - checked: settings.hideHiddenFiles ? "true" : false, - }), - el("span", { class: "config-toggle-slider" }), - ]), - el("span", { class: "config-hint" }, [document.createTextNode("Masquer les fichiers/dossiers commençant par un point dans l'interface (ils restent indexés et cherchables)")]), - ]); - - vaultCard.appendChild(header); - vaultCard.appendChild(toggleRow); - - container.appendChild(vaultCard); - }); - } - - async function saveHiddenFilesSettings() { - const btn = document.getElementById("cfg-save-hidden-files"); - if (btn) { - btn.disabled = true; - btn.textContent = "Sauvegarde..."; - } - - try { - const vaultCards = document.querySelectorAll(".hidden-files-vault-card"); - const promises = []; - - vaultCards.forEach((card) => { - const vaultName = card.dataset.vault; - const hideHiddenFiles = document.getElementById(`hide-hidden-${vaultName}`)?.checked || false; - - const settings = { - hideHiddenFiles, - }; - - promises.push( - api(`/api/vaults/${encodeURIComponent(vaultName)}/settings`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(settings), - }), - ); - }); - - await Promise.all(promises); - - // Reload vault settings to update the cache - await loadVaultSettings(); - - showToast("✓ Paramètres sauvegardés", "success"); - - // Refresh the UI to apply the filter - await Promise.all([refreshSidebarTreePreservingState(), refreshTagsForContext()]); - } catch (err) { - console.error("Failed to save hidden files settings:", err); - const errorMsg = err.message || "Erreur inconnue"; - showToast(`Erreur: ${errorMsg}`, "error"); - } finally { - if (btn) { - btn.disabled = false; - btn.textContent = "💾 Sauvegarder"; - } - } - } - - // ── Webhooks UI ── - async function loadWebhooksUI() { - const list = document.getElementById("webhooks-list"); - if (!list) return; - try { - const webhooks = await api("/api/webhooks"); - renderWebhooksUI(webhooks); - } catch { list.innerHTML = '
    Admin uniquement
    '; } - } - function renderWebhooksUI(webhooks) { - const list = document.getElementById("webhooks-list"); - if (!list) return; - if (!webhooks.length) { list.innerHTML = '
    Aucun webhook configuré.
    '; return; } - list.innerHTML = webhooks.map(w => ` -
    - ${escapeHtml(w.name)} - ${escapeHtml(w.url)} - ${(w.events||[]).join(", ")} - -
    - `).join(""); - list.querySelectorAll(".webhook-delete").forEach(b => b.addEventListener("click", async () => { - await api(`/api/webhooks/${b.dataset.id}`, { method: "DELETE" }); - loadWebhooksUI(); - })); - } - document.addEventListener("click", function(e) { - if (e.target.id === "webhook-add-btn") { - const name = document.getElementById("webhook-name-input").value.trim(); - const url = document.getElementById("webhook-url-input").value.trim(); - if (!url) { showToast("URL requise", "error"); return; } - api("/api/webhooks", { method: "POST", body: JSON.stringify({ name: name || "Webhook", url, events: ["file_created","file_deleted","file_modified","file_renamed"] }) }).then(() => { loadWebhooksUI(); document.getElementById("webhook-name-input").value = ""; document.getElementById("webhook-url-input").value = ""; }).catch(err => showToast(err.message, "error")); - } - }); - - // ── Shares UI ── - async function loadSharesUI() { - const list = document.getElementById("shares-list"); - if (!list) return; - try { - const shares = await api("/api/shares"); - renderSharesUI(shares); - } catch { list.innerHTML = '
    Chargement...
    '; } - } - function renderSharesUI(shares) { - const list = document.getElementById("shares-list"); - if (!list) return; - if (!shares.length) { list.innerHTML = '
    Aucun partage actif.
    '; return; } - list.innerHTML = shares.map(s => ` - - `).join(""); - list.querySelectorAll(".share-revoke").forEach(b => b.addEventListener("click", async () => { - await api(`/api/share/${b.dataset.id}`, { method: "DELETE" }); - loadSharesUI(); - })); - } - - // ── Share Dialog (professional) ── - async function openShareDialog(vault, path) { - // First check if already shared - let existingShare = null; - try { - const shares = await api("/api/shares"); - existingShare = shares.find(s => s.vault === vault && s.path === path); - } catch (e) { /* ignore */ } - - const div = document.createElement("div"); - div.className = "share-dialog-overlay"; - - const renderContent = () => { - if (existingShare) { - const url = window.location.origin + existingShare.url; - const expiresInfo = existingShare.expires_at - ? `

    Expire le ${new Date(existingShare.expires_at).toLocaleDateString("fr-FR")}

    ` - : '

    Sans expiration

    '; - div.innerHTML = ` - `; - div.querySelector(".share-copy-btn").addEventListener("click", async () => { - try { - await navigator.clipboard.writeText(url); - } catch (e) { - // Fallback for non-HTTPS contexts - const ta = document.createElement("textarea"); - ta.value = url; ta.style.position = "fixed"; ta.style.left = "-9999px"; - document.body.appendChild(ta); ta.select(); document.execCommand("copy"); - document.body.removeChild(ta); - } - showToast("Lien copié !", "success"); - div.remove(); - }); - div.querySelector(".share-revoke-btn").addEventListener("click", async () => { - try { - await api(`/api/share/${existingShare.id}`, { method: "DELETE" }); - showToast("Partage révoqué", "success"); - existingShare = null; - renderContent(); - } catch (err) { showToast("Erreur: " + err.message, "error"); } - }); - } else { - div.innerHTML = ` - `; - div.querySelector(".share-create-btn").addEventListener("click", async () => { - try { - const expiry = document.getElementById("share-expiry")?.value; - const share = await api(`/api/share/${encodeURIComponent(vault)}`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ path, expires_in_hours: expiry ? parseInt(expiry) : null }), - }); - existingShare = share; - renderContent(); - showToast("Lien créé !", "success"); - } catch (err) { showToast("Erreur: " + err.message, "error"); } - }); - } - div.querySelector(".share-close-btn").addEventListener("click", () => div.remove()); - div.addEventListener("click", (e) => { if (e.target === div) div.remove(); }); - }; - - renderContent(); - document.body.appendChild(div); - } - - function renderConfigFilters() { - const config = TagFilterService.getConfig(); - const filters = config.tagFilters || TagFilterService.defaultFilters; - const container = document.getElementById("config-filters-list"); - - container.innerHTML = ""; - - filters.forEach((filter, index) => { - const badge = el("div", { class: `config-filter-badge ${!filter.enabled ? "disabled" : ""}` }, [ - el("span", {}, [document.createTextNode(filter.pattern)]), - el( - "button", - { - class: "config-filter-toggle", - title: filter.enabled ? "Désactiver" : "Activer", - type: "button", - }, - [document.createTextNode(filter.enabled ? "✓" : "○")], - ), - el( - "button", - { - class: "config-filter-remove", - title: "Supprimer", - type: "button", - }, - [document.createTextNode("×")], - ), - ]); - - const toggleBtn = badge.querySelector(".config-filter-toggle"); - const removeBtn = badge.querySelector(".config-filter-remove"); - - toggleBtn.addEventListener("click", (e) => { - e.stopPropagation(); - toggleConfigFilter(index); - }); - - removeBtn.addEventListener("click", (e) => { - e.stopPropagation(); - removeConfigFilter(index); - }); - - container.appendChild(badge); - }); - } - - function toggleConfigFilter(index) { - const config = TagFilterService.getConfig(); - const filters = config.tagFilters || TagFilterService.defaultFilters; - if (filters[index]) { - filters[index].enabled = !filters[index].enabled; - config.tagFilters = filters; - TagFilterService.saveConfig(config); - renderConfigFilters(); - refreshTagsForContext().catch((err) => console.error("Error refreshing tags:", err)); - } - } - - function removeConfigFilter(index) { - const config = TagFilterService.getConfig(); - let filters = config.tagFilters || TagFilterService.defaultFilters; - filters = filters.filter((_, i) => i !== index); - config.tagFilters = filters; - TagFilterService.saveConfig(config); - renderConfigFilters(); - refreshTagsForContext().catch((err) => console.error("Error refreshing tags:", err)); - } - - function addConfigFilter() { - const input = document.getElementById("config-pattern-input"); - const pattern = input.value.trim(); - - if (!pattern) return; - - const regex = TagFilterService.patternToRegex(pattern); - const config = TagFilterService.getConfig(); - const filters = config.tagFilters || TagFilterService.defaultFilters; - - const newFilter = { pattern, regex, enabled: true }; - filters.push(newFilter); - config.tagFilters = filters; - TagFilterService.saveConfig(config); - - input.value = ""; - renderConfigFilters(); - refreshTagsForContext().catch((err) => console.error("Error refreshing tags:", err)); - updateRegexPreview(); - } - - function updateRegexPreview() { - const input = document.getElementById("config-pattern-input"); - const preview = document.getElementById("config-regex-preview"); - const code = document.getElementById("config-regex-code"); - const pattern = input.value.trim(); - - if (pattern) { - const regex = TagFilterService.patternToRegex(pattern); - code.textContent = `^${regex}$`; - preview.style.display = "block"; - } else { - preview.style.display = "none"; - } - } - - // --------------------------------------------------------------------------- - // Search (enhanced with autocomplete, keyboard nav, global shortcuts) - // --------------------------------------------------------------------------- - // ── Search toggle state ── - - function initSearch() { - const input = document.getElementById("search-input"); - if (!input) return; - const caseBtn = document.getElementById("rb-case"); - const wordBtn = document.getElementById("rb-word"); - const regexBtn = document.getElementById("rb-regex"); - const filterBtn = document.getElementById("search-filter-btn"); - const clearBtn = document.getElementById("search-clear-btn"); - const filterRow = document.getElementById("search-filter-row"); - const prevBtn = document.getElementById("rb-prev"); - const nextBtn = document.getElementById("rb-next"); - const countEl = document.getElementById("rb-count"); - const resultsBar = document.getElementById("results-bar"); - - function _showResultsBar() { if (resultsBar) resultsBar.style.display = 'flex'; } - function _hideResultsBar() { if (resultsBar) resultsBar.style.display = 'none'; } - - function _updateToggleUI() { - if (caseBtn) caseBtn.classList.toggle("active", searchCaseSensitive); - if (wordBtn) wordBtn.classList.toggle("active", searchWholeWord); - if (regexBtn) regexBtn.classList.toggle("active", searchRegex); - if (filterBtn) filterBtn.classList.toggle("active", searchFilterVisible); - } - - // Toggle buttons - if (caseBtn) caseBtn.addEventListener("click", () => { searchCaseSensitive = !searchCaseSensitive; _updateToggleUI(); _research(); }); - if (wordBtn) wordBtn.addEventListener("click", () => { searchWholeWord = !searchWholeWord; _updateToggleUI(); _research(); }); - if (regexBtn) regexBtn.addEventListener("click", () => { searchRegex = !searchRegex; _updateToggleUI(); _research(); }); - if (filterBtn) filterBtn.addEventListener("click", () => { searchFilterVisible = !searchFilterVisible; if (filterRow) filterRow.style.display = searchFilterVisible ? "flex" : "none"; _updateToggleUI(); }); - - // ── Result navigation (up/down arrows + Enter) ── - let _searchResultIdx = -1; - let _searchResultItems = []; - - function _updateResultHighlight() { - _searchResultItems.forEach((el, i) => { - el.classList.toggle("search-result-active", i === _searchResultIdx); - }); - if (_searchResultIdx >= 0 && _searchResultIdx < _searchResultItems.length) { - _searchResultItems[_searchResultIdx].scrollIntoView({ block: "nearest", behavior: "smooth" }); - } - const countEl = document.getElementById("rb-count"); - if (countEl) countEl.textContent = _searchResultIdx >= 0 ? `${_searchResultIdx + 1}/${_searchResultItems.length}` : `0/${_searchResultItems.length}`; - } - - function _refreshResultItems() { - _searchResultItems = Array.from(document.querySelectorAll(".search-result-item")); - _searchResultIdx = _searchResultItems.length > 0 ? 0 : -1; - _updateResultHighlight(); - if (_searchResultItems.length > 0) _showResultsBar(); else _hideResultsBar(); - } - - window.navigateSearchResults = function(delta) { - _searchResultItems = Array.from(document.querySelectorAll(".search-result-item")); - if (_searchResultItems.length === 0) return; - _searchResultIdx = Math.max(0, Math.min(_searchResultItems.length - 1, _searchResultIdx + delta)); - _updateResultHighlight(); - }; - - if (prevBtn) prevBtn.addEventListener("click", () => navigateSearchResults(-1)); - if (nextBtn) nextBtn.addEventListener("click", () => navigateSearchResults(1)); - - function _research() { - const q = input.value.trim(); - if (q.length >= _getEffective("min_query_length", 2)) { - clearTimeout(searchTimeout); - searchTimeout = setTimeout(() => { - const vault = document.getElementById("vault-filter").value; - const tagFilter = selectedTags.length > 0 ? selectedTags.join(",") : null; - advancedSearchOffset = 0; - performAdvancedSearch(q, vault, tagFilter); - }, _getEffective("debounce_ms", 300)); - } - } - - // Keyboard shortcuts - document.addEventListener("keydown", (e) => { - if (e.altKey && !e.ctrlKey && !e.metaKey) { - if (e.key === "c" || e.key === "C") { e.preventDefault(); caseBtn.click(); } - else if (e.key === "w" || e.key === "W") { e.preventDefault(); if (wordBtn) wordBtn.click(); } - else if (e.key === "r" || e.key === "R") { e.preventDefault(); if (regexBtn) regexBtn.click(); } - else if (e.key === "f" || e.key === "F") { e.preventDefault(); if (filterBtn) filterBtn.click(); input.focus(); } - } - }); - - // Initialize sub-controllers - AutocompleteDropdown.init(); - SearchChips.init(); - - // Initially hide clear button - if (clearBtn) clearBtn.style.display = "none"; - - // --- Input handler: autocomplete dropdown only (search triggered on Enter or selection) --- - input.addEventListener("input", () => { - const hasText = input.value.length > 0; - clearBtn.style.display = hasText ? "flex" : "none"; - - // Show autocomplete dropdown while typing - AutocompleteDropdown.populate(input.value, input.selectionStart); - - // Clear results when input becomes empty - if (!hasText) { - SearchChips.clear(); - showWelcome(); - } - }); - - // --- Focus handler: show history dropdown --- - input.addEventListener("focus", () => { - if (input.value.length === 0) { - const historyItems = SearchHistory.filter("").slice(0, 5); - if (historyItems.length > 0) { - AutocompleteDropdown.populate("", 0); - } - } - }); - - // --- Keyboard navigation in dropdown --- - input.addEventListener("keydown", (e) => { - if (AutocompleteDropdown.isVisible()) { - if (e.key === "ArrowDown") { - e.preventDefault(); - AutocompleteDropdown.navigateDown(); - } else if (e.key === "ArrowUp") { - e.preventDefault(); - AutocompleteDropdown.navigateUp(); - } else if (e.key === "Enter") { - // First: check dropdown suggestions (higher priority than search results) - if (AutocompleteDropdown.selectActive()) { - e.preventDefault(); - return; - } - // Second: navigate search results if visible - const results = document.querySelectorAll(".search-result-item"); - if (results.length > 0 && _searchResultIdx >= 0) { - const el = results[_searchResultIdx]; - if (el) { - const vault = el.dataset.vault; - const path = el.dataset.path; - if (vault && path) { TabManager.openPreview(vault, path); e.preventDefault(); return; } - } - } - // Third: execute search - AutocompleteDropdown.hide(); - const q = input.value.trim(); - if (q) { - SearchHistory.add(q); - clearTimeout(searchTimeout); - advancedSearchOffset = 0; - const vault = document.getElementById("vault-filter").value; - const tagFilter = selectedTags.length > 0 ? selectedTags.join(",") : null; - performAdvancedSearch(q, vault, tagFilter); - } - e.preventDefault(); - } else if (e.key === "Escape") { - AutocompleteDropdown.hide(); - e.stopPropagation(); - } - } else { - // Dropdown not visible: navigate search results or execute search - if (e.key === "ArrowDown") { - if (window.navigateSearchResults) { window.navigateSearchResults(1); e.preventDefault(); } - } else if (e.key === "ArrowUp") { - if (window.navigateSearchResults) { window.navigateSearchResults(-1); e.preventDefault(); } - } else if (e.key === "Enter") { - const q = input.value.trim(); - if (q) { - SearchHistory.add(q); - clearTimeout(searchTimeout); - advancedSearchOffset = 0; - const vault = document.getElementById("vault-filter").value; - const tagFilter = selectedTags.length > 0 ? selectedTags.join(",") : null; - performAdvancedSearch(q, vault, tagFilter); - } - e.preventDefault(); - } - } - }); - - clearBtn.addEventListener("click", () => { - input.value = ""; - if (clearBtn) clearBtn.style.display = "none"; - searchCaseSensitive = false; - searchWholeWord = false; - searchRegex = false; - _updateToggleUI(); - SearchChips.clear(); - AutocompleteDropdown.hide(); - showWelcome(); - }); - - // --- Global keyboard shortcuts --- - document.addEventListener("keydown", (e) => { - // Ctrl+K or Cmd+K: focus search - if ((e.ctrlKey || e.metaKey) && e.key === "k") { - e.preventDefault(); - input.focus(); - input.select(); - } - // "/" key: focus search (when not in an input/textarea) - if (e.key === "/" && !_isInputFocused()) { - e.preventDefault(); - input.focus(); - } - // Escape: blur search input and close dropdown - if (e.key === "Escape" && document.activeElement === input) { - AutocompleteDropdown.hide(); - input.blur(); - } - }); - } - - /** Check if user is focused on an input/textarea/contenteditable */ - function _isInputFocused() { - const tag = document.activeElement?.tagName; - if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true; - return document.activeElement?.isContentEditable === true; - } - - // --- Backward-compatible search (existing /api/search endpoint) --- - async function performSearch(query, vaultFilter, tagFilter) { - if (searchAbortController) searchAbortController.abort(); - searchAbortController = new AbortController(); - const searchId = ++currentSearchId; - showLoading(); - let url = `/api/search?q=${encodeURIComponent(query)}&vault=${encodeURIComponent(vaultFilter)}`; - if (tagFilter) url += `&tag=${encodeURIComponent(tagFilter)}`; - try { - const data = await api(url, { signal: searchAbortController.signal }); - if (searchId !== currentSearchId) return; - renderSearchResults(data, query, tagFilter); - } catch (err) { - if (err.name === "AbortError") return; - if (searchId !== currentSearchId) return; - showWelcome(); - } finally { - hideProgressBar(); - if (searchId === currentSearchId) searchAbortController = null; - } - } - - // --- Advanced search with TF-IDF, facets, pagination --- - async function performAdvancedSearch(query, vaultFilter, tagFilter, offset, sort) { - if (searchAbortController) searchAbortController.abort(); - searchAbortController = new AbortController(); - const searchId = ++currentSearchId; - showLoading(); - - const ofs = offset !== undefined ? offset : advancedSearchOffset; - const sortBy = sort || advancedSearchSort; - advancedSearchLastQuery = query; - - // Update chips from parsed query - const parsed = QueryParser.parse(query); - SearchChips.update(parsed); - - const effectiveLimit = _getEffective("results_per_page", ADVANCED_SEARCH_LIMIT); - let url = `/api/search/advanced?q=${encodeURIComponent(query)}&vault=${encodeURIComponent(vaultFilter)}&limit=${effectiveLimit}&offset=${ofs}&sort=${sortBy}`; - if (tagFilter) url += `&tag=${encodeURIComponent(tagFilter)}`; - if (searchCaseSensitive) url += "&case_sensitive=true"; - if (searchWholeWord) url += "&whole_word=true"; - if (searchRegex) url += "®ex=true"; - const includeEl = document.getElementById("search-include-input"); - const excludeEl = document.getElementById("search-exclude-input"); - if (includeEl?.value.trim()) url += `&include_paths=${encodeURIComponent(includeEl.value.trim())}`; - if (excludeEl?.value.trim()) url += `&exclude_paths=${encodeURIComponent(excludeEl.value.trim())}`; - - // Search timeout — abort if server takes too long - const timeoutId = setTimeout( - () => { - if (searchAbortController) searchAbortController.abort(); - }, - _getEffective("search_timeout_ms", SEARCH_TIMEOUT_MS), - ); - - try { - const data = await api(url, { signal: searchAbortController.signal }); - clearTimeout(timeoutId); - if (searchId !== currentSearchId) return; - advancedSearchTotal = data.total; - advancedSearchOffset = ofs; - renderAdvancedSearchResults(data, query, tagFilter); - } catch (err) { - clearTimeout(timeoutId); - if (err.name === "AbortError") return; - if (searchId !== currentSearchId) return; - showWelcome(); - } finally { - hideProgressBar(); - if (searchId === currentSearchId) searchAbortController = null; - } - } - - // --- Legacy search results renderer (kept for backward compat) --- - function renderSearchResults(data, query, tagFilter) { - const area = document.getElementById("content-area"); - area.innerHTML = ""; - const header = buildSearchResultsHeader(data, query, tagFilter); - area.appendChild(header); - if (data.results.length === 0) { - area.appendChild(el("p", { style: "color:var(--text-muted);margin-top:20px" }, [document.createTextNode("Aucun résultat trouvé.")])); - return; - } - const container = el("div", { class: "search-results" }); - data.results.forEach((r) => { - // Apply client-side filtering for hidden files - if (!shouldDisplayPath(r.path, r.vault)) { - return; // Skip this result - } - - const titleDiv = el("div", { class: "search-result-title" }); - if (query && query.trim()) { - highlightSearchText(titleDiv, r.title, query, searchCaseSensitive); - } else { - titleDiv.textContent = r.title; - } - const snippetDiv = el("div", { class: "search-result-snippet" }); - if (r.snippet && r.snippet.includes("")) { - snippetDiv.innerHTML = r.snippet; - } else if (query && query.trim() && r.snippet) { - highlightSearchText(snippetDiv, r.snippet, query, searchCaseSensitive); - } else { - snippetDiv.textContent = r.snippet || ""; - } - const item = el("div", { class: "search-result-item", "data-vault": r.vault, "data-path": r.path }, [ - el("span", { class: "search-result-ext" }, [document.createTextNode(r.extension || (r.path || "").split(".").pop() || "")]), - titleDiv, - el("div", { class: "search-result-vault" }, [document.createTextNode(r.vault + " / " + r.path)]), - snippetDiv - ]); - if (r.tags && r.tags.length > 0) { - const tagsDiv = el("div", { class: "search-result-tags" }); - r.tags.forEach((tag) => { - if (!TagFilterService.isTagFiltered(tag)) { - const tagEl = el("span", { class: "file-tag" }, [document.createTextNode(`#${tag}`)]); - tagEl.addEventListener("click", (e) => { - e.stopPropagation(); - addTagFilter(tag); - }); - tagsDiv.appendChild(tagEl); - } - }); - if (tagsDiv.children.length > 0) item.appendChild(tagsDiv); - } - item.addEventListener("click", () => TabManager.openPreview(r.vault, r.path)); - item.addEventListener("dblclick", (e) => { e.preventDefault(); TabManager.openPersistent(r.vault, r.path); }); - container.appendChild(item); - }); - area.appendChild(container); - } - - // --- Advanced search results renderer (facets, highlighted snippets, pagination, sort) --- - function renderAdvancedSearchResults(data, query, tagFilter) { - const area = document.getElementById("content-area"); - area.innerHTML = ""; - - // Update match counter + show floating results bar - var rb = document.getElementById("results-bar"); - var countEl = document.getElementById("rb-count"); - if (countEl) countEl.textContent = `${data.total > 0 ? "1" : "0"}/${data.total}`; - if (rb) rb.style.display = 'flex'; - - // Header with result count and sort controls - const header = el("div", { class: "search-results-header" }); - const summaryText = el("span", { class: "search-results-summary-text" }); - const parsed = QueryParser.parse(query); - const freeText = parsed.freeText; - - if (freeText && tagFilter) { - summaryText.textContent = `${data.total} résultat(s) pour "${freeText}" avec filtres`; - } else if (freeText) { - summaryText.textContent = `${data.total} résultat(s) pour "${freeText}"`; - } else if (parsed.tags.length > 0 || tagFilter) { - summaryText.textContent = `${data.total} fichier(s) avec filtres`; - } else { - summaryText.textContent = `${data.total} résultat(s)`; - } - if (data.query_time_ms !== undefined && data.query_time_ms > 0) { - const timeBadge = el("span", { class: "search-time-badge" }); - timeBadge.textContent = `(${data.query_time_ms} ms)`; - summaryText.appendChild(timeBadge); - } - header.appendChild(summaryText); - - // Active filter badges - const filtersRow = el("div", { class: "search-filters-row" }); - if (searchCaseSensitive) filtersRow.appendChild(el("span", { class: "search-filter-badge" }, [document.createTextNode("Aa")])); - if (searchWholeWord) filtersRow.appendChild(el("span", { class: "search-filter-badge" }, [document.createTextNode("wd")])); - if (searchRegex) filtersRow.appendChild(el("span", { class: "search-filter-badge" }, [document.createTextNode(".*")])); - const inclEl = document.getElementById("search-include-input"); - const exclEl = document.getElementById("search-exclude-input"); - if (inclEl?.value.trim()) filtersRow.appendChild(el("span", { class: "search-filter-badge path" }, [document.createTextNode("incl: " + inclEl.value.trim())])); - if (exclEl?.value.trim()) filtersRow.appendChild(el("span", { class: "search-filter-badge path" }, [document.createTextNode("excl: " + exclEl.value.trim())])); - if (filtersRow.children.length > 0) header.appendChild(filtersRow); - - // Sort controls - const sortDiv = el("div", { class: "search-sort" }); - const btnRelevance = el("button", { class: "search-sort__btn" + (advancedSearchSort === "relevance" ? " active" : ""), type: "button" }); - btnRelevance.textContent = "Pertinence"; - btnRelevance.addEventListener("click", () => { - advancedSearchSort = "relevance"; - advancedSearchOffset = 0; - const vault = document.getElementById("vault-filter").value; - performAdvancedSearch(query, vault, tagFilter, 0, "relevance"); - }); - const btnDate = el("button", { class: "search-sort__btn" + (advancedSearchSort === "modified" ? " active" : ""), type: "button" }); - btnDate.textContent = "Date"; - btnDate.addEventListener("click", () => { - advancedSearchSort = "modified"; - advancedSearchOffset = 0; - const vault = document.getElementById("vault-filter").value; - performAdvancedSearch(query, vault, tagFilter, 0, "modified"); - }); - sortDiv.appendChild(btnRelevance); - sortDiv.appendChild(btnDate); - header.appendChild(sortDiv); - - // Save search button - const saveBtn = el("button", { class: "search-save-btn", type: "button", title: "Sauvegarder cette recherche" }); - saveBtn.innerHTML = ' Sauver'; - saveBtn.addEventListener("click", async () => { - const inclEl = document.getElementById("search-include-input"); - const exclEl = document.getElementById("search-exclude-input"); - try { - await api("/api/saved-searches", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - query: query, - vault: document.getElementById("vault-filter")?.value || "all", - case_sensitive: searchCaseSensitive, - whole_word: searchWholeWord, - regex: searchRegex, - include_paths: inclEl?.value || "", - exclude_paths: exclEl?.value || "", - }), - }); - showToast("Recherche sauvegardée", "success"); - } catch (err) { showToast("Erreur: " + err.message, "error"); } - }); - header.appendChild(saveBtn); - area.appendChild(header); - - // Active sidebar tag chips - if (selectedTags.length > 0) { - const activeTags = el("div", { class: "search-results-active-tags" }); - selectedTags.forEach((tag) => { - const removeBtn = el( - "button", - { - class: "search-results-active-tag-remove", - title: `Retirer ${tag} du filtre`, - }, - [document.createTextNode("×")], - ); - removeBtn.addEventListener("click", (e) => { - e.stopPropagation(); - removeTagFilter(tag); - }); - const chip = el("span", { class: "search-results-active-tag" }, [document.createTextNode(`#${tag}`), removeBtn]); - activeTags.appendChild(chip); - }); - area.appendChild(activeTags); - } - - // Facets panel - if (data.facets && (Object.keys(data.facets.tags || {}).length > 0 || Object.keys(data.facets.vaults || {}).length > 0)) { - const facetsDiv = el("div", { class: "search-facets" }); - - // Vault facets - const vaultFacets = data.facets.vaults || {}; - if (Object.keys(vaultFacets).length > 1) { - const group = el("div", { class: "search-facets__group" }); - const label = el("span", { class: "search-facets__label" }); - label.textContent = "Vaults"; - group.appendChild(label); - for (const [vaultName, count] of Object.entries(vaultFacets)) { - const item = el("span", { class: "search-facets__item" }); - item.innerHTML = `${vaultName} ${count}`; - item.addEventListener("click", () => { - const input = document.getElementById("search-input"); - // Add vault: operator - const current = input.value.replace(/vault:\S+\s*/gi, "").trim(); - input.value = current + " vault:" + vaultName; - _triggerAdvancedSearch(input.value); - }); - group.appendChild(item); - } - facetsDiv.appendChild(group); - } - - // Tag facets - const tagFacets = data.facets.tags || {}; - if (Object.keys(tagFacets).length > 0) { - const group = el("div", { class: "search-facets__group" }); - const label = el("span", { class: "search-facets__label" }); - label.textContent = "Tags"; - group.appendChild(label); - const entries = Object.entries(tagFacets).slice(0, 12); - for (const [tagName, count] of entries) { - const item = el("span", { class: "search-facets__item" }); - item.innerHTML = `#${tagName} ${count}`; - item.addEventListener("click", () => { - addTagFilter(tagName); - }); - group.appendChild(item); - } - facetsDiv.appendChild(group); - } - - area.appendChild(facetsDiv); - } - - // Empty state - if (data.results.length === 0) { - area.appendChild(el("p", { style: "color:var(--text-muted);margin-top:20px" }, [document.createTextNode("Aucun résultat trouvé.")])); - return; - } - - // Results list - const container = el("div", { class: "search-results" }); - data.results.forEach((r) => { - // Apply client-side filtering for hidden files - if (!shouldDisplayPath(r.path, r.vault)) { - return; // Skip this result - } - - const titleDiv = el("div", { class: "search-result-title" }); - if (freeText) { - highlightSearchText(titleDiv, r.title, freeText, searchCaseSensitive); - } else { - titleDiv.textContent = r.title; - } - - // Snippet — use HTML from backend (already has tags) - const snippetDiv = el("div", { class: "search-result-snippet search-result__snippet" }); - if (r.snippet && r.snippet.includes("")) { - snippetDiv.innerHTML = r.snippet; - } else if (freeText && r.snippet) { - highlightSearchText(snippetDiv, r.snippet, freeText, searchCaseSensitive); - } else { - snippetDiv.textContent = r.snippet || ""; - } - - // Score badge - const scoreEl = el("span", { class: "search-result-score", style: "font-size:0.7rem;color:var(--text-muted);margin-left:8px" }); - scoreEl.textContent = `score: ${r.score}`; - - const vaultPath = el("div", { class: "search-result-vault" }, [document.createTextNode(r.vault + " / " + r.path), scoreEl]); - - const item = el("div", { class: "search-result-item", "data-vault": r.vault, "data-path": r.path }, [ - el("span", { class: "search-result-ext" }, [document.createTextNode(r.extension || (r.path || "").split(".").pop() || "")]), - titleDiv, vaultPath, snippetDiv - ]); - - if (r.tags && r.tags.length > 0) { - const tagsDiv = el("div", { class: "search-result-tags" }); - r.tags.forEach((tag) => { - if (!TagFilterService.isTagFiltered(tag)) { - const tagEl = el("span", { class: "file-tag" }, [document.createTextNode(`#${tag}`)]); - tagEl.addEventListener("click", (e) => { - e.stopPropagation(); - addTagFilter(tag); - }); - tagsDiv.appendChild(tagEl); - } - }); - if (tagsDiv.children.length > 0) item.appendChild(tagsDiv); - } - - item.addEventListener("click", () => TabManager.openPreview(r.vault, r.path)); - item.addEventListener("dblclick", (e) => { e.preventDefault(); TabManager.openPersistent(r.vault, r.path); }); - container.appendChild(item); - }); - area.appendChild(container); - - // Pagination - if (data.total > ADVANCED_SEARCH_LIMIT) { - const paginationDiv = el("div", { class: "search-pagination" }); - const prevBtn = el("button", { class: "search-pagination__btn", type: "button" }); - prevBtn.textContent = "← Précédent"; - prevBtn.disabled = advancedSearchOffset === 0; - prevBtn.addEventListener("click", () => { - advancedSearchOffset = Math.max(0, advancedSearchOffset - ADVANCED_SEARCH_LIMIT); - const vault = document.getElementById("vault-filter").value; - performAdvancedSearch(query, vault, tagFilter, advancedSearchOffset); - document.getElementById("content-area").scrollTop = 0; - }); - - const info = el("span", { class: "search-pagination__info" }); - const from = advancedSearchOffset + 1; - const to = Math.min(advancedSearchOffset + ADVANCED_SEARCH_LIMIT, data.total); - info.textContent = `${from}–${to} sur ${data.total}`; - - const nextBtn = el("button", { class: "search-pagination__btn", type: "button" }); - nextBtn.textContent = "Suivant →"; - nextBtn.disabled = advancedSearchOffset + ADVANCED_SEARCH_LIMIT >= data.total; - nextBtn.addEventListener("click", () => { - advancedSearchOffset += ADVANCED_SEARCH_LIMIT; - const vault = document.getElementById("vault-filter").value; - performAdvancedSearch(query, vault, tagFilter, advancedSearchOffset); - document.getElementById("content-area").scrollTop = 0; - }); - - paginationDiv.appendChild(prevBtn); - paginationDiv.appendChild(info); - paginationDiv.appendChild(nextBtn); - area.appendChild(paginationDiv); - } - - safeCreateIcons(); - // Initialize result navigation (select first result) - setTimeout(() => { if (window.navigateSearchResults) window.navigateSearchResults(0); }, 50); - } - - // --------------------------------------------------------------------------- - // Resizable sidebar (horizontal) - // --------------------------------------------------------------------------- - function initSidebarResize() { - const handle = document.getElementById("sidebar-resize-handle"); - const sidebar = document.getElementById("sidebar"); - if (!handle || !sidebar) return; - - // Restore saved width - const savedWidth = localStorage.getItem("obsigate-sidebar-width"); - if (savedWidth) { - sidebar.style.width = savedWidth + "px"; - } - - let startX = 0; - let startWidth = 0; - - function onMouseMove(e) { - const newWidth = Math.min(500, Math.max(200, startWidth + (e.clientX - startX))); - sidebar.style.width = newWidth + "px"; - } - - function onMouseUp() { - document.body.classList.remove("resizing"); - handle.classList.remove("active"); - document.removeEventListener("mousemove", onMouseMove); - document.removeEventListener("mouseup", onMouseUp); - localStorage.setItem("obsigate-sidebar-width", parseInt(sidebar.style.width)); - } - - handle.addEventListener("mousedown", (e) => { - e.preventDefault(); - startX = e.clientX; - startWidth = sidebar.getBoundingClientRect().width; - document.body.classList.add("resizing"); - handle.classList.add("active"); - document.addEventListener("mousemove", onMouseMove); - document.addEventListener("mouseup", onMouseUp); - }); - } - - // --------------------------------------------------------------------------- - // Resizable tag section (vertical) - // --------------------------------------------------------------------------- - function initTagResize() { - const handle = document.getElementById("tag-resize-handle"); - const tagSection = document.getElementById("tag-cloud-section"); - if (!handle || !tagSection) return; - - // Restore saved height - const savedHeight = localStorage.getItem("obsigate-tag-height"); - if (savedHeight) { - tagSection.style.height = savedHeight + "px"; - } - - let startY = 0; - let startHeight = 0; - - function onMouseMove(e) { - // Dragging up increases height, dragging down decreases - const newHeight = Math.min(400, Math.max(60, startHeight - (e.clientY - startY))); - tagSection.style.height = newHeight + "px"; - } - - function onMouseUp() { - document.body.classList.remove("resizing-v"); - handle.classList.remove("active"); - document.removeEventListener("mousemove", onMouseMove); - document.removeEventListener("mouseup", onMouseUp); - localStorage.setItem("obsigate-tag-height", parseInt(tagSection.style.height)); - } - - handle.addEventListener("mousedown", (e) => { - e.preventDefault(); - startY = e.clientY; - startHeight = tagSection.getBoundingClientRect().height; - document.body.classList.add("resizing-v"); - handle.classList.add("active"); - document.addEventListener("mousemove", onMouseMove); - document.addEventListener("mouseup", onMouseUp); - }); - } - - // --------------------------------------------------------------------------- - // Frontmatter Accent Card Builder - // --------------------------------------------------------------------------- - - function buildFrontmatterCard(frontmatter) { - // Helper: format date - function formatDate(iso) { - if (!iso) return "—"; - const d = new Date(iso); - const date = d.toISOString().slice(0, 10); - const time = d.toTimeString().slice(0, 5); - return `${date} · ${time}`; - } - - // Extract boolean flags - const booleanFlags = ["publish", "favoris", "template", "task", "archive", "draft", "private"].map((key) => ({ key, value: !!frontmatter[key] })); - - // Toggle state - let isOpen = true; - - // Build header with chevron - const chevron = el("span", { class: "fm-chevron open" }); - chevron.innerHTML = ''; - - const fmHeader = el("div", { class: "fm-header" }, [chevron, document.createTextNode("Frontmatter")]); - - // ZONE 1: Top strip - const topBadges = []; - - // Title badge - const title = frontmatter.titre || frontmatter.title || ""; - if (title) { - topBadges.push(el("span", { class: "ac-title" }, [document.createTextNode(`"${title}"`)])); - } - - // Status badge - if (frontmatter.statut) { - const statusBadge = el("span", { class: "ac-badge green" }, [el("span", { class: "ac-dot" }), document.createTextNode(frontmatter.statut)]); - topBadges.push(statusBadge); - } - - // Category badge - if (frontmatter.catégorie || frontmatter.categorie) { - const cat = frontmatter.catégorie || frontmatter.categorie; - const catBadge = el("span", { class: "ac-badge blue" }, [document.createTextNode(cat)]); - topBadges.push(catBadge); - } - - // Publish badge - if (frontmatter.publish) { - topBadges.push(el("span", { class: "ac-badge purple" }, [document.createTextNode("publié")])); - } - - // Favoris badge - if (frontmatter.favoris) { - topBadges.push(el("span", { class: "ac-badge purple" }, [document.createTextNode("favori")])); - } - - const acTop = el("div", { class: "ac-top" }, topBadges); - - // ZONE 2: Body 2 columns - const leftCol = el("div", { class: "ac-col" }, [ - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("auteur")]), el("span", { class: "ac-v" }, [document.createTextNode(frontmatter.auteur || "—")])]), - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("catégorie")]), el("span", { class: "ac-v" }, [document.createTextNode(frontmatter.catégorie || frontmatter.categorie || "—")])]), - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("statut")]), el("span", { class: "ac-v" }, [document.createTextNode(frontmatter.statut || "—")])]), - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("aliases")]), el("span", { class: "ac-v muted" }, [document.createTextNode(frontmatter.aliases && frontmatter.aliases.length > 0 ? frontmatter.aliases.join(", ") : "[]")])]), - ]); - - const rightCol = el("div", { class: "ac-col" }, [ - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("creation_date")]), el("span", { class: "ac-v mono" }, [document.createTextNode(formatDate(frontmatter.creation_date))])]), - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("modification_date")]), el("span", { class: "ac-v mono" }, [document.createTextNode(formatDate(frontmatter.modification_date))])]), - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("publish")]), el("span", { class: "ac-v" }, [document.createTextNode(String(frontmatter.publish || false))])]), - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("favoris")]), el("span", { class: "ac-v" }, [document.createTextNode(String(frontmatter.favoris || false))])]), - ]); - - const acBody = el("div", { class: "ac-body" }, [leftCol, rightCol]); - - // ZONE 3: Tags row - const tagPills = []; - if (frontmatter.tags && frontmatter.tags.length > 0) { - frontmatter.tags.forEach((tag) => { - tagPills.push(el("span", { class: "ac-tag" }, [document.createTextNode(tag)])); - }); - } - - const acTagsRow = el("div", { class: "ac-tags-row" }, [el("span", { class: "ac-tags-k" }, [document.createTextNode("tags")]), el("div", { class: "ac-tags-wrap" }, tagPills)]); - - // ZONE 4: Flags row - const flagChips = []; - booleanFlags.forEach((flag) => { - const chipClass = flag.value ? "flag-chip on" : "flag-chip off"; - flagChips.push(el("span", { class: chipClass }, [el("span", { class: "flag-dot" }), document.createTextNode(flag.key)])); - }); - - const acFlagsRow = el("div", { class: "ac-flags-row" }, [el("span", { class: "ac-flags-k" }, [document.createTextNode("flags")]), ...flagChips]); - - // Assemble the card - const acCard = el("div", { class: "ac-card" }, [acTop, acBody, acTagsRow, acFlagsRow]); - - // Toggle functionality - fmHeader.addEventListener("click", () => { - isOpen = !isOpen; - if (isOpen) { - acCard.style.display = "block"; - chevron.classList.remove("closed"); - chevron.classList.add("open"); - } else { - acCard.style.display = "none"; - chevron.classList.remove("open"); - chevron.classList.add("closed"); - } - safeCreateIcons(); - }); - - // Wrap in section - const fmSection = el("div", { class: "fm-section" }, [fmHeader, acCard]); - - return fmSection; - } - - // --------------------------------------------------------------------------- - // Helpers - // --------------------------------------------------------------------------- - function escapeHtml(str) { - if (!str) return ""; - return String(str).replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); - } - - function el(tag, attrs, children) { - const e = document.createElement(tag); - if (attrs) { - Object.entries(attrs).forEach(([k, v]) => { - // Skip boolean false for standard HTML boolean attributes to avoid setAttribute("checked", "false") bug - if (v === false && (k === "checked" || k === "disabled" || k === "hidden" || k === "required" || k === "readonly")) { - return; - } - e.setAttribute(k, v); - }); - } - if (children) { - children.forEach((c) => { - if (c) e.appendChild(c); - }); - } - return e; - } - - function icon(name, size) { - const i = document.createElement("i"); - i.setAttribute("data-lucide", name); - i.style.width = size + "px"; - i.style.height = size + "px"; - i.classList.add("icon"); - return i; - } - - function smallBadge(count) { - const s = document.createElement("span"); - s.className = "badge-small"; - s.style.cssText = "font-size:0.68rem;color:var(--text-muted);margin-left:4px"; - s.textContent = `(${count})`; - return s; - } - - function getContextMenuPositionFromElement(target) { - const rect = target.getBoundingClientRect(); - return { - x: Math.min(rect.right - 8, window.innerWidth - 16), - y: Math.min(rect.top + rect.height / 2, window.innerHeight - 16), - }; - } - - function attachTreeItemActionButton(itemEl, vault, path, type, isReadonly) { - const button = document.createElement("button"); - button.type = "button"; - button.className = "tree-item-action-btn"; - button.setAttribute("aria-label", "Afficher le menu d’actions"); - button.setAttribute("title", "Actions"); - const iconEl = icon("more-vertical", 16); - button.appendChild(iconEl); - button.addEventListener("click", (e) => { - e.preventDefault(); - e.stopPropagation(); - const pos = getContextMenuPositionFromElement(button); - ContextMenuManager.show(pos.x, pos.y, vault, path, type, isReadonly); - }); - itemEl.appendChild(button); - // Ensure Lucide icons are rendered for the button - setTimeout(() => { - safeCreateIcons(); - }, 0); - } - - function attachTreeItemLongPress(itemEl, getMenuData) { - let pressTimer = null; - let pressHandled = false; - let startX = 0; - let startY = 0; - const longPressDelay = 550; - const moveThreshold = 10; - - const clearPressTimer = () => { - if (pressTimer) { - clearTimeout(pressTimer); - pressTimer = null; - } - }; - - itemEl.addEventListener("touchstart", (e) => { - if (!e.touches || e.touches.length !== 1) return; - pressHandled = false; - startX = e.touches[0].clientX; - startY = e.touches[0].clientY; - clearPressTimer(); - pressTimer = setTimeout(() => { - const data = getMenuData(); - if (!data) return; - pressHandled = true; - ContextMenuManager.show(startX, startY, data.vault, data.path, data.type, data.isReadonly); - }, longPressDelay); - }, { passive: true }); - - itemEl.addEventListener("touchmove", (e) => { - if (!e.touches || e.touches.length !== 1) return; - const dx = Math.abs(e.touches[0].clientX - startX); - const dy = Math.abs(e.touches[0].clientY - startY); - if (dx > moveThreshold || dy > moveThreshold) { - clearPressTimer(); - } - }, { passive: true }); - - itemEl.addEventListener("touchend", () => { - clearPressTimer(); - }, { passive: true }); - - itemEl.addEventListener("touchcancel", () => { - clearPressTimer(); - }, { passive: true }); - - itemEl.addEventListener("click", (e) => { - if (pressHandled) { - e.preventDefault(); - e.stopPropagation(); - setTimeout(() => { - pressHandled = false; - }, 0); - } - }, true); - } - - function getVaultIcon(vaultName, size = 16) { - const v = allVaults.find((val) => val.name === vaultName); - const type = v ? v.type : "VAULT"; - - if (type === "DIR") { - const i = icon("folder", size); - i.style.color = "#eab308"; // yellow tint - return i; - } else { - const purple = "#8b5cf6"; - const svgNS = "http://www.w3.org/2000/svg"; - const svg = document.createElementNS(svgNS, "svg"); - svg.setAttribute("xmlns", svgNS); - svg.setAttribute("width", size); - svg.setAttribute("height", size); - svg.setAttribute("viewBox", "0 0 24 24"); - svg.setAttribute("fill", "none"); - svg.setAttribute("stroke", purple); - svg.setAttribute("stroke-width", "2"); - svg.setAttribute("stroke-linecap", "round"); - svg.setAttribute("stroke-linejoin", "round"); - svg.classList.add("icon"); - - const path1 = document.createElementNS(svgNS, "path"); - path1.setAttribute("d", "M6 3h12l4 6-10 12L2 9z"); - const path2 = document.createElementNS(svgNS, "path"); - path2.setAttribute("d", "M11 3 8 9l4 12"); - const path3 = document.createElementNS(svgNS, "path"); - path3.setAttribute("d", "M12 21l4-12-3-6"); - const path4 = document.createElementNS(svgNS, "path"); - path4.setAttribute("d", "M2 9h20"); - - svg.appendChild(path1); - svg.appendChild(path2); - svg.appendChild(path3); - svg.appendChild(path4); - return svg; - } - } - - function makeBreadcrumbSpan(text, onClick) { - const s = document.createElement("span"); - s.textContent = text; - if (onClick) { - s.addEventListener("click", async (event) => { - event.preventDefault(); - if (s.dataset.busy === "true") return; - s.dataset.busy = "true"; - s.style.pointerEvents = "none"; - try { - await onClick(event); - } finally { - s.dataset.busy = "false"; - s.style.pointerEvents = ""; - } - }); - } - return s; - } - - function appendHighlightedText(container, text, query, caseSensitive) { - container.textContent = ""; - if (!query) { - container.appendChild(document.createTextNode(text)); - return; - } - - const source = caseSensitive ? text : text.toLowerCase(); - const needle = caseSensitive ? query : query.toLowerCase(); - let start = 0; - let index = source.indexOf(needle, start); - - if (index === -1) { - container.appendChild(document.createTextNode(text)); - return; - } - - while (index !== -1) { - if (index > start) { - container.appendChild(document.createTextNode(text.slice(start, index))); - } - const mark = el("mark", { class: "filter-highlight" }, [document.createTextNode(text.slice(index, index + query.length))]); - container.appendChild(mark); - start = index + query.length; - index = source.indexOf(needle, start); - } - - if (start < text.length) { - container.appendChild(document.createTextNode(text.slice(start))); - } - } - - function highlightSearchText(container, text, query, caseSensitive) { - container.textContent = ""; - if (!query || !text) { - container.appendChild(document.createTextNode(text || "")); - return; - } - - const source = caseSensitive ? text : text.toLowerCase(); - const needle = caseSensitive ? query : query.toLowerCase(); - let start = 0; - let index = source.indexOf(needle, start); - - if (index === -1) { - container.appendChild(document.createTextNode(text)); - return; - } - - while (index !== -1) { - if (index > start) { - container.appendChild(document.createTextNode(text.slice(start, index))); - } - const mark = el("mark", { class: "search-highlight" }, [document.createTextNode(text.slice(index, index + query.length))]); - container.appendChild(mark); - start = index + query.length; - index = source.indexOf(needle, start); - } - - if (start < text.length) { - container.appendChild(document.createTextNode(text.slice(start))); - } - } - - function showWelcome() { - hideProgressBar(); - - // Restore or rebuild the dashboard with tabbed sections - const area = document.getElementById("content-area"); - const home = document.getElementById("dashboard-home"); - - if (area && !home) { - area.innerHTML = ` -
    - -
    - - - - -
    - - -
    -
    -
    Chargement...
    -
    -
    -
    - - -
    -
    -
    - - Aucun bookmark -

    Épinglez des fichiers pour les retrouver ici.

    -
    -
    - - -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    - -
    - - -
    -
    -
    - - Aucun document partagé -

    Partagez un document pour le voir apparaître ici

    -
    -
    -
    `; - - // Re-initialize widgets and dashboard tabs - if (typeof DashboardRecentWidget !== "undefined") { - DashboardRecentWidget.init(); - } - initDashboardTabs(); - safeCreateIcons(); - } else if (home) { - // Dashboard already exists, show it with default tab - home.style.display = ""; - // Reset tabs to default - document.querySelectorAll(".dashboard-tab").forEach(t => t.classList.remove("active")); - document.querySelectorAll(".dashboard-panel").forEach(p => p.classList.remove("active")); - const defaultTab = document.querySelector('.dashboard-tab[data-tab="stats"]'); - const defaultPanel = document.getElementById("dashboard-panel-stats"); - if (defaultTab) defaultTab.classList.add("active"); - if (defaultPanel) defaultPanel.classList.add("active"); - } - - // Load all widgets (they handle missing elements gracefully) - if (typeof DashboardStatsWidget !== "undefined") { - DashboardStatsWidget.load(); - } - if (typeof DashboardConflictsWidget !== "undefined") { - DashboardConflictsWidget.load(); - } - if (typeof DashboardRecentWidget !== "undefined") { - DashboardRecentWidget.load(selectedContextVault); - } - if (typeof DashboardBookmarkWidget !== "undefined") { - DashboardBookmarkWidget.load(selectedContextVault); - } - if (typeof DashboardSharedWidget !== "undefined") { - DashboardSharedWidget.load(); - } - - // Load saved searches sidebar - loadSavedSearches(); - } - - async function loadSavedSearches() { - const list = document.getElementById("saved-searches-list"); - const empty = document.getElementById("saved-searches-empty"); - if (!list) return; - try { - const searches = await api("/api/saved-searches"); - if (!searches.length) { - list.innerHTML = ""; - if (empty) empty.style.display = ""; - return; - } - if (empty) empty.style.display = "none"; - list.innerHTML = searches.map(s => { - const badges = []; - if (s.case_sensitive) badges.push('Aa'); - if (s.whole_word) badges.push('wd'); - if (s.regex) badges.push('.*'); - const pathFilters = []; - if (s.include_paths) pathFilters.push(`📥 ${escapeHtml(s.include_paths)}`); - if (s.exclude_paths) pathFilters.push(`📤 ${escapeHtml(s.exclude_paths)}`); - const vaultStr = s.vault && s.vault !== "all" ? `📁 ${escapeHtml(s.vault)}` : ""; - return ` -
    -
    ${escapeHtml(s.query)}
    -
    - ${badges.join("")} - ${vaultStr} -
    - ${pathFilters.length ? '
    ' + pathFilters.join(" ") + '
    ' : ""} - -
    - `}).join(""); - list.querySelectorAll(".saved-search-item").forEach(item => { - item.addEventListener("click", (e) => { - if (e.target.classList.contains("saved-search-delete")) return; - const idx = Array.from(list.children).indexOf(item); - const s = searches[idx]; - if (!s) return; - // Apply the saved search - const input = document.getElementById("search-input"); - if (input) input.value = s.query; - searchCaseSensitive = s.case_sensitive || false; - searchWholeWord = s.whole_word || false; - searchRegex = s.regex || false; - if (typeof _updateToggleUI === "function") _updateToggleUI(); - if (s.include_paths) { - const incl = document.getElementById("search-include-input"); - if (incl) incl.value = s.include_paths; - } - if (s.exclude_paths) { - const excl = document.getElementById("search-exclude-input"); - if (excl) excl.value = s.exclude_paths; - } - // Execute the search — suppress dropdown from appearing - AutocompleteDropdown.hide(); - AutocompleteDropdown._suppressNext = true; - const vault = s.vault || "all"; - if (input) { input.dispatchEvent(new Event("input")); } - clearTimeout(searchTimeout); - advancedSearchOffset = 0; - performAdvancedSearch(s.query, vault, null); - }); - }); - list.querySelectorAll(".saved-search-delete").forEach(b => b.addEventListener("click", async (e) => { - e.stopPropagation(); - await api(`/api/saved-searches/${b.dataset.id}`, { method: "DELETE" }); - loadSavedSearches(); - })); - safeCreateIcons(); - } catch (err) { /* silently ignore */ } - } - - function showLoading() { - const area = document.getElementById("content-area"); - area.innerHTML = ` -
    -
    -
    Recherche en cours...
    -
    `; - showProgressBar(); - } - - function showProgressBar() { - const bar = document.getElementById("search-progress-bar"); - if (bar) bar.classList.add("active"); - } - - function hideProgressBar() { - const bar = document.getElementById("search-progress-bar"); - if (bar) bar.classList.remove("active"); - } - - function goHome() { - const searchInput = document.getElementById("search-input"); - if (searchInput) searchInput.value = ""; - - document.querySelectorAll(".tree-item.active").forEach((el) => el.classList.remove("active")); - - currentVault = null; - currentPath = null; - showingSource = false; - cachedRawSource = null; - - closeMobileSidebar(); - showWelcome(); - } - - // --------------------------------------------------------------------------- - // Editor (CodeMirror) - // --------------------------------------------------------------------------- - async function openEditor(vaultName, filePath) { - editorVault = vaultName; - editorPath = filePath; - - const modal = document.getElementById("editor-modal"); - const titleEl = document.getElementById("editor-title"); - const bodyEl = document.getElementById("editor-body"); - - titleEl.textContent = `Édition: ${filePath.split("/").pop()}`; - - // Fetch raw content - const rawUrl = `/api/file/${encodeURIComponent(vaultName)}/raw?path=${encodeURIComponent(filePath)}`; - const rawData = await api(rawUrl); - - // Clear previous editor - bodyEl.innerHTML = ""; - if (editorView) { - editorView.destroy(); - editorView = null; - } - fallbackEditorEl = null; - - try { - await waitForCodeMirror(); - - const { EditorView, EditorState, basicSetup, markdown, python, javascript, html, css, json, xml, sql, php, cpp, java, rust, oneDark, keymap } = window.CodeMirror; - - const currentTheme = document.documentElement.getAttribute("data-theme"); - const fileExt = filePath.split(".").pop().toLowerCase(); - - const extensions = [ - basicSetup, - keymap.of([ - { - key: "Mod-s", - run: () => { - saveFile(); - return true; - }, - }, - ]), - EditorView.lineWrapping, - ]; - - // Add language support based on file extension - const langMap = { - md: markdown, - markdown: markdown, - py: python, - js: javascript, - jsx: javascript, - ts: javascript, - tsx: javascript, - mjs: javascript, - cjs: javascript, - html: html, - htm: html, - css: css, - scss: css, - less: css, - json: json, - xml: xml, - svg: xml, - sql: sql, - php: php, - cpp: cpp, - cc: cpp, - cxx: cpp, - c: cpp, - h: cpp, - hpp: cpp, - java: java, - rs: rust, - sh: javascript, // Using javascript for shell scripts as fallback - bash: javascript, - zsh: javascript, - }; - - const langMode = langMap[fileExt]; - if (langMode) { - extensions.push(langMode()); - } - - if (currentTheme === "dark") { - extensions.push(oneDark); - } - - const state = EditorState.create({ - doc: rawData.raw, - extensions: extensions, - }); - - editorView = new EditorView({ - state: state, - parent: bodyEl, - }); - } catch (err) { - console.error("CodeMirror init failed, falling back to textarea:", err); - fallbackEditorEl = document.createElement("textarea"); - fallbackEditorEl.className = "fallback-editor"; - fallbackEditorEl.value = rawData.raw; - bodyEl.appendChild(fallbackEditorEl); - } - - modal.classList.add("active"); - safeCreateIcons(); - } - - async function waitForCodeMirror() { - let attempts = 0; - while (!window.CodeMirror && attempts < 50) { - await new Promise((resolve) => setTimeout(resolve, 100)); - attempts++; - } - if (!window.CodeMirror) { - throw new Error("CodeMirror failed to load"); - } - } - - function closeEditor() { - const modal = document.getElementById("editor-modal"); - modal.classList.remove("active"); - if (editorView) { - editorView.destroy(); - editorView = null; - } - fallbackEditorEl = null; - // Remove forge iframe if present + refresh current file - var forgeFrame = document.getElementById("forge-iframe"); - if (forgeFrame) { - forgeFrame.remove(); - if (currentVault && currentPath) openFile(currentVault, currentPath); - } - editorVault = null; - editorPath = null; - } - - async function saveFile() { - if ((!editorView && !fallbackEditorEl) || !editorVault || !editorPath) return; - - const content = editorView ? editorView.state.doc.toString() : fallbackEditorEl.value; - const saveBtn = document.getElementById("editor-save"); - const originalHTML = saveBtn.innerHTML; - - try { - saveBtn.disabled = true; - saveBtn.innerHTML = ''; - safeCreateIcons(); - - const response = await fetch(`/api/file/${encodeURIComponent(editorVault)}/save?path=${encodeURIComponent(editorPath)}`, { - method: "PUT", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ content }), - }); - - if (!response.ok) { - const error = await response.json(); - throw new Error(error.detail || "Erreur de sauvegarde"); - } - - saveBtn.innerHTML = ''; - safeCreateIcons(); - - setTimeout(() => { - closeEditor(); - if (currentVault === editorVault && currentPath === editorPath) { - openFile(currentVault, currentPath); - } - }, 800); - } catch (err) { - console.error("Save error:", err); - alert(`Erreur: ${err.message}`); - saveBtn.innerHTML = originalHTML; - saveBtn.disabled = false; - safeCreateIcons(); - } - } - - async function deleteFile() { - if (!editorVault || !editorPath) return; - - const deleteBtn = document.getElementById("editor-delete"); - const originalHTML = deleteBtn.innerHTML; - - try { - deleteBtn.disabled = true; - deleteBtn.innerHTML = ''; - safeCreateIcons(); - - const response = await fetch(`/api/file/${encodeURIComponent(editorVault)}?path=${encodeURIComponent(editorPath)}`, { method: "DELETE" }); - - if (!response.ok) { - const error = await response.json(); - throw new Error(error.detail || "Erreur de suppression"); - } - - closeEditor(); - showWelcome(); - await refreshSidebarForContext(); - await refreshTagsForContext(); - } catch (err) { - console.error("Delete error:", err); - alert(`Erreur: ${err.message}`); - deleteBtn.innerHTML = originalHTML; - deleteBtn.disabled = false; - safeCreateIcons(); - } - } - - function initEditor() { - const cancelBtn = document.getElementById("editor-cancel"); - const deleteBtn = document.getElementById("editor-delete"); - const saveBtn = document.getElementById("editor-save"); - const modal = document.getElementById("editor-modal"); - - cancelBtn.addEventListener("click", closeEditor); - deleteBtn.addEventListener("click", deleteFile); - saveBtn.addEventListener("click", saveFile); - - // Close on overlay click - modal.addEventListener("click", (e) => { - if (e.target === modal) { - closeEditor(); - } - }); - - // ESC to close - document.addEventListener("keydown", (e) => { - if (e.key === "Escape" && modal.classList.contains("active")) { - closeEditor(); - } - }); - - // Fix mouse wheel scrolling in editor - modal.addEventListener( - "wheel", - (e) => { - const editorBody = document.getElementById("editor-body"); - if (editorBody && editorBody.contains(e.target)) { - // Let the editor handle the scroll - return; - } - // Prevent modal from scrolling if not in editor area - e.preventDefault(); - }, - { passive: false }, - ); - } - - // --------------------------------------------------------------------------- - // SSE Client — IndexUpdateManager - // --------------------------------------------------------------------------- - const IndexUpdateManager = (() => { - let eventSource = null; - let reconnectTimer = null; - let reconnectDelay = 1000; - const MAX_RECONNECT_DELAY = 30000; - let recentEvents = []; - const MAX_RECENT_EVENTS = 20; - let connectionState = "disconnected"; // disconnected | connecting | connected - - function connect() { - if (eventSource) { - eventSource.close(); - } - connectionState = "connecting"; - _updateBadge(); - - eventSource = new EventSource("/api/events"); - - eventSource.addEventListener("connected", (e) => { - connectionState = "connected"; - reconnectDelay = 1000; - _updateBadge(); - }); - - eventSource.addEventListener("index_updated", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_updated", data); - _onIndexUpdated(data); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("index_reloaded", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_reloaded", data); - _onIndexReloaded(data); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("vault_added", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("vault_added", data); - showToast(`Vault "${data.vault}" ajouté (${data.stats.file_count} fichiers)`, "info"); - loadVaults(); - loadTags(); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("vault_removed", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("vault_removed", data); - showToast(`Vault "${data.vault}" supprimé`, "info"); - loadVaults(); - loadTags(); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("index_start", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_start", data); - connectionState = "syncing"; - _updateBadge(); - showToast(`Indexation démarrée (${data.total_vaults} vaults)`, "info"); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("index_progress", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_progress", data); - connectionState = "syncing"; - _updateBadge(); - loadVaults(); - loadTags(); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("index_complete", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_complete", data); - connectionState = "connected"; - _updateBadge(); - showToast(`Indexation terminée (${data.total_files} fichiers)`, "success"); - loadVaults(); - loadTags(); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.onerror = () => { - connectionState = "disconnected"; - _updateBadge(); - eventSource.close(); - eventSource = null; - _scheduleReconnect(); - }; - } - - function _scheduleReconnect() { - if (reconnectTimer) clearTimeout(reconnectTimer); - reconnectTimer = setTimeout(() => { - reconnectDelay = Math.min(reconnectDelay * 2, MAX_RECONNECT_DELAY); - connect(); - }, reconnectDelay); - } - - function _addEvent(type, data) { - recentEvents.unshift({ - type, - data, - timestamp: new Date().toISOString(), - }); - if (recentEvents.length > MAX_RECENT_EVENTS) { - recentEvents = recentEvents.slice(0, MAX_RECENT_EVENTS); - } - } - - async function _onIndexUpdated(data) { - // Brief syncing state - connectionState = "syncing"; - _updateBadge(); - - const n = data.total_changes || 0; - const vaults = (data.vaults || []).join(", "); - // Toast removed: silent auto-indexing — no notification needed - - // Refresh sidebar and tags if affected vault matches current context - const affectsCurrentVault = selectedContextVault === "all" || (data.vaults || []).includes(selectedContextVault); - if (affectsCurrentVault) { - try { - await Promise.all([refreshSidebarTreePreservingState(), refreshTagsForContext()]); - // Refresh current file if it was updated - if (currentVault && currentPath) { - const changed = (data.changes || []).some((c) => c.vault === currentVault && c.path === currentPath); - if (changed) { - openFile(currentVault, currentPath); - } - } - } catch (err) { - console.error("Error refreshing after index update:", err); - } - } - - // Refresh recent tab if it is active - if (activeSidebarTab === "recent") { - const vaultFilter = document.getElementById("recent-vault-filter"); - loadRecentFiles(vaultFilter ? vaultFilter.value || null : null); - } - - setTimeout(() => { - connectionState = "connected"; - _updateBadge(); - }, 1500); - } - - async function _onIndexReloaded(data) { - connectionState = "syncing"; - _updateBadge(); - showToast("Index complet rechargé", "info"); - try { - await Promise.all([loadVaults(), loadTags()]); - } catch (err) { - console.error("Error refreshing after full reload:", err); - } - setTimeout(() => { - connectionState = "connected"; - _updateBadge(); - }, 1500); - } - - function _updateBadge() { - const badge = document.getElementById("sync-badge"); - if (!badge) return; - badge.className = "sync-badge sync-badge--" + connectionState; - const labels = { - disconnected: "Déconnecté", - connecting: "Connexion...", - connected: "Synchronisé", - syncing: "Mise à jour...", - }; - badge.title = labels[connectionState] || connectionState; - } - - function disconnect() { - if (eventSource) { - eventSource.close(); - eventSource = null; - } - if (reconnectTimer) { - clearTimeout(reconnectTimer); - reconnectTimer = null; - } - connectionState = "disconnected"; - _updateBadge(); - } - - function getState() { - return connectionState; - } - - function getRecentEvents() { - return recentEvents; - } - - return { connect, disconnect, getState, getRecentEvents }; - })(); - - function initSyncStatus() { - const badge = document.getElementById("sync-badge"); - if (!badge) return; - - badge.addEventListener("click", (e) => { - e.stopPropagation(); - toggleSyncPanel(); - }); - - IndexUpdateManager.connect(); - } - - function toggleSyncPanel() { - let panel = document.getElementById("sync-panel"); - if (panel) { - panel.remove(); - return; - } - // Auto reconnect if disconnected when user opens the panel - if (IndexUpdateManager.getState() === "disconnected") { - IndexUpdateManager.connect(); - } - panel = document.createElement("div"); - panel.id = "sync-panel"; - panel.className = "sync-panel"; - _renderSyncPanel(panel); - document.body.appendChild(panel); - - // Close on outside click - setTimeout(() => { - document.addEventListener("click", _closeSyncPanelOutside, { once: true }); - }, 0); - } - - function _closeSyncPanelOutside(e) { - const panel = document.getElementById("sync-panel"); - if (panel && !panel.contains(e.target) && e.target.id !== "sync-badge") { - panel.remove(); - } - } - - function _renderSyncPanel(panel) { - const state = IndexUpdateManager.getState(); - const events = IndexUpdateManager.getRecentEvents(); - - const stateLabels = { - disconnected: "Déconnecté", - connecting: "Connexion...", - connected: "Connecté", - syncing: "Synchronisation...", - }; - - let html = `
    - Synchronisation - ${stateLabels[state] || state} -
    `; - - if (events.length === 0) { - html += `
    Aucun événement récent
    `; - } else { - html += `
    `; - events.slice(0, 10).forEach((ev) => { - const time = new Date(ev.timestamp).toLocaleTimeString(); - const typeLabels = { - index_updated: "Mise à jour", - index_reloaded: "Rechargement", - vault_added: "Vault ajouté", - vault_removed: "Vault supprimé", - index_start: "Démarrage index.", - index_progress: "Vault indexé", - index_complete: "Indexation tech.", - }; - const label = typeLabels[ev.type] || ev.type; - let detail = ev.data.vaults ? ev.data.vaults.join(", ") : ev.data.vault || ""; - if (ev.type === "index_start") detail = `${ev.data.total_vaults} vaults à traiter`; - if (ev.type === "index_progress") detail = `${ev.data.vault} (${ev.data.files} fichiers)`; - if (ev.type === "index_complete" && ev.data.total_files !== undefined) detail = `${ev.data.total_files} fichiers total`; - html += `
    - ${label} - ${detail} - ${time} -
    `; - }); - html += `
    `; - } - - panel.innerHTML = html; - } - - // --------------------------------------------------------------------------- - // Context Menu Manager - // --------------------------------------------------------------------------- - - const ContextMenuManager = { - _menu: null, - _targetElement: null, - _targetVault: null, - _targetPath: null, - _targetType: null, - - init() { - this._menu = document.createElement('div'); - this._menu.className = 'context-menu'; - this._menu.id = 'context-menu'; - document.body.appendChild(this._menu); - - document.addEventListener('click', () => this.hide()); - document.addEventListener('contextmenu', (e) => { - if (!e.target.closest('.tree-item')) { - this.hide(); - } - }); - - document.addEventListener('keydown', (e) => { - if (e.key === 'Escape') this.hide(); - }); - - document.addEventListener('scroll', () => this.hide(), true); - }, - - show(x, y, vault, path, type, isReadonly) { - this._targetVault = vault; - this._targetPath = path; - this._targetType = type; - - this._menu.innerHTML = ''; - - // Copy path — available for all types - const pathToCopy = type === 'vault' ? vault : `${vault}/${path}`; - this._addItem('clipboard-copy', 'Copier le chemin', () => this._copyPath(pathToCopy), false); - - // Graph view — available for all types - const graphPath = type === 'vault' ? '' : path; - this._addItem('git-graph', 'Vue Graphique', () => GraphViewManager.open(vault, graphPath, type), false); - - this._addSeparator(); - - if (type === 'vault') { - this._addItem('folder-plus', 'Nouveau dossier', () => this._createDirectory(), isReadonly); - this._addItem('file-plus', 'Nouveau fichier', () => this._createFile(), isReadonly); - } else if (type === 'directory') { - this._addItem('folder-plus', 'Nouveau sous-dossier', () => this._createDirectory(), isReadonly); - this._addItem('file-plus', 'Nouveau fichier ici', () => this._createFile(), isReadonly); - this._addSeparator(); - this._addItem('edit', 'Renommer', () => this._renameItem(), isReadonly); - this._addItem('trash-2', 'Supprimer', () => this._deleteDirectory(), isReadonly); - } else if (type === 'file') { - this._addItem('edit', 'Renommer', () => this._renameItem(), isReadonly); - this._addItem('trash-2', 'Supprimer', () => this._deleteFile(), isReadonly); - this._addSeparator(); - this._addItem('bookmark-plus', 'Ajouter aux bookmarks', () => this._toggleBookmark(), false); - } - - this._menu.classList.add('active'); - - const rect = this._menu.getBoundingClientRect(); - const viewportWidth = window.innerWidth; - const viewportHeight = window.innerHeight; - - let finalX = x; - let finalY = y; - - if (x + rect.width > viewportWidth) { - finalX = viewportWidth - rect.width - 10; - } - - if (y + rect.height > viewportHeight) { - finalY = viewportHeight - rect.height - 10; - } - - this._menu.style.left = `${finalX}px`; - this._menu.style.top = `${finalY}px`; - - safeCreateIcons(); - }, - - hide() { - if (this._menu) { - this._menu.classList.remove('active'); - } - }, - - _addItem(icon, label, callback, disabled) { - const item = document.createElement('div'); - item.className = 'context-menu-item' + (disabled ? ' disabled' : ''); - item.innerHTML = ` - - ${label} - `; - - if (!disabled) { - item.addEventListener('click', (e) => { - e.stopPropagation(); - this.hide(); - callback(); - }); - } else { - item.title = 'Vault en lecture seule'; - } - - this._menu.appendChild(item); - }, - - _addSeparator() { - const sep = document.createElement('div'); - sep.className = 'context-menu-separator'; - this._menu.appendChild(sep); - }, - - _createDirectory() { - FileOperations.showCreateDirectoryModal(this._targetVault, this._targetPath); - }, - - _createFile() { - FileOperations.showCreateFileModal(this._targetVault, this._targetPath); - }, - - _renameItem() { - FileOperations.startInlineRename(this._targetVault, this._targetPath, this._targetType); - }, - - _deleteDirectory() { - FileOperations.confirmDeleteDirectory(this._targetVault, this._targetPath); - }, - - _deleteFile() { - FileOperations.confirmDeleteFile(this._targetVault, this._targetPath); - }, - - _copyPath(path) { - // Try modern clipboard API first, fall back to execCommand for non-secure contexts - if (navigator.clipboard && navigator.clipboard.writeText) { - navigator.clipboard.writeText(path).then(() => { - showToast(`Chemin copié : ${path}`, 'success'); - }).catch(() => { - this._copyPathFallback(path); - }); - } else { - this._copyPathFallback(path); - } - }, - - _copyPathFallback(path) { - const textarea = document.createElement('textarea'); - textarea.value = path; - textarea.style.position = 'fixed'; - textarea.style.left = '-9999px'; - textarea.style.top = '-9999px'; - document.body.appendChild(textarea); - textarea.focus(); - textarea.select(); - try { - const success = document.execCommand('copy'); - if (success) { - showToast(`Chemin copié : ${path}`, 'success'); - } else { - showToast('Erreur lors de la copie', 'error'); - } - } catch (e) { - showToast('Erreur lors de la copie', 'error'); - } - document.body.removeChild(textarea); - }, - - async _toggleBookmark() { - try { - const data = await api("/api/bookmarks/toggle", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ vault: this._targetVault, path: this._targetPath, title: this._targetPath.split("/").pop() }), - }); - showToast(data.bookmarked ? "Ajouté aux bookmarks" : "Retiré des bookmarks", "success"); - if (typeof DashboardBookmarkWidget !== "undefined" && DashboardBookmarkWidget.load) { - DashboardBookmarkWidget.load(); - } - } catch (err) { showToast("Erreur: " + err.message, "error"); } - } - }; - - // --------------------------------------------------------------------------- - // File Operations Manager - // --------------------------------------------------------------------------- - - const FileOperations = { - showCreateDirectoryModal(vault, parentPath) { - const overlay = this._createModalOverlay(); - const modal = document.createElement('div'); - modal.className = 'obsigate-modal'; - modal.innerHTML = ` -
    -

    Créer un dossier

    -
    -
    - -
    - - `; - - overlay.appendChild(modal); - document.body.appendChild(overlay); - - setTimeout(() => overlay.classList.add('active'), 10); - - const input = modal.querySelector('#dir-name-input'); - const errorDiv = modal.querySelector('#dir-error'); - const createBtn = modal.querySelector('#dir-create-btn'); - const cancelBtn = modal.querySelector('#dir-cancel-btn'); - - input.focus(); - - const validateName = (name) => { - if (!name.trim()) return 'Le nom ne peut pas être vide'; - if (/[/\\:*?"<>|]/.test(name)) return 'Caractères interdits: / \\ : * ? " < > |'; - return null; - }; - - input.addEventListener('input', () => { - const error = validateName(input.value); - if (error) { - errorDiv.textContent = error; - errorDiv.style.display = 'block'; - input.classList.add('error'); - } else { - errorDiv.style.display = 'none'; - input.classList.remove('error'); - } - }); - - const create = async () => { - const name = input.value.trim(); - const error = validateName(name); - if (error) { - errorDiv.textContent = error; - errorDiv.style.display = 'block'; - return; - } - - const path = parentPath ? `${parentPath}/${name}` : name; - createBtn.disabled = true; - createBtn.textContent = 'Création...'; - - try { - await api(`/api/directory/${encodeURIComponent(vault)}`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ path }), - }); - - showToast(`Dossier "${name}" créé`, 'success'); - this._closeModal(overlay); - await refreshSidebarTreePreservingState(); - } catch (err) { - showToast(err.message || 'Erreur lors de la création', 'error'); - createBtn.disabled = false; - createBtn.textContent = 'Créer'; - } - }; - - createBtn.addEventListener('click', create); - cancelBtn.addEventListener('click', () => this._closeModal(overlay)); - - input.addEventListener('keydown', (e) => { - if (e.key === 'Enter') create(); - if (e.key === 'Escape') this._closeModal(overlay); - }); - }, - - showCreateFileModal(vault, parentPath) { - const overlay = this._createModalOverlay(); - const modal = document.createElement('div'); - modal.className = 'obsigate-modal'; - modal.innerHTML = ` -
    -

    Créer un fichier

    -
    -
    - - -
    - - `; - - overlay.appendChild(modal); - document.body.appendChild(overlay); - - setTimeout(() => overlay.classList.add('active'), 10); - - const input = modal.querySelector('#file-name-input'); - const extSelect = modal.querySelector('#file-ext-select'); - const errorDiv = modal.querySelector('#file-error'); - const createBtn = modal.querySelector('#file-create-btn'); - const cancelBtn = modal.querySelector('#file-cancel-btn'); - - input.focus(); - - const validateName = (name) => { - if (!name.trim()) return 'Le nom ne peut pas être vide'; - if (/[/\\:*?"<>|]/.test(name)) return 'Caractères interdits: / \\ : * ? " < > |'; - return null; - }; - - input.addEventListener('input', () => { - const error = validateName(input.value); - if (error) { - errorDiv.textContent = error; - errorDiv.style.display = 'block'; - input.classList.add('error'); - } else { - errorDiv.style.display = 'none'; - input.classList.remove('error'); - } - }); - - const create = async () => { - let name = input.value.trim(); - const error = validateName(name); - if (error) { - errorDiv.textContent = error; - errorDiv.style.display = 'block'; - return; - } - - const ext = extSelect.value; - if (!name.endsWith(ext)) { - name += ext; - } - - const path = parentPath ? `${parentPath}/${name}` : name; - createBtn.disabled = true; - createBtn.textContent = 'Création...'; - - try { - await api(`/api/file/${encodeURIComponent(vault)}`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ path, content: '' }), - }); - - showToast(`Fichier "${name}" créé`, 'success'); - this._closeModal(overlay); - await refreshSidebarTreePreservingState(); - openFile(vault, path); - } catch (err) { - showToast(err.message || 'Erreur lors de la création', 'error'); - createBtn.disabled = false; - createBtn.textContent = 'Créer'; - } - }; - - createBtn.addEventListener('click', create); - cancelBtn.addEventListener('click', () => this._closeModal(overlay)); - - input.addEventListener('keydown', (e) => { - if (e.key === 'Enter') create(); - if (e.key === 'Escape') this._closeModal(overlay); - }); - }, - - async startInlineRename(vault, path, type) { - const item = document.querySelector(`.tree-item[data-vault="${CSS.escape(vault)}"][data-path="${CSS.escape(path)}"]`); - if (!item) { - showToast('Élément introuvable dans l’arborescence', 'error'); - return; - } - - const textNode = Array.from(item.childNodes).find((node) => node.nodeType === Node.TEXT_NODE && node.textContent.trim()); - if (!textNode) { - showToast('Impossible de renommer cet élément', 'error'); - return; - } - - const originalText = textNode.textContent; - const trimmedOriginal = originalText.trim(); - const currentName = path.split('/').pop() || trimmedOriginal; - const baseName = type === 'file' ? currentName.replace(/(\.[^./\\]+)$/i, '') : currentName; - const extension = type === 'file' ? (currentName.match(/(\.[^./\\]+)$/i)?.[1] || '') : ''; - - const input = document.createElement('input'); - input.type = 'text'; - input.className = 'sidebar-item-input'; - input.value = baseName; - - textNode.textContent = ' '; - const badge = item.querySelector('.badge-small'); - if (badge) { - item.insertBefore(input, badge); - } else { - item.appendChild(input); - } - - const restore = () => { - input.remove(); - textNode.textContent = originalText; - }; - - const validateName = (name) => { - if (!name.trim()) return 'Le nom ne peut pas être vide'; - if (/[/\\:*?"<>|]/.test(name)) return 'Caractères interdits: / \\ : * ? " < > |'; - return null; - }; - - const submit = async () => { - const name = input.value.trim(); - const error = validateName(name); - if (error) { - showToast(error, 'error'); - input.focus(); - input.select(); - return; - } - - const newName = `${name}${extension}`; - if (newName === currentName) { - restore(); - return; - } - - input.disabled = true; - try { - const endpoint = type === 'directory' ? `/api/directory/${encodeURIComponent(vault)}` : `/api/file/${encodeURIComponent(vault)}`; - const result = await api(endpoint, { - method: 'PATCH', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ path, new_name: newName }), - }); - - const nextPath = result.new_path; - await refreshSidebarTreePreservingState(); - - if (type === 'file' && currentVault === vault && currentPath === path) { - await openFile(vault, nextPath); - } else if (type === 'directory' && currentVault === vault && currentPath && (currentPath === path || currentPath.startsWith(`${path}/`))) { - const suffix = currentPath === path ? '' : currentPath.slice(path.length); - currentPath = `${nextPath}${suffix}`; - await focusPathInSidebar(vault, currentPath, { alignToTop: false }); - } - - showToast(type === 'directory' ? 'Dossier renommé' : 'Fichier renommé', 'success'); - } catch (err) { - input.disabled = false; - showToast(err.message || 'Erreur lors du renommage', 'error'); - input.focus(); - input.select(); - return; - } - }; - - input.addEventListener('click', (e) => e.stopPropagation()); - input.addEventListener('keydown', async (e) => { - e.stopPropagation(); - if (e.key === 'Enter') { - e.preventDefault(); - await submit(); - } - if (e.key === 'Escape') { - e.preventDefault(); - restore(); - } - }); - input.addEventListener('blur', async () => { - if (!input.disabled) { - await submit(); - } - }); - - input.focus(); - input.setSelectionRange(0, input.value.length); - }, - - confirmDeleteDirectory(vault, path) { - const overlay = this._createModalOverlay(); - const modal = document.createElement('div'); - modal.className = 'obsigate-modal'; - modal.innerHTML = ` -
    -

    Supprimer le dossier

    -
    -
    - - -
    - - `; - - overlay.appendChild(modal); - document.body.appendChild(overlay); - - setTimeout(() => overlay.classList.add('active'), 10); - safeCreateIcons(); - - const confirmBtn = modal.querySelector('#del-confirm-btn'); - const cancelBtn = modal.querySelector('#del-cancel-btn'); - - const deleteDir = async () => { - confirmBtn.disabled = true; - confirmBtn.textContent = 'Suppression...'; - - try { - const result = await api(`/api/directory/${encodeURIComponent(vault)}?path=${encodeURIComponent(path)}`, { - method: 'DELETE', - }); - - showToast(`Dossier supprimé (${result.deleted_count} fichiers)`, 'success'); - this._closeModal(overlay); - await refreshSidebarTreePreservingState(); - - if (currentVault === vault && currentPath && currentPath.startsWith(path)) { - showWelcome(); - } - } catch (err) { - showToast(err.message || 'Erreur lors de la suppression', 'error'); - confirmBtn.disabled = false; - confirmBtn.textContent = 'Supprimer définitivement'; - } - }; - - confirmBtn.addEventListener('click', deleteDir); - cancelBtn.addEventListener('click', () => this._closeModal(overlay)); - }, - - confirmDeleteFile(vault, path) { - const overlay = this._createModalOverlay(); - const modal = document.createElement('div'); - modal.className = 'obsigate-modal'; - modal.innerHTML = ` -
    -

    Supprimer le fichier

    -
    -
    - - -
    - - `; - - overlay.appendChild(modal); - document.body.appendChild(overlay); - - setTimeout(() => overlay.classList.add('active'), 10); - safeCreateIcons(); - - const confirmBtn = modal.querySelector('#del-confirm-btn'); - const cancelBtn = modal.querySelector('#del-cancel-btn'); - - const deleteFile = async () => { - confirmBtn.disabled = true; - confirmBtn.textContent = 'Suppression...'; - - try { - await api(`/api/file/${encodeURIComponent(vault)}?path=${encodeURIComponent(path)}`, { - method: 'DELETE', - }); - - showToast('Fichier supprimé', 'success'); - this._closeModal(overlay); - await refreshSidebarTreePreservingState(); - - if (currentVault === vault && currentPath === path) { - showWelcome(); - } - } catch (err) { - showToast(err.message || 'Erreur lors de la suppression', 'error'); - confirmBtn.disabled = false; - confirmBtn.textContent = 'Supprimer définitivement'; - } - }; - - confirmBtn.addEventListener('click', deleteFile); - cancelBtn.addEventListener('click', () => this._closeModal(overlay)); - }, - - _createModalOverlay() { - const overlay = document.createElement('div'); - overlay.className = 'obsigate-modal-overlay'; - overlay.addEventListener('click', (e) => { - if (e.target === overlay) { - this._closeModal(overlay); - } - }); - return overlay; - }, - - _closeModal(overlay) { - overlay.classList.remove('active'); - setTimeout(() => overlay.remove(), 200); - } - }; - - // --------------------------------------------------------------------------- - // Find in Page Manager - // --------------------------------------------------------------------------- - const FindInPageManager = { - isOpen: false, - searchTerm: "", - matches: [], - currentIndex: -1, - options: { - caseSensitive: false, - wholeWord: false, - useRegex: false, - }, - debounceTimer: null, - previousFocus: null, - - init() { - const bar = document.getElementById("find-in-page-bar"); - const input = document.getElementById("find-input"); - const prevBtn = document.getElementById("find-prev"); - const nextBtn = document.getElementById("find-next"); - const closeBtn = document.getElementById("find-close"); - const caseSensitiveBtn = document.getElementById("find-case-sensitive"); - const wholeWordBtn = document.getElementById("find-whole-word"); - const regexBtn = document.getElementById("find-regex"); - - if (!bar || !input) return; - - // Keyboard shortcuts - document.addEventListener("keydown", (e) => { - // Ctrl+F or Cmd+F to open - if ((e.ctrlKey || e.metaKey) && e.key === "f") { - e.preventDefault(); - this.open(); - } - // Escape to close - if (e.key === "Escape" && this.isOpen) { - e.preventDefault(); - this.close(); - } - // Enter to go to next - if (e.key === "Enter" && this.isOpen && document.activeElement === input) { - e.preventDefault(); - if (e.shiftKey) { - this.goToPrevious(); - } else { - this.goToNext(); - } - } - // F3 for next/previous - if (e.key === "F3" && this.isOpen) { - e.preventDefault(); - if (e.shiftKey) { - this.goToPrevious(); - } else { - this.goToNext(); - } - } - }); - - // Input event with debounce - input.addEventListener("input", (e) => { - clearTimeout(this.debounceTimer); - this.debounceTimer = setTimeout(() => { - this.search(e.target.value); - }, 250); - }); - - // Navigation buttons - prevBtn.addEventListener("click", () => this.goToPrevious()); - nextBtn.addEventListener("click", () => this.goToNext()); - - // Close button - closeBtn.addEventListener("click", () => this.close()); - - // Option toggles - caseSensitiveBtn.addEventListener("click", () => { - this.options.caseSensitive = !this.options.caseSensitive; - caseSensitiveBtn.setAttribute("aria-pressed", this.options.caseSensitive); - this.saveState(); - if (this.searchTerm) this.search(this.searchTerm); - }); - - wholeWordBtn.addEventListener("click", () => { - this.options.wholeWord = !this.options.wholeWord; - wholeWordBtn.setAttribute("aria-pressed", this.options.wholeWord); - this.saveState(); - if (this.searchTerm) this.search(this.searchTerm); - }); - - regexBtn.addEventListener("click", () => { - this.options.useRegex = !this.options.useRegex; - regexBtn.setAttribute("aria-pressed", this.options.useRegex); - this.saveState(); - if (this.searchTerm) this.search(this.searchTerm); - }); - - // Load saved state - this.loadState(); - }, - - open() { - const bar = document.getElementById("find-in-page-bar"); - const input = document.getElementById("find-input"); - if (!bar || !input) return; - - this.previousFocus = document.activeElement; - this.isOpen = true; - bar.hidden = false; - input.focus(); - input.select(); - safeCreateIcons(); - }, - - close() { - const bar = document.getElementById("find-in-page-bar"); - if (!bar) return; - - this.isOpen = false; - bar.hidden = true; - this.clearHighlights(); - this.matches = []; - this.currentIndex = -1; - this.searchTerm = ""; - - // Restore previous focus - if (this.previousFocus && this.previousFocus.focus) { - this.previousFocus.focus(); - } - }, - - search(term) { - this.searchTerm = term; - this.clearHighlights(); - this.hideError(); - - if (!term || term.trim().length === 0) { - this.updateCounter(); - this.updateNavButtons(); - return; - } - - const contentArea = document.querySelector(".md-content"); - if (!contentArea) { - this.updateCounter(); - this.updateNavButtons(); - return; - } - - try { - const regex = this.createRegex(term); - this.matches = []; - this.findMatches(contentArea, regex); - this.currentIndex = this.matches.length > 0 ? 0 : -1; - this.highlightMatches(); - this.updateCounter(); - this.updateNavButtons(); - - if (this.matches.length > 0) { - this.scrollToMatch(0); - } - } catch (err) { - this.showError(err.message); - this.matches = []; - this.currentIndex = -1; - this.updateCounter(); - this.updateNavButtons(); - } - }, - - createRegex(term) { - let pattern = term; - - if (!this.options.useRegex) { - // Escape special regex characters - pattern = term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - } - - if (this.options.wholeWord) { - pattern = "\\b" + pattern + "\\b"; - } - - const flags = this.options.caseSensitive ? "g" : "gi"; - return new RegExp(pattern, flags); - }, - - findMatches(container, regex) { - const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT, { - acceptNode: (node) => { - // Skip code blocks, scripts, styles - const parent = node.parentElement; - if (!parent) return NodeFilter.FILTER_REJECT; - const tagName = parent.tagName.toLowerCase(); - if (["code", "pre", "script", "style"].includes(tagName)) { - return NodeFilter.FILTER_REJECT; - } - // Skip empty text nodes - if (!node.textContent || node.textContent.trim().length === 0) { - return NodeFilter.FILTER_REJECT; - } - return NodeFilter.FILTER_ACCEPT; - }, - }); - - let node; - while ((node = walker.nextNode())) { - const text = node.textContent; - let match; - regex.lastIndex = 0; // Reset regex - - while ((match = regex.exec(text)) !== null) { - this.matches.push({ - node: node, - index: match.index, - length: match[0].length, - text: match[0], - }); - - // Prevent infinite loop with zero-width matches - if (match.index === regex.lastIndex) { - regex.lastIndex++; - } - } - } - }, - - highlightMatches() { - const matchesByNode = new Map(); - - this.matches.forEach((match, idx) => { - if (!matchesByNode.has(match.node)) { - matchesByNode.set(match.node, []); - } - matchesByNode.get(match.node).push({ match, idx }); - }); - - matchesByNode.forEach((entries, node) => { - if (!node || !node.parentNode) return; - - const text = node.textContent || ""; - let cursor = 0; - const fragment = document.createDocumentFragment(); - - entries.sort((a, b) => a.match.index - b.match.index); - - entries.forEach(({ match, idx }) => { - if (match.index > cursor) { - fragment.appendChild(document.createTextNode(text.substring(cursor, match.index))); - } - - const matchText = text.substring(match.index, match.index + match.length); - const mark = document.createElement("mark"); - mark.className = idx === this.currentIndex ? "find-highlight find-highlight-active" : "find-highlight"; - mark.textContent = matchText; - mark.setAttribute("data-find-index", idx); - fragment.appendChild(mark); - - match.element = mark; - cursor = match.index + match.length; - }); - - if (cursor < text.length) { - fragment.appendChild(document.createTextNode(text.substring(cursor))); - } - - node.parentNode.replaceChild(fragment, node); - }); - }, - - clearHighlights() { - const contentArea = document.querySelector(".md-content"); - if (!contentArea) return; - - const marks = contentArea.querySelectorAll("mark.find-highlight"); - marks.forEach((mark) => { - if (!mark.parentNode) return; - const text = mark.textContent; - const textNode = document.createTextNode(text); - mark.parentNode.replaceChild(textNode, mark); - }); - - // Normalize text nodes to merge adjacent text nodes - contentArea.normalize(); - }, - - goToNext() { - if (this.matches.length === 0) return; - - // Remove active class from current - if (this.currentIndex >= 0 && this.matches[this.currentIndex].element) { - this.matches[this.currentIndex].element.classList.remove("find-highlight-active"); - } - - // Move to next (with wrapping) - this.currentIndex = (this.currentIndex + 1) % this.matches.length; - - // Add active class to new current - if (this.matches[this.currentIndex].element) { - this.matches[this.currentIndex].element.classList.add("find-highlight-active"); - } - - this.scrollToMatch(this.currentIndex); - this.updateCounter(); - }, - - goToPrevious() { - if (this.matches.length === 0) return; - - // Remove active class from current - if (this.currentIndex >= 0 && this.matches[this.currentIndex].element) { - this.matches[this.currentIndex].element.classList.remove("find-highlight-active"); - } - - // Move to previous (with wrapping) - this.currentIndex = this.currentIndex <= 0 ? this.matches.length - 1 : this.currentIndex - 1; - - // Add active class to new current - if (this.matches[this.currentIndex].element) { - this.matches[this.currentIndex].element.classList.add("find-highlight-active"); - } - - this.scrollToMatch(this.currentIndex); - this.updateCounter(); - }, - - scrollToMatch(index) { - if (index < 0 || index >= this.matches.length) return; - - const match = this.matches[index]; - if (!match.element) return; - - const contentArea = document.getElementById("content-area"); - if (!contentArea) { - match.element.scrollIntoView({ behavior: "smooth", block: "center" }); - return; - } - - // Calculate position with offset for header - const elementTop = match.element.offsetTop; - const offset = 100; // Offset for header - - contentArea.scrollTo({ - top: elementTop - offset, - behavior: "smooth", - }); - }, - - updateCounter() { - const counter = document.getElementById("find-counter"); - if (!counter) return; - - const count = this.matches.length; - if (count === 0) { - counter.textContent = "0 occurrence"; - } else if (count === 1) { - counter.textContent = "1 occurrence"; - } else { - counter.textContent = `${count} occurrences`; - } - }, - - updateNavButtons() { - const prevBtn = document.getElementById("find-prev"); - const nextBtn = document.getElementById("find-next"); - if (!prevBtn || !nextBtn) return; - - const hasMatches = this.matches.length > 0; - prevBtn.disabled = !hasMatches; - nextBtn.disabled = !hasMatches; - }, - - showError(message) { - const errorEl = document.getElementById("find-error"); - if (!errorEl) return; - - errorEl.textContent = message; - errorEl.hidden = false; - }, - - hideError() { - const errorEl = document.getElementById("find-error"); - if (!errorEl) return; - - errorEl.hidden = true; - }, - - saveState() { - try { - const state = { - options: this.options, - }; - localStorage.setItem("obsigate-find-in-page-state", JSON.stringify(state)); - } catch (e) { - // Ignore localStorage errors - } - }, - - loadState() { - try { - const saved = localStorage.getItem("obsigate-find-in-page-state"); - if (saved) { - const state = JSON.parse(saved); - if (state.options) { - this.options = { ...this.options, ...state.options }; - - // Update button states - const caseSensitiveBtn = document.getElementById("find-case-sensitive"); - const wholeWordBtn = document.getElementById("find-whole-word"); - const regexBtn = document.getElementById("find-regex"); - - if (caseSensitiveBtn) caseSensitiveBtn.setAttribute("aria-pressed", this.options.caseSensitive); - if (wholeWordBtn) wholeWordBtn.setAttribute("aria-pressed", this.options.wholeWord); - if (regexBtn) regexBtn.setAttribute("aria-pressed", this.options.useRegex); - } - } - } catch (e) { - // Ignore localStorage errors - } - }, - }; - - // --------------------------------------------------------------------------- - // Init - // --------------------------------------------------------------------------- - async function init() { - initTheme(); - initHeaderMenu(); - initCustomDropdowns(); - document.getElementById("theme-toggle").addEventListener("click", toggleTheme); - document.getElementById("header-logo").addEventListener("click", goHome); - const refreshBtn = document.getElementById("header-refresh-btn"); - if (refreshBtn) refreshBtn.addEventListener("click", goHome); - initSearch(); - initSidebarToggle(); - initMobile(); - initVaultContext(); - initSidebarTabs(); - initHelpModal(); - initConfigModal(); - initEditorPocBtn(); - initSidebarFilter(); - initSidebarResize(); - initEditor(); - initLoginForm(); - initRecentTab(); - RightSidebarManager.init(); - FindInPageManager.init(); - ContextMenuManager.init(); - - // Mermaid.js init - import('./mermaid-viewer.js').then(function(m) { - m.initMermaid(); - m.setupFocusMode(); - }); - - // Check auth status first - const authOk = await AuthManager.initAuth(); - - if (authOk) { - // Start SSE sync AFTER auth is established (cookie available) - initSyncStatus(); - - try { - await Promise.all([loadVaultSettings(), loadVaults(), loadTags()]); - - // Initialize dashboard widgets now that vaults are loaded - if (typeof DashboardRecentWidget !== "undefined") { - DashboardRecentWidget.init(); - } - - // Check for popup mode query parameter - const urlParams = new URLSearchParams(window.location.search); - if (urlParams.get("popup") === "true") { - document.body.classList.add("popup-mode"); - } - - // Handle direct deep-link to file via #file=... - if (window.location.hash && window.location.hash.startsWith("#file=")) { - const hashVal = window.location.hash.substring(6); - const sepIndex = hashVal.indexOf(":"); - if (sepIndex > -1) { - const vault = decodeURIComponent(hashVal.substring(0, sepIndex)); - const path = decodeURIComponent(hashVal.substring(sepIndex + 1)); - openFile(vault, path); - } - } else if (urlParams.get("popup") !== "true") { - // Default to dashboard if no deep link and not in popup mode - showWelcome(); - } - } catch (err) { - console.error("Failed to initialize ObsiGate:", err); - showToast("Erreur lors de l'initialisation", "error"); - } - } - - safeCreateIcons(); - } - - // --------------------------------------------------------------------------- - // PWA Service Worker Registration - // --------------------------------------------------------------------------- - function registerServiceWorker() { - if ("serviceWorker" in navigator) { - window.addEventListener("load", () => { - navigator.serviceWorker - .register("/sw.js") - .then((registration) => { - console.log("[PWA] Service Worker registered successfully:", registration.scope); - - // Check for updates periodically - setInterval(() => { - registration.update(); - }, 60000); // Check every minute - - // Handle service worker updates - registration.addEventListener("updatefound", () => { - const newWorker = registration.installing; - newWorker.addEventListener("statechange", () => { - if (newWorker.state === "installed" && navigator.serviceWorker.controller) { - // New service worker available - showUpdateNotification(); - } - }); - }); - }) - .catch((error) => { - console.log("[PWA] Service Worker registration failed:", error); - }); - }); - } - } - - function showUpdateNotification() { - const message = document.createElement("div"); - message.className = "pwa-update-notification"; - message.innerHTML = ` -
    - Une nouvelle version d'ObsiGate est disponible ! - - -
    - `; - document.body.appendChild(message); - - // Auto-dismiss after 30 seconds - setTimeout(() => { - if (message.parentElement) { - message.remove(); - } - }, 30000); - } - - // Handle install prompt - let deferredPrompt; - window.addEventListener("beforeinstallprompt", (e) => { - e.preventDefault(); - deferredPrompt = e; - - // Show install button if desired - const installBtn = document.getElementById("pwa-install-btn"); - if (installBtn) { - installBtn.style.display = "block"; - installBtn.addEventListener("click", async () => { - if (deferredPrompt) { - deferredPrompt.prompt(); - const { outcome } = await deferredPrompt.userChoice; - console.log(`[PWA] User response to install prompt: ${outcome}`); - deferredPrompt = null; - installBtn.style.display = "none"; - } - }); - } - }); - - // Log when app is installed - window.addEventListener("appinstalled", () => { - console.log("[PWA] ObsiGate has been installed"); - showToast("ObsiGate installé avec succès !", "success"); - }); - - document.addEventListener("DOMContentLoaded", () => { - init(); - registerServiceWorker(); - initDashboardTabs(); - }); - - // ── Dashboard tab switching (runs on page load and after rebuild) ── - function initDashboardTabs() { - document.querySelectorAll(".dashboard-tab").forEach(tab => { - // Remove existing listeners by cloning - const newTab = tab.cloneNode(true); - tab.parentNode.replaceChild(newTab, tab); - newTab.addEventListener("click", function() { - document.querySelectorAll(".dashboard-tab").forEach(t => t.classList.remove("active")); - document.querySelectorAll(".dashboard-panel").forEach(p => p.classList.remove("active")); - this.classList.add("active"); - const panel = document.getElementById("dashboard-panel-" + this.dataset.tab); - if (panel) panel.classList.add("active"); - }); - }); - } - - // --------------------------------------------------------------------------- - // Tab Manager — Multi-file tab support - // --------------------------------------------------------------------------- - - const TabManager = { - _tabs: [], - _activeTabId: null, - _previewTabId: null, // single-click preview tab (temporary, replaced on next preview) - _tabCache: {}, // { tabId: { vault, path, title, data, rawSource, sourceView, scrollTop, icon } } - _tabBar: null, - _tabList: null, - _dirtyTabs: new Set(), - - init() { - this._tabBar = document.getElementById("tab-bar"); - this._tabList = document.getElementById("tab-list"); - }, - - /** Open a file as a preview tab (single-click). - * Replaces any existing preview tab. If the file is already - * open as a persistent tab, just activates it. */ - async openPreview(vault, path) { - const tabId = `${vault}::${path}`; - - // If already open as persistent tab, just activate it - const existing = this._tabs.find(t => t.id === tabId && !t.preview); - if (existing) { - this.activate(tabId); - return; - } - - // Close existing preview tab - if (this._previewTabId && this._previewTabId !== tabId) { - this.close(this._previewTabId); - } - - // If already open as preview, just focus it - const previewExisting = this._tabs.find(t => t.id === tabId && t.preview); - if (previewExisting) { - this.activate(tabId); - return; - } - - // Create preview tab - const name = path.split("/").pop().replace(/\.md$/i, ""); - const icon = getFileIcon(name + ".md"); - - this._tabs.push({ id: tabId, vault, path, name, icon, preview: true }); - this._tabCache[tabId] = { vault, path, title: name, data: null, rawSource: null, sourceView: false, scrollTop: 0, icon }; - this._previewTabId = tabId; - - this._renderTabs(); - this.activate(tabId); - }, - - /** Convert a preview tab to a persistent tab (double-click). - * If already persistent, opens a new duplicate (same file, different tab). */ - async openPersistent(vault, path) { - const tabId = `${vault}::${path}`; - - // If it's already a preview tab, convert it to persistent - const previewTab = this._tabs.find(t => t.id === tabId && t.preview); - if (previewTab) { - previewTab.preview = false; - if (this._previewTabId === tabId) { - this._previewTabId = null; - } - this._renderTabs(); - this.activate(tabId); - return; - } - - // If already persistent, just focus it - const existing = this._tabs.find(t => t.id === tabId && !t.preview); - if (existing) { - this.activate(tabId); - return; - } - - // Create a new persistent tab - this.open(vault, path); - }, - - /** Open a file in a tab (or focus existing) */ - async open(vault, path, options = {}) { - const tabId = `${vault}::${path}`; - - // If already open, just focus it - const existing = this._tabs.find(t => t.id === tabId); - if (existing) { - // Convert preview to persistent if needed - if (existing.preview) { - existing.preview = false; - if (this._previewTabId === tabId) this._previewTabId = null; - this._renderTabs(); - } - this.activate(tabId); - return; - } - - // Create new tab - const name = path.split("/").pop().replace(/\.md$/i, ""); - const icon = getFileIcon(name + ".md"); - - this._tabs.push({ id: tabId, vault, path, name, icon }); - this._tabCache[tabId] = { vault, path, title: name, data: null, rawSource: null, sourceView: false, scrollTop: 0, icon }; - - this._renderTabs(); - this.activate(tabId); - }, - - /** Activate a specific tab */ - async activate(tabId) { - if (this._activeTabId === tabId && this._tabs.length > 0) return; - - // Save current tab state - if (this._activeTabId && this._tabCache[this._activeTabId]) { - this._saveCurrentTabState(); - } - - this._activeTabId = tabId; - this._renderTabs(); - - // Load tab content - const cache = this._tabCache[tabId]; - if (!cache) return; - - // Update global state - currentVault = cache.vault; - currentPath = cache.path; - syncActiveFileTreeItem(cache.vault, cache.path); - - const area = document.getElementById("content-area"); - - if (cache.data) { - // Use cached data - this._restoreTabContent(cache, area); - } else { - // Fetch file content - area.innerHTML = '
    Chargement...
    '; - try { - const data = await api(`/api/file/${encodeURIComponent(cache.vault)}?path=${encodeURIComponent(cache.path)}`); - cache.data = data; - cache.title = data.title; - renderFile(cache.data); - - // Restore source view if needed - if (cache.sourceView) { - await this._toggleSourceView(cache, area); - } - if (cache.scrollTop) { - area.scrollTop = cache.scrollTop; - } - } catch (err) { - area.innerHTML = `
    Erreur: ${escapeHtml(err.message)}
    `; - } - } - - // Update URL hash - if (history.pushState) { - history.pushState(null, "", `#/file/${encodeURIComponent(cache.vault)}/${encodeURIComponent(cache.path)}`); - } - - // Hide dashboard - const dashboard = document.getElementById("dashboard-home"); - if (dashboard) dashboard.style.display = "none"; - }, - - /** Close a tab */ - close(tabId) { - const idx = this._tabs.findIndex(t => t.id === tabId); - if (idx === -1) return; - - this._tabs.splice(idx, 1); - delete this._tabCache[tabId]; - this._dirtyTabs.delete(tabId); - - if (this._tabs.length === 0) { - this._activeTabId = null; - this._showDashboard(); - this._tabBar.hidden = true; - } else if (this._activeTabId === tabId) { - // Activate adjacent tab - const newIdx = Math.min(idx, this._tabs.length - 1); - this.activate(this._tabs[newIdx].id); - } - - this._renderTabs(); - }, - - /** Close all tabs */ - closeAll() { - this._tabs = []; - this._tabCache = {}; - this._dirtyTabs.clear(); - this._activeTabId = null; - this._showDashboard(); - this._tabBar.hidden = true; - }, - - /** Close tabs to the right */ - closeRight(tabId) { - const idx = this._tabs.findIndex(t => t.id === tabId); - if (idx === -1) return; - const toClose = this._tabs.slice(idx + 1); - for (const tab of toClose) { - delete this._tabCache[tab.id]; - this._dirtyTabs.delete(tab.id); - } - this._tabs = this._tabs.slice(0, idx + 1); - if (!this._tabs.find(t => t.id === this._activeTabId)) { - this.activate(tabId); - } - this._renderTabs(); - }, - - /** Close other tabs */ - closeOthers(tabId) { - const tab = this._tabs.find(t => t.id === tabId); - if (!tab) return; - for (const t of this._tabs) { - if (t.id !== tabId) { - delete this._tabCache[t.id]; - this._dirtyTabs.delete(t.id); - } - } - this._tabs = [tab]; - this.activate(tabId); - this._renderTabs(); - }, - - /** Reorder tabs by drag and drop */ - moveTab(fromIdx, toIdx) { - if (fromIdx === toIdx || fromIdx < 0 || toIdx < 0) return; - const tab = this._tabs.splice(fromIdx, 1)[0]; - this._tabs.splice(toIdx, 0, tab); - this._renderTabs(); - }, - - /** Save current tab state before switching */ - _saveCurrentTabState() { - const cache = this._tabCache[this._activeTabId]; - if (!cache) return; - - const area = document.getElementById("content-area"); - const rendered = document.getElementById("file-rendered-content"); - - cache.scrollTop = area.scrollTop; - cache.sourceView = rendered ? rendered.style.display === "none" : false; - }, - - /** Restore tab content from cache */ - _restoreTabContent(cache, area) { - renderFile(cache.data); - if (cache.sourceView) { - this._restoreSourceView(cache, area); - } - if (cache.scrollTop) { - area.scrollTop = cache.scrollTop; - } - }, - - async _toggleSourceView(cache, area) { - const rendered = document.getElementById("file-rendered-content"); - const raw = document.getElementById("file-raw-content"); - if (!rendered || !raw) return; - - if (!cache.rawSource) { - const rawData = await api(`/api/file/${encodeURIComponent(cache.vault)}/raw?path=${encodeURIComponent(cache.path)}`); - cache.rawSource = rawData.raw; - } - raw.textContent = cache.rawSource; - rendered.style.display = "none"; - raw.style.display = "block"; - }, - - _restoreSourceView(cache, area) { - requestAnimationFrame(() => { - const rendered = document.getElementById("file-rendered-content"); - const raw = document.getElementById("file-raw-content"); - if (rendered && raw && cache.rawSource) { - raw.textContent = cache.rawSource; - rendered.style.display = "none"; - raw.style.display = "block"; - } - }); - }, - - _showDashboard() { - const area = document.getElementById("content-area"); - // Save dashboard DOM before clearing (it may have been removed from DOM by renderFile) - let dashboard = document.getElementById("dashboard-home"); - if (!dashboard) { - // Dashboard was destroyed — rebuild via showWelcome - area.innerHTML = ""; - showWelcome(); - return; - } - area.innerHTML = ""; - dashboard.style.display = ""; - area.appendChild(dashboard); - // Refresh widgets after restoring - if (typeof DashboardStatsWidget !== "undefined") DashboardStatsWidget.load(); - if (typeof DashboardConflictsWidget !== "undefined") DashboardConflictsWidget.load(); - if (typeof DashboardRecentWidget !== "undefined") DashboardRecentWidget.load(selectedContextVault); - if (typeof DashboardBookmarkWidget !== "undefined") DashboardBookmarkWidget.load(selectedContextVault); - if (history.pushState) { - history.pushState(null, "", "#"); - } - }, - - /** Render the tab bar */ - _renderTabs() { - if (!this._tabList) return; - - this._tabList.innerHTML = ""; - - if (this._tabs.length === 0) { - this._tabBar.hidden = true; - return; - } - - this._tabBar.hidden = false; - - this._tabs.forEach((tab, idx) => { - const el = document.createElement("div"); - el.className = "tab-item" + (tab.id === this._activeTabId ? " active" : "") + (tab.preview ? " preview" : ""); - el.draggable = true; - el.dataset.tabId = tab.id; - el.dataset.index = idx; - - // Icon - const iconEl = document.createElement("i"); - iconEl.setAttribute("data-lucide", tab.icon); - iconEl.className = "tab-icon"; - iconEl.style.width = "14px"; - iconEl.style.height = "14px"; - el.appendChild(iconEl); - - // Name - const nameEl = document.createElement("span"); - nameEl.className = "tab-name"; - nameEl.textContent = tab.name; - nameEl.title = `${tab.vault}/${tab.path}`; - el.appendChild(nameEl); - - // Close button - const closeEl = document.createElement("span"); - closeEl.className = "tab-close"; - closeEl.innerHTML = ''; - closeEl.addEventListener("click", (e) => { - e.stopPropagation(); - this.close(tab.id); - }); - el.appendChild(closeEl); - - // Click to activate - el.addEventListener("click", () => this.activate(tab.id)); - - // Double-click to close - el.addEventListener("dblclick", (e) => { - e.preventDefault(); - this.close(tab.id); - }); - - // Middle-click to close - el.addEventListener("mousedown", (e) => { - if (e.button === 1) { - e.preventDefault(); - this.close(tab.id); - } - }); - - // Context menu on tab - el.addEventListener("contextmenu", (e) => { - e.preventDefault(); - this._showTabContextMenu(e.clientX, e.clientY, tab.id); - }); - - // Drag and drop - el.addEventListener("dragstart", (e) => { - e.dataTransfer.setData("text/plain", String(idx)); - el.classList.add("dragging"); - }); - el.addEventListener("dragend", () => { - el.classList.remove("dragging"); - document.querySelectorAll(".tab-drop-indicator").forEach(d => d.remove()); - }); - el.addEventListener("dragover", (e) => { - e.preventDefault(); - e.dataTransfer.dropEffect = "move"; - const rect = el.getBoundingClientRect(); - const mid = rect.left + rect.width / 2; - document.querySelectorAll(".tab-drop-indicator").forEach(d => d.remove()); - const indicator = document.createElement("div"); - indicator.className = "tab-drop-indicator"; - if (e.clientX < mid) { - el.before(indicator); - } else { - el.after(indicator); - } - }); - el.addEventListener("drop", (e) => { - e.preventDefault(); - document.querySelectorAll(".tab-drop-indicator").forEach(d => d.remove()); - const fromIdx = parseInt(e.dataTransfer.getData("text/plain")); - const rect = el.getBoundingClientRect(); - const mid = rect.left + rect.width / 2; - const toIdx = e.clientX < mid ? idx : idx + 1; - if (fromIdx !== toIdx && fromIdx !== toIdx - 1) { - this.moveTab(fromIdx, toIdx); - } - }); - - this._tabList.appendChild(el); - }); - - safeCreateIcons(); - }, - - _showTabContextMenu(x, y, tabId) { - const existing = document.getElementById("tab-context-menu"); - if (existing) existing.remove(); - - const menu = document.createElement("div"); - menu.id = "tab-context-menu"; - menu.className = "context-menu active"; - menu.style.left = x + "px"; - menu.style.top = y + "px"; - menu.innerHTML = ` -
    Fermer
    -
    Fermer les autres
    -
    Fermer à droite
    -
    -
    Fermer tout
    - `; - document.body.appendChild(menu); - safeCreateIcons(); - - menu.addEventListener("click", (e) => { - const action = e.target.closest(".context-menu-item")?.dataset.action; - if (action === "close") this.close(tabId); - else if (action === "closeOthers") this.closeOthers(tabId); - else if (action === "closeRight") this.closeRight(tabId); - else if (action === "closeAll") this.closeAll(); - menu.remove(); - }); - - const closeMenu = () => menu.remove(); - document.addEventListener("click", closeMenu, { once: true }); - document.addEventListener("keydown", (e) => { if (e.key === "Escape") { menu.remove(); } }, { once: true }); - }, - }; - - // ---- Modify openFile to use TabManager ---- - const _originalOpenFile = openFile; - openFile = function(vault, path) { - TabManager.open(vault, path); - }; - - // ---- Keyboard shortcuts for tabs ---- - document.addEventListener("keydown", (e) => { - if (e.ctrlKey || e.metaKey) { - if (e.key === "w" || e.key === "W") { - e.preventDefault(); - if (TabManager._activeTabId) { - TabManager.close(TabManager._activeTabId); - } - } else if (e.key === "Tab" && !e.shiftKey) { - e.preventDefault(); - const tabs = TabManager._tabs; - const currentIdx = tabs.findIndex(t => t.id === TabManager._activeTabId); - if (currentIdx >= 0 && tabs.length > 1) { - const nextIdx = (currentIdx + 1) % tabs.length; - TabManager.activate(tabs[nextIdx].id); - } - } else if (e.key === "Tab" && e.shiftKey) { - e.preventDefault(); - const tabs = TabManager._tabs; - const currentIdx = tabs.findIndex(t => t.id === TabManager._activeTabId); - if (currentIdx >= 0 && tabs.length > 1) { - const prevIdx = (currentIdx - 1 + tabs.length) % tabs.length; - TabManager.activate(tabs[prevIdx].id); - } - } - } - }); - - // ---- Modify init to include TabManager ---- - const _origInit2 = init; - init = function() { - _origInit2(); - TabManager.init(); - }; - - // --------------------------------------------------------------------------- - // Graph View Manager — Interactive file/folder relationship visualization - // --------------------------------------------------------------------------- - - const GraphViewManager = { - _canvas: null, - _ctx: null, - _nodes: [], - _edges: [], - _offsetX: 0, - _offsetY: 0, - _zoom: 1, - _dragging: false, - _dragNode: null, - _panning: false, - _panStartX: 0, - _panStartY: 0, - _animFrame: null, - _vault: null, - _path: null, - _nodePositions: {}, - _width: 0, - _height: 0, - - async open(vault, path, type) { - this._vault = vault; - this._path = path; - - const modal = document.getElementById("graph-modal"); - const title = document.getElementById("graph-title"); - const info = document.getElementById("graph-info"); - const canvas = document.getElementById("graph-canvas"); - - if (!modal || !canvas) return; - - title.textContent = `Vue Graphique — ${vault}${path ? "/" + path : ""}`; - info.textContent = "Chargement..."; - modal.classList.add("active"); - - this._canvas = canvas; - this._ctx = canvas.getContext("2d"); - this._resetView(); - - // Fetch graph data - try { - const data = await api(`/api/graph/${encodeURIComponent(vault)}?path=${encodeURIComponent(path)}&depth=1`); - this._nodes = data.nodes || []; - this._edges = data.edges || []; - info.textContent = `${this._nodes.length} nœuds, ${this._edges.length} liens`; - this._initLayout(); - this._startRender(); - } catch (err) { - info.textContent = "Erreur de chargement"; - console.error("Graph error:", err); - } - - safeCreateIcons(); - }, - - close() { - const modal = document.getElementById("graph-modal"); - if (modal) modal.classList.remove("active"); - if (this._animFrame) { - cancelAnimationFrame(this._animFrame); - this._animFrame = null; - } - }, - - _resetView() { - this._offsetX = 0; - this._offsetY = 0; - this._zoom = 1; - this._nodePositions = {}; - }, - - _initLayout() { - const w = this._canvas.parentElement.clientWidth; - const h = this._canvas.parentElement.clientHeight; - this._canvas.width = w * devicePixelRatio; - this._canvas.height = h * devicePixelRatio; - this._canvas.style.width = w + "px"; - this._canvas.style.height = h + "px"; - this._width = w; - this._height = h; - this._ctx.scale(devicePixelRatio, devicePixelRatio); - - // Position nodes in a circle initially - const cx = w / 2; - const cy = h / 2; - const radius = Math.min(w, h) * 0.35; - - this._nodes.forEach((node, i) => { - const angle = (2 * Math.PI * i) / this._nodes.length; - this._nodePositions[node.id] = { - x: cx + radius * Math.cos(angle), - y: cy + radius * Math.sin(angle), - vx: 0, - vy: 0, - }; - }); - }, - - _startRender() { - const self = this; - let lastTime = 0; - - const loop = (time) => { - const dt = Math.min((time - lastTime) / 1000, 0.1); - lastTime = time; - self._simulate(dt); - self._draw(); - self._animFrame = requestAnimationFrame(loop); - }; - - this._animFrame = requestAnimationFrame(loop); - }, - - _simulate(dt) { - if (this._dragging || this._dragNode) return; - - const positions = this._nodePositions; - const cx = this._width / 2; - const cy = this._height / 2; - - // Spring forces (edges) - for (const edge of this._edges) { - const a = positions[edge.source]; - const b = positions[edge.target]; - if (!a || !b) continue; - - const dx = b.x - a.x; - const dy = b.y - a.y; - const dist = Math.sqrt(dx * dx + dy * dy) || 1; - const targetLen = 80; - const force = (dist - targetLen) * 0.01; - const fx = (dx / dist) * force; - const fy = (dy / dist) * force; - - a.vx += fx; - a.vy += fy; - b.vx -= fx; - b.vy -= fy; - } - - // Repulsion between all nodes - for (const n1 of this._nodes) { - for (const n2 of this._nodes) { - if (n1.id === n2.id) continue; - const a = positions[n1.id]; - const b = positions[n2.id]; - if (!a || !b) continue; - - const dx = b.x - a.x; - const dy = b.y - a.y; - const dist = Math.sqrt(dx * dx + dy * dy) || 1; - const force = 2000 / (dist * dist); - const fx = (dx / dist) * force; - const fy = (dy / dist) * force; - - a.vx -= fx; - a.vy -= fy; - } - } - - // Center gravity - for (const node of this._nodes) { - const p = positions[node.id]; - if (!p) continue; - p.vx += (cx - p.x) * 0.001; - p.vy += (cy - p.y) * 0.001; - } - - // Apply velocities with damping - for (const node of this._nodes) { - const p = positions[node.id]; - if (!p) continue; - p.vx *= 0.9; - p.vy *= 0.9; - p.x += p.vx * dt * 60; - p.y += p.vy * dt * 60; - } - }, - - _draw() { - const ctx = this._ctx; - const w = this._width; - const h = this._height; - - ctx.save(); - ctx.clearRect(0, 0, w, h); - - // Apply transform (pan + zoom) - ctx.translate(this._offsetX, this._offsetY); - ctx.scale(this._zoom, this._zoom); - - // Draw edges - for (const edge of this._edges) { - const a = this._nodePositions[edge.source]; - const b = this._nodePositions[edge.target]; - if (!a || !b) continue; - - ctx.beginPath(); - ctx.moveTo(a.x, a.y); - ctx.lineTo(b.x, b.y); - ctx.strokeStyle = edge.relation === "wikilink" ? "var(--accent-color, #2563eb)" : "var(--text-muted, #888)"; - ctx.lineWidth = edge.relation === "wikilink" ? 2 : 1; - ctx.setLineDash(edge.relation === "wikilink" ? [4, 4] : []); - ctx.stroke(); - } - ctx.setLineDash([]); - - // Draw nodes - for (const node of this._nodes) { - const p = this._nodePositions[node.id]; - if (!p) continue; - - const r = Math.max(5, Math.min(20, 6 + Math.sqrt(node.size || 100) / 100)); - - // Node circle - ctx.beginPath(); - ctx.arc(p.x, p.y, r, 0, Math.PI * 2); - - switch (node.type) { - case "directory": - ctx.fillStyle = "#5b9bd5"; - break; - case "file": - ctx.fillStyle = (node.path || "").endsWith(".md") ? "#70ad47" : "#c0c0c0"; - break; - default: - ctx.fillStyle = "#ffc000"; - break; - } - ctx.fill(); - ctx.strokeStyle = "var(--bg-primary, #1e1e1e)"; - ctx.lineWidth = 1.5; - ctx.stroke(); - - // Node label - const label = node.name.length > 20 ? node.name.slice(0, 18) + "..." : node.name; - ctx.font = `${11 / this._zoom}px -apple-system, sans-serif`; - ctx.fillStyle = "var(--text-primary, #ddd)"; - ctx.textAlign = "center"; - ctx.fillText(label, p.x, p.y + r + 12 / this._zoom); - } - - ctx.restore(); - }, - - _getNodeAt(screenX, screenY) { - const x = (screenX - this._offsetX) / this._zoom; - const y = (screenY - this._offsetY) / this._zoom; - - for (const node of this._nodes) { - const p = this._nodePositions[node.id]; - if (!p) continue; - const r = Math.max(5, Math.min(20, 6 + Math.sqrt(node.size || 100) / 100)); - const dx = x - p.x; - const dy = y - p.y; - if (dx * dx + dy * dy <= r * r + 100) { - return { node, pos: p }; - } - } - return null; - }, - - _onMouseDown(e) { - const rect = this._canvas.getBoundingClientRect(); - const mx = e.clientX - rect.left; - const my = e.clientY - rect.top; - - const hit = this._getNodeAt(mx, my); - if (hit) { - this._dragging = true; - this._dragNode = hit; - this._canvas.style.cursor = "grabbing"; - } else { - this._panning = true; - this._panStartX = e.clientX - this._offsetX; - this._panStartY = e.clientY - this._offsetY; - this._canvas.style.cursor = "grabbing"; - } - }, - - _onMouseMove(e) { - const rect = this._canvas.getBoundingClientRect(); - const mx = e.clientX - rect.left; - const my = e.clientY - rect.top; - - if (this._dragging && this._dragNode) { - this._dragNode.pos.x = (mx - this._offsetX) / this._zoom; - this._dragNode.pos.y = (my - this._offsetY) / this._zoom; - this._dragNode.pos.vx = 0; - this._dragNode.pos.vy = 0; - } else if (this._panning) { - this._offsetX = e.clientX - this._panStartX; - this._offsetY = e.clientY - this._panStartY; - } else { - const hit = this._getNodeAt(mx, my); - this._canvas.style.cursor = hit ? "pointer" : "grab"; - this._canvas.title = hit ? `Ouvrir: ${hit.node.path || hit.node.name}` : ""; - } - }, - - _onMouseUp(e) { - if (this._dragging && this._dragNode) { - // Check if it was a click (not a drag) - const rect = this._canvas.getBoundingClientRect(); - const node = this._dragNode.node; - this._dragging = false; - this._dragNode = null; - this._canvas.style.cursor = "grab"; - - // If it's a file, open it on click - if (node.type === "file") { - this.close(); - openFile(this._vault, node.path); - } else if (node.type === "directory" || node.type === "vault") { - // Expand into this directory - this.close(); - this.open(this._vault, node.path, node.type); - } - } - this._panning = false; - }, - - _onWheel(e) { - e.preventDefault(); - const rect = this._canvas.getBoundingClientRect(); - const mx = e.clientX - rect.left; - const my = e.clientY - rect.top; - - const zoomFactor = e.deltaY < 0 ? 1.1 : 0.9; - const newZoom = Math.max(0.2, Math.min(3, this._zoom * zoomFactor)); - - this._offsetX = mx - (mx - this._offsetX) * (newZoom / this._zoom); - this._offsetY = my - (my - this._offsetY) * (newZoom / this._zoom); - this._zoom = newZoom; - }, - - _onResize() { - if (!this._canvas || !this._nodes.length) return; - const w = this._canvas.parentElement.clientWidth; - const h = this._canvas.parentElement.clientHeight; - this._canvas.width = w * devicePixelRatio; - this._canvas.height = h * devicePixelRatio; - this._canvas.style.width = w + "px"; - this._canvas.style.height = h + "px"; - this._width = w; - this._height = h; - this._ctx.setTransform(1, 0, 0, 1, 0, 0); - this._ctx.scale(devicePixelRatio, devicePixelRatio); - }, - }; - - // Init graph view event listeners after DOM ready - function initGraphView() { - const closeBtn = document.getElementById("graph-close"); - const zoomIn = document.getElementById("graph-zoom-in"); - const zoomOut = document.getElementById("graph-zoom-out"); - const reset = document.getElementById("graph-reset"); - const modal = document.getElementById("graph-modal"); - const canvas = document.getElementById("graph-canvas"); - - if (closeBtn) closeBtn.addEventListener("click", () => GraphViewManager.close()); - if (modal) modal.addEventListener("click", (e) => { if (e.target === modal) GraphViewManager.close(); }); - if (zoomIn) zoomIn.addEventListener("click", () => { GraphViewManager._zoom = Math.min(3, GraphViewManager._zoom * 1.2); }); - if (zoomOut) zoomOut.addEventListener("click", () => { GraphViewManager._zoom = Math.max(0.2, GraphViewManager._zoom * 0.8); }); - if (reset) reset.addEventListener("click", () => { - GraphViewManager._offsetX = 0; - GraphViewManager._offsetY = 0; - GraphViewManager._zoom = 1; - }); - - if (canvas) { - canvas.addEventListener("mousedown", (e) => GraphViewManager._onMouseDown(e)); - canvas.addEventListener("mousemove", (e) => GraphViewManager._onMouseMove(e)); - canvas.addEventListener("mouseup", (e) => GraphViewManager._onMouseUp(e)); - canvas.addEventListener("mouseleave", () => { - GraphViewManager._dragging = false; - GraphViewManager._dragNode = null; - GraphViewManager._panning = false; - canvas.style.cursor = "grab"; - }); - canvas.addEventListener("wheel", (e) => GraphViewManager._onWheel(e), { passive: false }); - window.addEventListener("resize", () => GraphViewManager._onResize()); - } - - document.addEventListener("keydown", (e) => { - if (modal && modal.classList.contains("active") && e.key === "Escape") { - GraphViewManager.close(); - } - }); - } - - // Add to init - const _origInit = init; - init = function() { - _origInit(); - initGraphView(); - }; - -})(); diff --git a/desktop/frontend-static/editor-poc.html b/desktop/frontend-static/editor-poc.html deleted file mode 100644 index 18d7e53..0000000 --- a/desktop/frontend-static/editor-poc.html +++ /dev/null @@ -1,1998 +0,0 @@ - - - - - -ObsiGate Editor v1 — POC - - - - - -
    - - -
    -
    - - ObsiGate - - / - -
    -
    - - - -
    Saved
    -
    -
    - - -
    -
    - - -
    -
    🖼
    Drop files here
    Images, PDFs, documents
    -
    - - -
    -
    -
    - -
    -
    -
    -
    - -
    - - -
    -
    🎨 Image
    -
    </> Code Block
    -
    📊 Table
    -
    ─ Divider
    -
    -
    📐 Diagram
    -
    🔀 Flowchart
    -
    🔁 Sequence
    -
    🔂 Class Diagram
    -
    🔃 State Diagram
    -
    🔄 ER Diagram
    -
    🔅 Gantt Chart
    -
    🔆 Pie Chart
    -
    - - -
    -
    Table dimensions
    -
    -
    -
    - - -
    -
    - - -
    - - -
    - -
    Formatting
    -
    H1
    Heading 1
    Big section heading
    -
    H2
    Heading 2
    Medium section heading
    -
    H3
    Heading 3
    Small section heading
    -
    •
    Bullet List
    Unordered list
    -
    1.
    Numbered List
    Ordered list
    -
    ☐
    Checklist
    Task list
    -
    ❝
    Quote
    Block quote
    -
    </>
    Code Block
    Syntax-highlighted
    -
    ─
    Divider
    Horizontal rule
    -
    -
    Insert
    -
    🎨
    Image
    ![alt](url)
    -
    🔗
    Link
    [text](url)
    -
    📊
    Table
    Data table
    -
    -
    AI Actions
    -
    ✨
    AI: Improve writing
    Enhance style and clarity
    -
    ✨
    AI: Fix spelling
    Correct errors
    -
    ✨
    AI: Continue writing
    Continue from here
    -
    ✨
    AI: Summarize
    Condense document
    -
    ✨
    AI: Translate
    To another language
    -
    -
    -
    -
    -
    - - -
    - - -
    -
    Preview appears here
    -
    -
    - - -
    - - - - - - - - -
    -
    ✨ Improve writing
    -
    ✅ Fix spelling
    -
    🔄 Make shorter
    -
    🔅 Make longer
    -
    🌐 Translate to EN
    -
    ➕ Continue writing
    -
    -
    - - - -
    - - -
    -
    - Type / for commands | Alt+\ autocomplete | Alt+I Insert - Ctrl+J AI panel - Ctrl+S save - Ctrl+K link - ✨ AI processing... - -
    -
    - - 0 words -
    -
    - - -
    - - -
    -
    -

    Forge Editor — Aide

    -

    Navigation

    - - - - - - -
    /Menu de commandes (en debut de ligne)
    Alt+IInsertion rapide (Quick Insert)
    F1Ce panneau d'aide
    TabIndenter la ligne / element de liste
    Shift+TabDesindenter
    -

    Formatage

    - - - - - - -
    Ctrl+B**Gras**
    Ctrl+I*Italique*
    Ctrl+KInserer un lien [texte](url)
    Selection + [Envelopper en [lien](https://)
    Selection + `Envelopper en `code`
    -

    Brackets & Auto-completion

    - - - - - - -
    [Auto-ferme [] avec curseur au milieu
    (Auto-ferme () — si apres [texte], insere https://
    "Auto-ferme ""
    `Auto-ferme ``
    BackspaceSupprime la paire de brackets d'un coup
    -

    Fichier

    - - - - - - - -
    Ctrl+SSauvegarder
    Clic sur le titreRenommer le fichier
    Ctrl+JPanneau AI
    Alt+\Autocompletion intelligente
    Enter (liste)Continue la liste (-, *, 1.) et checkboxes
    Enter (liste vide)Termine la liste
    -

    Slash — Commandes

    - - - - - - -
    /h1 /h2 /h3Titres
    /bullet /numberedListes
    /checklistListe de taches
    /quote /code /dividerBlocs
    /link /image /tableInsertions
    - -
    -
    - - - - - - - - - - \ No newline at end of file diff --git a/desktop/frontend-static/icons/README.md b/desktop/frontend-static/icons/README.md deleted file mode 100644 index ec850f5..0000000 --- a/desktop/frontend-static/icons/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# ObsiGate PWA Icons - -## Generated Icons - -This directory contains PWA icons in SVG format. - -### Converting to PNG - -For production, convert these SVG files to PNG: - -**Using ImageMagick:** -```bash -for file in *.svg; do - size=$(echo $file | grep -oP '\d+x\d+' | head -1 | cut -d'x' -f1) - convert -background none -resize ${size}x${size} "$file" "${file%.svg}.png" -done -``` - -**Using Inkscape:** -```bash -for file in *.svg; do - size=$(echo $file | grep -oP '\d+x\d+' | head -1 | cut -d'x' -f1) - inkscape "$file" --export-filename="${file%.svg}.png" --export-width=$size -done -``` - -**Online tools:** -- https://cloudconvert.com/svg-to-png -- https://convertio.co/svg-png/ - -### Icon Types - -- **Regular icons**: Standard app icons with rounded corners -- **Maskable icons**: Icons with safe zone padding for adaptive icons -- **Search icon**: Icon for the search shortcut - -### Sizes - -- 72x72, 96x96, 128x128, 144x144, 152x152: Mobile devices -- 192x192: Android home screen -- 384x384: High-res displays -- 512x512: Splash screens and high-DPI displays diff --git a/desktop/frontend-static/icons/icon-128x128.svg b/desktop/frontend-static/icons/icon-128x128.svg deleted file mode 100644 index d044b04..0000000 --- a/desktop/frontend-static/icons/icon-128x128.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/desktop/frontend-static/icons/icon-144x144.svg b/desktop/frontend-static/icons/icon-144x144.svg deleted file mode 100644 index d48435d..0000000 --- a/desktop/frontend-static/icons/icon-144x144.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/desktop/frontend-static/icons/icon-152x152.svg b/desktop/frontend-static/icons/icon-152x152.svg deleted file mode 100644 index 54c763b..0000000 --- a/desktop/frontend-static/icons/icon-152x152.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/desktop/frontend-static/icons/icon-192x192-maskable.svg b/desktop/frontend-static/icons/icon-192x192-maskable.svg deleted file mode 100644 index 438889a..0000000 --- a/desktop/frontend-static/icons/icon-192x192-maskable.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/desktop/frontend-static/icons/icon-192x192.svg b/desktop/frontend-static/icons/icon-192x192.svg deleted file mode 100644 index 069f0dc..0000000 --- a/desktop/frontend-static/icons/icon-192x192.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/desktop/frontend-static/icons/icon-384x384.svg b/desktop/frontend-static/icons/icon-384x384.svg deleted file mode 100644 index 96e783c..0000000 --- a/desktop/frontend-static/icons/icon-384x384.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/desktop/frontend-static/icons/icon-512x512-maskable.svg b/desktop/frontend-static/icons/icon-512x512-maskable.svg deleted file mode 100644 index f2217fd..0000000 --- a/desktop/frontend-static/icons/icon-512x512-maskable.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/desktop/frontend-static/icons/icon-512x512.svg b/desktop/frontend-static/icons/icon-512x512.svg deleted file mode 100644 index dd9a6c6..0000000 --- a/desktop/frontend-static/icons/icon-512x512.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/desktop/frontend-static/icons/icon-72x72.svg b/desktop/frontend-static/icons/icon-72x72.svg deleted file mode 100644 index 3c67e91..0000000 --- a/desktop/frontend-static/icons/icon-72x72.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/desktop/frontend-static/icons/icon-96x96.svg b/desktop/frontend-static/icons/icon-96x96.svg deleted file mode 100644 index 9831f65..0000000 --- a/desktop/frontend-static/icons/icon-96x96.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/desktop/frontend-static/icons/search-96x96.svg b/desktop/frontend-static/icons/search-96x96.svg deleted file mode 100644 index b3f0ee0..0000000 --- a/desktop/frontend-static/icons/search-96x96.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/desktop/frontend-static/index.html b/desktop/frontend-static/index.html deleted file mode 100644 index 4b810f9..0000000 --- a/desktop/frontend-static/index.html +++ /dev/null @@ -1,4827 +0,0 @@ - - - - - - ObsiGate - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    -
    - - - - - -
    - -
    -
    - - - - - -
    - -
    -
    - -
    - -
    - - -
    -
    - - - - - - -
    -
    - -
    - - -
    - - All -
    - -
    -
    - -
    - -
    -
    -
    -
    - - -
    - - - - - - - - - - -
    - 📂 Toutes les vaults -
    -
    - - - - -
    -
    - -
    - - - - -
    - - -
    -
    -
    - Chargement... -
    -
    -
    - -
    -
    - - Raccourcis & Astuces - -
    -
    -
    - Ctrl+Shift+Space - Palette de commandes -
    -
    - Ctrl+Alt+Space - Palette de fichiers (nav. - rapide) -
    -
    - Ctrl+K - Focus barre de recherche -
    -
    - / - Recherche rapide (hors champ - texte) -
    -
    - Ctrl+S - Sauvegarder le fichier - ouvert -
    -
    - Ctrl+F - Rechercher dans le - document -
    -
    - Esc - Fermer l'editeur / modale -
    -
    - Ctrl+J - Completion IA inline (dans - l'editeur) -
    -
    - Alt+I - Insertion rapide (editeur - Forge) -
    -
    - F1 - Aide de l'editeur Forge -
    -
    -
    - - Survolez un document avec - Ctrl pour un - apercu rapide. Cliquez sur - Forge dans la - barre d'outils pour l'editeur - avance. -
    -
    -
    -
    - - -
    -
    -
    - - Aucun bookmark -

    - Épinglez des fichiers pour les retrouver - ici. -

    -
    -
    - - -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    - - -
    -
    -
    - - Aucun document partagé -

    - Partagez un document pour le voir - apparaître ici -

    -
    -
    -
    -
    -
    - - - - - - - -
    -
    - - -
    -
    -
    - ObsiGate - - / - -
    - Saved - - - -
    -
    -
    -
    - -
    -
    - - -
    -
    -
    -
    Configurations
    -
    - -
    -
    -
    - -
    -
    - - - - -
    -

    - 📋 Historique récent - Redémarrage non requis -

    -
    - - - Entre 5 et 100 fichiers (sauvegarde sur le serveur) -
    -
    - - - Nombre maximum de versions backup conservées par fichier (1-50) -
    -
    - - -
    -

    - Paramètres backend - Redémarrage requis -

    -

    - Ces paramètres sont sauvegardés sur le - serveur. Certains nécessitent un redémarrage - ou une réindexation. -

    - -
    - - - Threads dédiés à la recherche (1-8) -
    -
    - - - Contenu indexé par fichier (10K-1M). Réindexation requise. -
    -
    - - - Multiplicateur de pertinence pour les correspondances dans le titre -
    -
    - - - Multiplicateur de pertinence pour les correspondances dans les tags -
    -
    - - - Nombre max de tokens élargis par préfixe (10-200) -
    -
    -
    - - - -
    - - - -
    -

    Filtrage de tags

    -

    - Définissez les patterns de tags à masquer - dans la sidebar. Vous pouvez utiliser des - wildcards pour cibler les tags de template. -

    - -
    - -
    - - -
    - - -
    - - -
    -

    Synchronisation automatique

    -

    - Surveillance des fichiers en temps réel via - watchdog. Les modifications sont détectées - automatiquement et l'index est mis à jour - sans redémarrage. -

    - -
    - - - Activer/désactiver la surveillance - automatique des fichiers -
    -
    - - - Forcer le mode polling au lieu de - inotify natif (utile si le mode natif ne - fonctionne pas) -
    -
    - - - Intervalle de scrutation en mode - polling (1-30 secondes) -
    -
    - - - Délai avant traitement des changements - groupés (0.5-10 secondes) -
    -
    - - -
    -

    🗂️ Fichiers cachés

    -

    - Contrôlez l'affichage des fichiers/dossiers - cachés (commençant par .) par - vault. -

    -

    - i️ Note : Tous les fichiers - sont toujours indexés et cherchables. Ce - paramètre contrôle uniquement leur - visibilité dans l'interface. -

    - -
    - -
    - -
    - -
    -
    - - -
    -

    Diagnostics

    -

    - Statistiques de l'index et du moteur de - recherche. -

    -
    -
    - Chargement... -
    -
    - -
    - - -
    -

    🤖 Cles API Intelligence Artificielle

    -

    - Configurez vos cles API. Cliquez sur - Tester pour charger les - modeles. -

    -
    - - - -
    -
    - - - -
    -
    - - - -
    -
    - - - -
    -
    - - -
    -

    🎨 Thèmes

    -

    - Choisissez un thème visuel. Chaque thème - offre un mode sombre et clair. -

    -
    -
    Chargement...
    -
    -
    - - -
    -

    👤 Profil utilisateur

    -

    - Préférences personnelles pour personnaliser - l'expérience ObsiGate. -

    -
    -
    - - - Utilisée par l'autocomplétion et le ghost text. -
    -
    - - -
    - - - -
    -
    - - -
    -

    📦 À propos

    -
    -
    - Chargement... -
    -
    -
    - - -
    -

    🔔 Webhooks

    -

    - Notifications HTTP vers des services - externes lors des changements de fichiers. -

    -
    -
    - - - -
    -
    - - -
    -

    📤 Partages publics

    -

    - Liens de partage publics pour des documents - (lecture seule, sans authentification). -

    -
    -
    -
    -
    -
    -
    -
    - - -
    -
    - -
    - -
    - - - -
    - Vue Graphique -
    - - Prof. - - - - - - - -
    - -
    -
    - - - Ctrl+survol -
    -
    -
    -
    - - -
    - -
    -
    - -
    - -
    -
    - -
    - — -
    - - - - │ - ── Parent - ┅┅ Wikilink - ← Backlink -
    -
    -
    -
    -
    - - -
    -
    -
    - -
    - Guide d'utilisation ObsiGate -
    -
    - -
    -
    -
    - -
    -
    -
    -
    Guide officiel
    -

    📘 Bienvenue dans ObsiGate

    -

    - ObsiGate est votre porte d'entrée web vers - vos vaults Obsidian. Accédez, naviguez et - recherchez dans toutes vos notes depuis - n'importe quel appareil via une interface - moderne et responsive. -

    -
    - ⚡ Navigation rapide - 🗂️ Multi-vault - 🏷️ Tags intelligents - 📝 Lecture et édition - 🔍 Recherche TF-IDF -
    -
    - -
    - -
    -

    🧭 Interface utilisateur

    - -

    En-tête

    -

    - La barre supérieure contient les éléments - essentiels : -

    -
      -
    • - Bouton menu hamburger - : obile) : Affiche/masque la sidebar -
    • -
    • - Bouton toggle sidebar (desktop) : Masque la sidebar pour plus - d'espace -
    • -
    • - Logo ObsiGate : Retour à - l'accueil -
    • -
    • - Barre de recherche : - Recherche globale avec autocomplétion -
    • -
    • - Indicateur de vault : - Affiche le contexte actif (All, vault1, - etc.) -
    • -
    • - Menu Options : Accès aux - paramètres, thème, aide -
    • -
    - -

    Sidebar (barre latérale)

    -

    La sidebar est divisée en deux onglets :

    -
      -
    • - Vaults : Arborescence des - fichiers et dossiers -
    • -
    • - Tags : Nuage de tags - cliquables -
    • -
    -

    Fonctionnalités de la sidebar :

    -
      -
    • - Filtrage : Barre de - recherche pour filtrer fichiers/tags -
    • -
    • - Sélection rapide : Dropdown - pour changer de vault -
    • -
    • - Redimensionnement : Glissez - le bord droit pour ajuster la largeur -
    • -
    • - Masquage : Cliquez sur - l'icône sidebar dans le header -
    • -
    - -

    Zone de contenu

    -

    La zone centrale affiche :

    -
      -
    • - Breadcrumb : Chemin du - fichier (cliquable pour repositionner la - sidebar) -
    • -
    • - Titre et tags : Métadonnées - du fichier -
    • -
    • - Boutons d'action : Copier, - Source, Télécharger, Éditer, Ouvrir dans - nouvelle fenêtre -
    • -
    • - Contenu rendu : Markdown - avec wikilinks et images -
    • -
    -
    - -
    -

    🗺️ Navigation

    - -

    Arborescence des vaults

    -

    - Cliquez sur un vault pour l'ouvrir et voir son - contenu. Les dossiers affichent un chevron et un - badge avec le nombre d'éléments. -

    -
      -
    • - Développer/Réduire: - Cliquez sur un dossier -
    • -
    • - Ouvrir un fichier: Cliquez - sur le nom du fichier -
    • -
    • - Icônes : Chaque type de - fichier a son icône (markdown, code, etc.)
    • -
    - -

    Filtrage de la sidebar

    -

    - Utilisez la barre de filtrage en haut de la - sidebar pour rechercher rapidement : -

    -
      -
    • - Recherche instantanée: - Tapez pour filtrer fichiers et dossiers -
    • -
    • - Case-sensitive: Bouton - "Aa" pour respecter la casse -
    • -
    • - Effacer : Bouton "×" pour - réinitialiser le filtre
    • -
    • - Résultats groupés: - Affichage par vault avec chemins complets -
    • -
    - -

    Breadcrumb et repositionnement

    -

    - Le chemin affiché au-dessus du contenu est - interactif : -

    -
      -
    • - Cliquez sur le vault: - Focus sur le vault dans la sidebar -
    • -
    • - Cliquez sur un segment: - Navigation vers ce dossier -
    • -
    • - Auto-scroll: La sidebar se - positionne automatiquement -
    • -
    - -

    Sélection de vault

    -

    - Changez de contexte pour filtrer l'affichage : -

    -
      -
    • - Menu header: Dropdown - "Vault" dans le menu Options -
    • -
    • - Sidebar dropdown : - Sélection rapide en haut de l'onglet Vaults
    • -
    • - Tous les vaults: Vue - globale de tous vos contenus -
    • -
    • - Vault spécifique: Focus - sur un seul vault -
    • -
    -
    - -
    -

    📑 Gestion des onglets

    -

    - ObsiGate supporte l'ouverture de plusieurs - fichiers simultanément dans des onglets. -

    - -

    Ouverture d'onglets

    -
      -
    • - Simple clic : Ouvre le - fichier dans un onglet temporaire (aperçu, - italique)
    • -
    • - Double clic: Ouvre le - fichier dans un onglet persistant -
    • -
    • - Navigation récente : - L'onglet "Récent" dans la sidebar liste vos - derniers fichiers
    • -
    - -

    Navigation entre onglets

    -
      -
    • - Clic sur un onglet: Active - l'onglet -
    • -
    • - Ctrl+Tab: Onglet suivant -
    • -
    • - Ctrl+Shift+Tab : Onglet - précédent
    • -
    • - Ctrl+W: Fermer l'onglet - actif -
    • -
    • - Bouton ✕: Ferme l'onglet - (sauf s'il est seul) -
    • -
    - -

    Fonctionnalités

    -
      -
    • - Barre d'onglets : Affichage - horizontal avec le nom du fichier et son - icône
    • -
    • - Onglet actif : Surligné en - couleur d'accentuation
    • -
    • - Prévisualisation : Un - onglet temporaire (italique) est remplacé - par le prochain clic
    • -
    • - Onglets persistants : - Restent ouverts jusqu'à fermeture manuelle
    • -
    -
    - -
    -

    🔍 Recherche

    - -

    Recherche simple

    -

    - Tapez dans la barre de recherche en haut pour - lancer une recherche fulltext : -

    -
      -
    • - Recherche dans tout: - Titre, contenu, tags, chemins -
    • -
    • - Scoring intelligent : - Résultats classés par pertinence TF-IDF
    • -
    • - Snippets surlignés: - Extraits avec termes en surbrillance -
    • -
    • - Pagination : Navigation par - pages de 50 résultats
    • -
    - -

    Opérateurs avancés

    -

    - Utilisez des opérateurs pour affiner votre - recherche : -

    -
      -
    • - tag:docker ou - #docker : Filtrer par tag -
    • -
    • - vault:IT : Rechercher dans un - vault spécifique -
    • -
    • - title:kubernetes : Chercher - dans les titres uniquement -
    • -
    • - path:recettes/soupes : Filtrer - par chemin -
    • -
    • - ext:md : Filtrer par type de - fichier -
    • -
    • - "phrase exacte" : Recherche de - phrase entre guillemets -
    • -
    -

    - Exemples: - ext:sh recherche dans les scripts - bash, ext:py dans les scripts - Python, ext:md dans les fichiers - Markdown. -

    -

    - Exemple combiné : - tag:linux vault:IT ext:md serveur web - recherche "serveur web" dans les fichiers - Markdown du vault IT avec le tag linux. -

    - -

    Autocomplétion

    -

    - L'autocomplétion vous aide à trouver rapidement - : -

    -
      -
    • - Historique : Les 50 - dernières recherches (localStorage)
    • -
    • - Fichiers: Suggestions de - titres de fichiers -
    • -
    • - Tags: Suggestions de tags - avec compteurs -
    • -
    • - Navigation clavier : ↑/↓ - pour naviguer, Enter pour sélectionner
    • -
    - -

    Chips de filtres actifs

    -

    - Les opérateurs utilisés s'affichent sous forme - de chips colorés : -

    -
      -
    • - Visualisation: Voir d'un - coup d'œil les filtres actifs -
    • -
    • - Suppression: Cliquez sur - "×" pour retirer un filtre -
    • -
    • - Couleurs : Chaque type - d'opérateur a sa couleur
    • -
    - -

    Facettes et tri

    -

    - Les résultats incluent des facettes pour affiner - : -

    -
      -
    • - Facettes tags : Compteurs - par tag dans les résultats
    • -
    • - Facettes vaults: Compteurs - par vault -
    • -
    • - Tri par pertinence : Score - TF-IDF (défaut)
    • -
    • - Tri par date : Dernière - modification
    • -
    -
    - -
    -

    🏷️ Tags

    - -

    Tag cloud

    -

    - L'onglet Tags de la sidebar affiche un nuage de - tags : -

    -
      -
    • - Tous les tags: Extraits - des frontmatters YAML et inline (#tag) -
    • -
    • - Cliquable : Cliquez pour - filtrer les résultats
    • -
    • - Filtrage: Utilisez la - barre de filtrage pour chercher un tag -
    • -
    • - Contexte vault : Les tags - s'adaptent au vault sélectionné
    • -
    - -

    Tags inline vs frontmatter

    -

    ObsiGate supporte deux types de tags :

    -
      -
    • - Frontmatter YAML: - tags: [docker, linux] ou - tags: docker, linux -
    • -
    • - Inline: - #docker dans le contenu - markdown -
    • -
    • - Fusion automatique : Les - deux types sont combinés
    • -
    - -

    Filtrage de tags template

    -

    - Dans les Configurations, vous pouvez masquer les - tags de template : -

    -
      -
    • - Patterns wildcards: Ex: - #<% ... %> ou - #{{ ... }} -
    • -
    • - Regex générée : Aperçu de - la regex appliquée
    • -
    • - Ajout/Suppression : Gérez - vos patterns de filtrage
    • -
    -
    - -
    -

    📄 Fichiers

    - -

    Visualisation

    -

    Les fichiers markdown sont rendus avec :

    -
      -
    • - Wikilinks cliquables: - [[lien]] et - [[lien|texte]] -
    • -
    • - Images Obsidian: Support - de ![[image.png]] -
    • -
    • - Syntax highlighting: - Coloration des blocs de code -
    • -
    • - Tables, listes, quotes: - Rendu complet du markdown -
    • -
    - -

    Actions sur fichiers

    -

    Boutons disponibles au-dessus du contenu :

    -
      -
    • - Copier: Copie le contenu - source dans le presse-papiers -
    • -
    • - Source: Affiche/masque le - markdown brut -
    • -
    • - Télécharger : Télécharge le - fichier
    • -
    • - Éditer : Ouvre l'éditeur - CodeMirror
    • -
    • - Ouvrir dans nouvelle fenêtre: Ouvre le fichier dans un nouvel onglet -
    • -
    - -

    Édition avec CodeMirror 6

    -

    L'éditeur intégré offre :

    -
      -
    • - Coloration syntaxique: - Support de nombreux langages -
    • -
    • - Numéros de ligne: - Navigation facile -
    • -
    • - Autocomplétion: - Suggestions contextuelles -
    • -
    • - Recherche: Ctrl+F pour - chercher dans le fichier -
    • -
    • - Sauvegarde: Bouton ✓ pour - enregistrer -
    • -
    • - Suppression: Bouton - corbeille pour supprimer -
    • -
    - -

    Types de fichiers supportés

    -

    ObsiGate indexe et affiche :

    -
      -
    • - Markdown : .md (rendu - complet) -
    • -
    • - Code : .py, .js, .ts, .jsx, - .tsx, .java, .c, .cpp, .rs, .go, etc. -
    • -
    • - Config : .json, .yaml, - .yml, .toml, .xml, .ini, .env -
    • -
    • - Scripts : .sh, .bash, .ps1, - .bat -
    • -
    • - Web : .html, .css, .scss -
    • -
    • - Autres : .txt, .log, .sql, - .csv -
    • -
    -
    - - -
    -

    ✏️ Édition avancée

    - -

    Éditeur CodeMirror 6

    -

    - L'éditeur intégré offre une expérience complète - d'édition : -

    -
      -
    • - Coloration syntaxique: - Python, JS, HTML, CSS, Java, C++, Rust, Go - et bien d'autres -
    • -
    • - Numéros de ligne : - Navigation facilitée dans les fichiers longs
    • -
    • - Find in page: Ctrl+F pour - chercher dans le fichier (casse, regex, mot - entier) -
    • -
    • - Sauvegarde automatique : - Auto-save silencieux après 2s d'inactivité, - flash vert de confirmation
    • -
    • - Bouton ✓: Sauvegarde - manuelle -
    • -
    • - Bouton 🗑️: Suppression du - fichier -
    • -
    • - Barre d'outils AI : - Complétion, réécriture, traduction (voir - section🤖 IA) -
    • -
    -
    - - -
    -

    🗺️ Vue Graphe

    -

    - La vue graphe offre une visualisation - interactive des connexions entre vos notes via - les wikilinks. -

    - -

    Ouverture

    -
      -
    • - Menu contextuel: Clic - droit sur un vault ou dossier → Vue - Graphique -
    • -
    • - Bouton dédié : Dans la - barre d'outils (le cas échéant)
    • -
    - -

    Interaction

    -
      -
    • - Zoom/Pan : Molette pour - zoomer, cliquer-glisser pour se déplacer
    • -
    • - Slider de profondeur : - Contrôle la profondeur d'exploration (0-3)
    • -
    • - Filtre par tag : N'affiche - que les nœuds avec un tag spécifique
    • -
    • - Filtre par type: - Inclut/exclut fichiers, dossiers, markdown, - autres -
    • -
    • - Recherche visuelle: Barre - de recherche pour surligner des nœuds -
    • -
    • - Mode focus : Centre la vue - sur un nœud spécifique
    • -
    • - Navigation ← → ↑: - Historique de navigation entre les nœuds -
    • -
    - -

    Affichage

    -
      -
    • - Nœuds : Fichiers (carrés) - et dossiers (cercles) avec icônes
    • -
    • - Arêtes: Wikilinks sortants - (bleu) et backlinks entrants (vert) -
    • -
    • - Panneau d'info : - Métadonnées du nœud (tags, liens, chemin)
    • -
    • - Ctrl+survol : Aperçu du - contenu de la note sans naviguer
    • -
    • - Plein écran: Bouton pour - agrandir la vue -
    • -
    • - Export PNG: Sauvegardez le - graphe en image -
    • -
    - -

    Performance

    -

    - La vue utilise l'algorithme Barnes-Hut pour - calculer la disposition en O(n log n), - garantissant des performances fluides même avec - des centaines de nœuds. -

    -
    - -
    -

    🎨 Personnalisation

    - -

    Thème clair/sombre

    -

    Basculez entre les thèmes :

    -
      -
    • - Menu Options : Cliquez sur - "Thème" dans le menu
    • -
    • - Raccourci : - Ctrl+T -
    • -
    • - Persistance : Votre choix - est sauvegardé en localStorage
    • -
    • - Highlight.js : Les blocs de - code s'adaptent au thème
    • -
    - -

    Redimensionnement de la sidebar

    -

    - Sur desktop, ajustez la largeur de la sidebar : -

    -
      -
    • - Handle de redimensionnement - : Bordure droite de la sidebar -
    • -
    • - Glisser-déposer : Cliquez - et glissez pour ajuster -
    • -
    • - Limites : Min 200px, Max - 500px -
    • -
    • - Persistance : La largeur - est sauvegardée
    • -
    - -

    Configuration avancée

    -

    - Le modal Configurations (menu Options) permet de - : -

    -
      -
    • - Paramètres de recherche : - Délai debounce, résultats par page, timeout
    • -
    • - Paramètres backend : - Workers, boosts TF-IDF, expansions préfixe
    • -
    • - Filtrage de tags : Patterns - pour masquer les tags template -
    • -
    • - Diagnostics : Stats index, - mémoire, moteur de recherche
    • -
    • - Réindexation : Forcer un - rescan des vaults -
    • -
    -
    - - -
    -

    ⌨️ Palette de commandes

    -

    - La palette de commandes permet d'accéder - rapidement aux fichiers et aux actions sans - utiliser la souris. -

    - -

    Ouverture

    -
      -
    • - Ctrl+Shift+Espace : Palette - de fichiers (recherche par titre) -
    • -
    • - Ctrl+Alt+Espace : Palette - de commandes (liste d'actions) -
    • -
    • - Tab : Bascule entre mode - fichiers et mode commandes -
    • -
    - -

    Mode fichiers

    -

    - Tapez le nom d'un fichier pour le trouver - rapidement. La recherche utilise l'API - /api/suggest pour des suggestions - instantanées. Appuyez sur Enter pour - ouvrir le fichier sélectionné. -

    - -

    Mode commandes

    -

    - Tapez > (ou Ctrl+Alt+Espace) - pour voir la liste des actions disponibles : -

    -
      -
    • - 🏠 Accueil : Retour à - l'accueil -
    • -
    • - ✏️ Éditer fichier courant : - Ouvre l'éditeur sur l'onglet actif -
    • -
    • - 🪟 Pop-out : Ouvre le - document dans une fenêtre détachée -
    • -
    • - 📄 Créer fichier markdown : - Crée un nouveau fichier .md et l'ouvre dans - l'éditeur -
    • -
    • - 🗑️ - Supprimer fichier courant : - Supprime le fichier de l'onglet actif -
    • -
    • - 📁 Créer répertoire : Crée - un nouveau dossier -
    • -
    • - 🗑️ Supprimer répertoire : - Supprime un dossier et son contenu -
    • -
    • - 🌓 Changer le thème : - Bascule clair/sombre -
    • -
    • - 🔄 Réindexer : Force la - réindexation complète -
    • -
    • - ❓ Aide : Ouvre ce guide -
    • -
    • - ⚙️ Configuration : Ouvre - les paramètres -
    • -
    - -

    Navigation

    -
      -
    • - ↑ ↓ : Se déplacer dans - la liste -
    • -
    • Enter : Ouvrir/sélectionner
    • -
    • Esc : Fermer la palette
    • -
    • - Tab : Basculer entre fichiers et - commandes -
    • -
    -
    - -
    -

    ⌨️ Raccourcis clavier

    - -

    Navigation

    -
      -
    • - Ctrl+K ou Cmd+K : - Focaliser la barre de recherche -
    • -
    • - / : Focaliser la recherche - (hors champ texte) -
    • -
    • - Escape : Fermer les suggestions - / quitter la recherche -
    • -
    - -

    Recherche et autocomplétion

    -
      -
    • - ↑ / ↓ : Naviguer - dans les suggestions -
    • -
    • - Enter : Sélectionner la - suggestion active ou lancer la recherche -
    • -
    • - Escape : Fermer le dropdown de - suggestions -
    • -
    - -

    Interface

    -
      -
    • - Ctrl+T : Basculer le thème - clair/sombre -
    • -
    • - Ctrl+Shift+Espace : Palette de - fichiers -
    • -
    • - Ctrl+Alt+Espace : Palette de - commandes -
    • -
    • - Escape : Fermer la palette / - les suggestions -
    • -
    - -

    Onglets

    -
      -
    • - Ctrl+W : Fermer l'onglet actif -
    • -
    • Ctrl+Tab : Onglet suivant
    • -
    • - Ctrl+Shift+Tab : Onglet - précédent -
    • -
    - -

    Éditeur CodeMirror

    -
      -
    • - Ctrl+F : Rechercher dans le - fichier -
    • -
    • Ctrl+Z : Annuler
    • -
    • Ctrl+Y : Refaire
    • -
    • - Ctrl+S : Sauvegarder (si - configuré) -
    • -
    -
    - -
    -

    🤖 Intelligence Artificielle dans l'Éditeur

    -

    - ObsiGate intègre un assistant IA directement - dans l'éditeur de texte. Pour l'activer, - configurez au moins un provider AI dans le - fichier .env (DeepSeek, OpenRouter - ou Gemini). -

    - -

    Activation

    -
      -
    1. - Ajoutez votre clé API dans - .env : - DEEPSEEK_API_KEY=sk-... -
    2. -
    3. - Redémarrez le conteneur : - docker compose down && docker compose - up -d --build -
    4. -
    5. - Ouvrez un fichier en mode Édition (bouton ✏️ - Éditer) -
    6. -
    7. - La barre d'outils AI apparaît sous le titre - de l'éditeur -
    8. -
    - -

    Barre d'outils AI

    -

    - La barre d'outils contient les boutons suivants - : -

    -
      -
    • - ✦ AI — Complétion inline - (Ctrl+J). Complète - automatiquement le texte là où se trouve le - curseur. -
    • -
    • - Éditer ▾ — Menu de - modification du texte sélectionné :
        -
      • - 🪄 - Improve writing : - Améliore la qualité, la clarté et le - flux du texte -
      • -
      • - 🔤 - Fix spelling & grammar - : Corrige les fautes d'orthographe - et de grammaire -
      • -
      • - 📏 Make shorter : - Rend le texte plus concis tout en - préservant l'information -
      • -
      • - 📐 Make longer : - Ajoute des détails, exemples ou - explications -
      • -
      • - 📋 - Simplify language : - Simplifie le langage, évite le - jargon -
      • -
      -
    • -
    • - Ton ▾ — Change le ton du - texte : -
        -
      • - 💼 Professional : - Ton formel et professionnel -
      • -
      • - 💬 Casual : Ton - décontracté et conversationnel -
      • -
      -
    • -
    • - Traduire ▾ — Traduit le - texte sélectionné vers une autre langue :
        -
      • - 🇬🇧 English · 🇨🇳 Chinese · 🇯🇵 - Japanese · 🇩🇪 German · 🇫🇷 French · - 🇪🇸 Spanish -
      • -
      -
    • -
    • - Générer ▾ — Génère du - contenu à partir de la sélection :
        -
      • - ℹ️ Explain this : - Explique le texte sélectionné de - façon claire -
      • -
      • - 📝 Summarize : - Résume le texte de façon concise -
      • -
      • - ✏️ - Continue writing : - Continue l'écriture à partir du - texte -
      • -
      -
    • -
    • - 💬 Réécrire — Réécrit le - texte selon vos instructions personnalisées. - Une boîte de dialogue vous demande votre - instruction.
    • -
    • - 🧰 Boîte ▾ — Outils de - conversion : -
        -
      • - 📋 - Convert to list : - Transforme le texte en liste - Markdown -
      • -
      • - 📊 - Convert to table : - Transforme en tableau Markdown -
      • -
      • - ⚙️ - Generate frontmatter - : Génère un bloc YAML frontmatter -
      • -
      • - 🔷 - Convert to canvas : - Convertit en diagramme Mermaid.js -
      • -
      -
    • -
    - -

    Indicateurs visuels

    -
      -
    • - Pendant une requête AI, un toast - ⏳ AI: traitement en cours... - s'affiche -
    • -
    • - Une fois terminé, - AI: texte traité ✓ confirme - le succès -
    • -
    • - En cas d'erreur de clé API : - AI: clé API invalide -
    • -
    - -

    Sauvegarde automatique

    -

    - L'éditeur sauvegarde automatiquement après 2 - secondes d'inactivité. Le bouton de sauvegarde - flashe en vert brièvement pour - confirmer. -

    - -

    Providers supportés

    - - - - - Modèle par défaut - - - - - - - - - - - - - - - - -
    ProviderVariable .env
    DeepSeekDEEPSEEK_API_KEYdeepseek-chat
    OpenRouterOPENROUTER_API_KEYopenai/gpt-4o-mini
    GeminiGEMINI_API_KEYgemini-2.0-flash
    -

    - Pour changer de provider par défaut : - AI_DEFAULT_PROVIDER=openrouter -

    -
    - - -
    -

    🔗 Partage et Webhooks

    - -

    Publication publique

    -

    - ObsiGate permet de partager des documents via un - lien public temporaire. -

    -
      -
    • - Bouton Partager : Dans les - actions du fichier, génère un lien unique
    • -
    • - Token unique : 64 - caractères hexadécimaux, impossible à - deviner
    • -
    • - Expiration configurable : - Durée de vie en heures
    • -
    • - Lecture seule : La vue - publique n'affiche que le contenu sans - édition
    • -
    • - Gestion des liens : Liste - et révocation dans les Configurations
    • -
    • - Export PDF : Téléchargement - du document partagé en PDF via/s/{token}/pdf -
    • -
    -
    - - -
    -

    🪝 Webhooks

    -

    - Les webhooks permettent à ObsiGate de - notifier automatiquement des services - externes - lorsque des fichiers ou dossiers sont modifiés. - Chaque événement déclenche un - POST HTTP vers l'URL de votre - choix, avec un payload JSON détaillé. -

    - -

    Cas d'usage

    -
      -
    • - Automatisation CI/CD : - Déclencher un build quand une note de - procédure est mise à jour
    • -
    • - Synchronisation : Copier - les nouveaux fichiers vers un autre système - (SharePoint, Google Drive)
    • -
    • - Notifications : Alerter un - canal Slack/Discord quand un document est - créé
    • -
    • - Audit externe : Logger - toutes les modifications dans une base de - données externe
    • -
    • - Déploiement : Publier un - article de blog quand un fichier est marquépublish: true -
    • -
    - -

    Événements supportés

    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - Événement - - Déclencheur - - Données -
    - file_created - - Création via l'API ou la palette - - vault, - path -
    - file_deleted - - Suppression via l'API ou l'éditeur - - vault, - path -
    - file_renamed - - Renommage via l'API - - vault, - old_path, - new_path -
    - directory_created - - Création de dossier via l'API - - vault, - path -
    - directory_deleted - - Suppression de dossier via l'API - - vault, - path -
    - directory_renamed - - Renommage de dossier via l'API - - vault, - old_path, - new_path -
    -
    -

    - Note : l'événement - file_modified est réservé pour - usage futur. Les modifications de contenu - via l'éditeur ne déclenchent pas encore de - webhook. -

    - -

    Format du payload

    -

    - Chaque webhook reçoit un POST avec - Content-Type: application/json : -

    -
    {
    -  "event": "file_created",
    -  "timestamp": "2026-06-03T14:30:00.123456+00:00",
    -  "data": {
    -    "vault": "IT",
    -    "path": "procedures/deploiement.md"
    -  }
    -}
    - -

    Sécurité : signature HMAC-SHA256

    -

    - Si vous configurez un secret, chaque requête - inclut un header - X-ObsiGate-Signature : -

    -
    X-ObsiGate-Signature: sha256=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
    -

    - Pour vérifier côté récepteur : calculez - HMAC-SHA256(corps_brut, secret) et - comparez. Le header - X-ObsiGate-Event contient aussi le - type d'événement pour un routage rapide. -

    - -

    Configuration

    -

    - Les webhooks se gèrent dans le modal - Configurations (⚙️ menu - Options), section Webhooks. Réservé aux - administrateurs. -

    -
      -
    1. - Allez dans ⚙️ Configurations → onglet - Webhooks -
    2. -
    3. - Remplissez : - Nom (descriptif), - URL (endpoint cible), - Secret (optionnel) -
    4. -
    5. Cochez les événements à écouter
    6. -
    7. Cliquez Ajouter
    8. -
    -

    - Les webhooks peuvent être activés/désactivés, - modifiés ou supprimés à tout moment. Le - last_fired_at indique la dernière - exécution. -

    - -

    Exemples concrets

    - -

    Récepteur Python (Flask)

    -
    from flask import Flask, request\nimport hmac, hashlib\n\napp = Flask(__name__)\nWEBHOOK_SECRET = "mon-secret"  # même que dans ObsiGate\n\n@app.route("/webhook", methods=["POST"])\ndef webhook():\n    # Vérifier la signature\n    signature = request.headers.get("X-ObsiGate-Signature", "")\n    body = request.get_data()\n    expected = "sha256=" + hmac.new(\n        WEBHOOK_SECRET.encode(), body, hashlib.sha256\n    ).hexdigest()\n    if not hmac.compare_digest(signature, expected):\n        return "Invalid signature", 403\n\n    payload = request.get_json()\n    print(f"Événement: {payload['event']}")\n    print(f"Fichier: {payload['data']['vault']}/{payload['data']['path']}")\n    return "OK", 200\n\napp.run(port=5000)
    - -

    n8n / Make (no-code)

    -
      -
    1. - Créez un - Webhook Trigger dans n8n ou - Make -
    2. -
    3. - Copiez l'URL générée (ex: - https://n8n.monserveur.com/webhook/abc123) -
    4. -
    5. - Dans ObsiGate, ajoutez un webhook pointant - vers cette URL -
    6. -
    7. Sélectionnez les événements souhaités
    8. -
    9. - Le workflow se déclenche automatiquement à - chaque événement -
    10. -
    - -

    Notification Discord

    -

    - Utilisez un webhook relais (n8n, Make, ou un - script) pour transformer le payload ObsiGate en - message Discord : -

    -
    # Exemple avec curl + jq dans un script bash
    -WEBHOOK_URL="https://discord.com/api/webhooks/..."
    -OBSIGATE_SECRET="mon-secret"
    -
    -# Lire le payload depuis stdin
    -read -r payload
    -event=$(echo "$payload" | jq -r '.event')
    -path=$(echo "$payload" | jq -r '.data.path')
    -
    -curl -H "Content-Type: application/json" -d "{
    -  \"content\": \"📝 **$event** — $path\"
    -}" "$WEBHOOK_URL"
    - -

    Tester avec curl

    -
    # Simuler ce qu'ObsiGate envoie (pour tester votre endpoint)
    -curl -X POST https://votre-serveur.com/webhook \
    -  -H "Content-Type: application/json" \
    -  -H "X-ObsiGate-Event: file_created" \
    -  -H "X-ObsiGate-Signature: sha256=$(echo -n '{"event":"file_created",...}' | openssl dgst -sha256 -hmac 'mon-secret' | cut -d' ' -f2)" \
    -  -d '{"event":"file_created","timestamp":"2026-06-03T14:30:00Z","data":{"vault":"IT","path":"notes/test.md"}}'
    - -

    Limitations actuelles

    -
      -
    • - Timeout de 5 secondes par - requête — les webhooks sont "fire and - forget" (pas de retry) -
    • -
    • - Les modifications détectées par le watcher - filesystem (watchdog) - ne déclenchent pas de - webhooks — seules les opérations via l'API - REST sont prises en compte -
    • -
    • - file_modified n'est pas encore - dispatché (réservé pour version future) -
    • -
    • Pas de retry automatique en cas d'échec
    • -
    • - Pas de filtrage par vault — un webhook - écoute toutes les vaults -
    • -
    -
    -
    -

    💾 Sauvegardes et Audits

    - -

    Backup automatique

    -

    - ObsiGate crée automatiquement des sauvegardes - avant chaque modification destructive. -

    -
      -
    • - Avant écriture : Sauvegarde - du contenu original dans - .obsigate-backup/ -
    • -
    • - Timestamp : Chaque backup - est horodaté
    • -
    • - Répertoire dédié : - .obsigate-backup/ dans le - répertoire de la vault -
    • -
    - -

    Audit log

    -

    - Toutes les opérations sensibles sont tracées - dans un journal. -

    -
      -
    • - Journal : Fichier - data/audit.log au format JSON - lines -
    • -
    • - Événements tracés : - Écritures, suppressions, changements de - configuration
    • -
    • - Rotation : Rotation - automatique à 10 Mo
    • -
    -
    - - -
    -

    🛡️ Sécurité

    - -

    Authentification

    -
      -
    • - JWT + Argon2id : Tokens JWT - avec mots de passe hachés Argon2id
    • -
    • - Contrôle d'accès par vault - : Chaque utilisateur voit uniquement ses - vaults -
    • -
    • - Refresh tokens : Cookies - HttpOnly avec rotation automatique -
    • -
    • - Rate limiting : 10 - tentatives / 15 min par IP + verrouillage - compte -
    • -
    • - Compte admin : Créé - automatiquement au premier démarrage
    • -
    - -

    Protection

    -
      -
    • - Secret redactor : Masque - JWT, clés API, tokens GitHub dans les - aperçus
    • -
    • - Path traversal : Validation - des chemins contre les attaques - ../ -
    • -
    • - Headers CSP : - Content-Security-Policy, X-Frame-Options, - XSS-Protection -
    • -
    • - Atomic writes : Écriture - via fichier temporaire + renommage atomique
    • -
    • - Non-root Docker : Conteneur - tourne avec UID 1000 -
    • -
    -
    - -
    -

    💡 Astuces et bonnes pratiques

    - -

    Workflow recommandé

    -
      -
    1. - Sélectionnez un contexte : - Choisissez un vault pour réduire le bruit
    2. -
    3. - Explorez l'arborescence : - Naviguez dans les dossiers -
    4. -
    5. - Utilisez les tags : Filtrez - par tags pour affiner -
    6. -
    7. - Recherchez intelligemment : - Combinez opérateurs et texte libre
    8. -
    9. - Profitez de l'historique : - Réutilisez vos recherches fréquentes
    10. -
    - -

    Optimisations

    -
      -
    • - Masquez la sidebar : Plus - d'espace pour le contenu -
    • -
    • - Utilisez le filtrage sidebar - : Plus rapide que la recherche globale pour - trouver un fichier -
    • -
    • - Favorisez les opérateurs : - tag: et - vault: accélèrent la recherche -
    • -
    • - Breadcrumb cliquable : - Repositionnez rapidement la sidebar -
    • -
    - -

    Trucs et astuces

    -
      -
    • - Navigation visuelle : Le - breadcrumb repositionne automatiquement la - sidebar -
    • -
    • - Gestion de l'espace : - Réduisez les sections Vaults/Tags selon vos - besoins
    • -
    • - Confort de lecture : - Ajustez la largeur de la sidebar -
    • -
    • - Mobile-friendly : Utilisez - le bouton hamburger sur mobile -
    • -
    • - Wikilinks : Naviguez entre - notes comme dans Obsidian -
    • -
    • - Images : Support complet - des syntaxes Obsidian -
    • -
    - -

    Cas d'usage avancés

    -
      -
    • - Recherche multi-critères : - tag:docker tag:linux vault:IT - nginx -
    • -
    • - Exploration par tags : - Cliquez sur un tag dans une note pour voir - toutes les notes similaires -
    • -
    • - Édition rapide : Ouvrez - l'éditeur, modifiez, sauvegardez
    • -
    • - Export : Téléchargez des - fichiers pour backup ou partage
    • -
    • - Multi-fenêtres : Ouvrez - plusieurs notes dans des onglets séparés
    • -
    -
    - - -
    -
    -
    -
    - - - - - - - - - - - -
    -
    -
    - Fichiers ouverts -
    - - -
    -
    -
    -
    -
    - - - -
    -
    -
    - Conflit hors-ligne -
    - -
    -
    -

    -
    - - -
    -
    -
    -
    - -
    -
    - -
    - -

    ObsiGate

    -

    Vos notes Obsidian,
    simplement accessibles.

    - v2.0.0-dev -
    -
    -
    -
    - — - Fichiers -
    -
    - — - Vaults -
    -
    - 285 - Tests -
    -
    -
    -

    Construit avec

    -
    - 🐍 FastAPI - ⚡ vanilla JS - 🎨 CSS custom - 🐳 Docker - 🔍 TF-IDF - 📝 CodeMirror 6 - 🧜 Mermaid.js - 🧠 Argon2id - 🔄 Watchdog - 📊 WeasyPrint - 🧪 Playwright - 🤖 AI multi-provider -
    -
    - -
    -
    -
    - - diff --git a/desktop/frontend-static/js/ai.js b/desktop/frontend-static/js/ai.js deleted file mode 100644 index 2fe9d62..0000000 --- a/desktop/frontend-static/js/ai.js +++ /dev/null @@ -1,457 +0,0 @@ -/* ObsiGate — AI Editor Toolbar - Provides AI-powered text editing features: - - Inline completion (Ctrl+J) - - Edit (improve, fix spelling, shorter, longer, simplify) - - Tone (professional, casual) - - Translate (multiple languages) - - Generate (explain, summarize, continue) - - AI Custom Rewrite - - AI Toolbox (to list, to table, frontmatter, to canvas) -*/ -import { api } from './auth.js'; -import { t } from './i18n.js'; - -// ── API call helper ── -async function aiAction(endpoint, text, extra = {}) { - const body = { text, ...extra }; - const data = await api(`/api/ai/${endpoint}`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(body), - }); - return data.result; -} - -// ── Get selected text from CodeMirror ── -function getSelection(editorView) { - if (!editorView) return ''; - const { from, to } = editorView.state.selection.main; - if (from === to) { - // No selection — get entire document - return editorView.state.doc.toString(); - } - return editorView.state.doc.sliceString(from, to); -} - -// ── Replace or insert text ── -function replaceSelection(editorView, newText, mode = 'replace') { - if (!editorView) return; - const { from, to } = editorView.state.selection.main; - if (mode === 'append') { - // Insert at end of selection - editorView.dispatch({ - changes: { from: to, insert: '\n' + newText }, - selection: { anchor: to + 1 + newText.length }, - }); - } else if (mode === 'before') { - editorView.dispatch({ - changes: { from: from, insert: newText + '\n' }, - }); - } else { - // Replace selection - editorView.dispatch({ - changes: { from, to, insert: newText }, - selection: { anchor: from + newText.length }, - }); - } -} - -// ── Show toast notification ── -function showToast(msg, type = 'info') { - // Use global showToast if available, otherwise console - if (typeof window._obsigateShowToast === 'function') { - window._obsigateShowToast(msg, type); - } -} - -// ── Dropdown menu builder ── -function createMenu(items, parentEl) { - // Remove any existing menu - const existing = document.querySelector('.ai-dropdown-menu'); - if (existing) existing.remove(); - - const menu = document.createElement('div'); - menu.className = 'ai-dropdown-menu'; - - // Position relative to parent, but attached to body to avoid - // being clipped by overflow:hidden on the editor container. - const rect = parentEl.getBoundingClientRect(); - const menuTop = rect.bottom + 4; - const menuLeft = rect.left; - - Object.assign(menu.style, { - position: 'fixed', - top: menuTop + 'px', - left: menuLeft + 'px', - background: 'var(--bg-primary)', - border: '1px solid var(--border-color)', - borderRadius: '6px', - padding: '4px 0', - minWidth: '200px', - maxHeight: '60vh', - overflowY: 'auto', - zIndex: '10000', - boxShadow: '0 4px 16px rgba(0,0,0,0.4)', - }); - - // If menu overflows bottom of viewport, flip above the button - requestAnimationFrame(() => { - const menuRect = menu.getBoundingClientRect(); - if (menuRect.bottom > window.innerHeight - 8) { - menu.style.top = Math.max(8, rect.top - menuRect.height - 4) + 'px'; - } - // If menu overflows right edge, align right - if (menuRect.right > window.innerWidth - 8) { - menu.style.left = Math.max(8, window.innerWidth - menuRect.width - 8) + 'px'; - } - }); - - items.forEach(item => { - const el = document.createElement('div'); - el.className = 'ai-menu-item'; - Object.assign(el.style, { - padding: '6px 12px', - cursor: 'pointer', - display: 'flex', - alignItems: 'center', - gap: '8px', - fontSize: '0.8rem', - color: 'var(--text-primary)', - whiteSpace: 'nowrap', - background: 'transparent', - transition: 'background 0.1s', - }); - el.innerHTML = item.label; - if (item.hint) { - const hint = document.createElement('span'); - hint.style.cssText = 'margin-left:auto;font-size:0.65rem;color:var(--text-muted)'; - hint.textContent = item.hint; - el.appendChild(hint); - } - if (item.children) { - const arrow = document.createElement('span'); - arrow.style.cssText = 'margin-left:auto;font-size:0.7rem;color:var(--text-muted)'; - arrow.textContent = '▶'; - el.appendChild(arrow); - } - el.addEventListener('mouseenter', () => { - el.style.background = 'rgba(255,255,255,0.06)'; - // Show submenu - if (item.children) { - const sub = el.querySelector('.ai-submenu'); - if (!sub) { - const subMenu = createSubMenu(item.children, el); - el.appendChild(subMenu); - } - } - }); - el.addEventListener('mouseleave', (e) => { - el.style.background = 'transparent'; - }); - el.addEventListener('click', (e) => { - e.stopPropagation(); - if (item.action) item.action(); - menu.remove(); - }); - menu.appendChild(el); - }); - - document.body.appendChild(menu); - - // Close on outside click - const closeHandler = (e) => { - if (!menu.contains(e.target)) { - menu.remove(); - document.removeEventListener('click', closeHandler); - } - }; - setTimeout(() => document.addEventListener('click', closeHandler), 0); -} - -function createSubMenu(items, parentEl) { - const menu = document.createElement('div'); - menu.className = 'ai-submenu'; - Object.assign(menu.style, { - position: 'absolute', - left: '100%', - top: '0', - background: 'var(--bg-primary)', - border: '1px solid var(--border-color)', - borderRadius: '6px', - padding: '4px 0', - minWidth: '180px', - zIndex: '101', - boxShadow: '0 4px 16px rgba(0,0,0,0.4)', - }); - - items.forEach(item => { - const el = document.createElement('div'); - el.className = 'ai-menu-item'; - Object.assign(el.style, { - padding: '6px 12px', - cursor: 'pointer', - fontSize: '0.78rem', - color: 'var(--text-primary)', - whiteSpace: 'nowrap', - }); - el.innerHTML = item.label; - el.addEventListener('mouseenter', () => { el.style.background = 'rgba(255,255,255,0.06)'; }); - el.addEventListener('mouseleave', () => { el.style.background = 'transparent'; }); - el.addEventListener('click', (e) => { - e.stopPropagation(); - if (item.action) item.action(); - // Close all menus - document.querySelectorAll('.ai-dropdown-menu, .ai-submenu').forEach(m => m.remove()); - }); - menu.appendChild(el); - }); - - return menu; -} - -// ── Main AI Toolbar ── -export async function createAIToolbar(container, getEditorView) { - // Check if AI is configured - let aiConfigured = false; - try { - const status = await api('/api/ai/status'); - aiConfigured = status.configured; - } catch { aiConfigured = false; } - - if (!aiConfigured) { - const hint = document.createElement('div'); - hint.style.cssText = 'padding:6px 12px;font-size:0.7rem;color:var(--text-muted);border-bottom:1px solid var(--border-color)'; - hint.textContent = t('ai.not_configured'); - container.appendChild(hint); - return; - } - - const toolbar = document.createElement('div'); - toolbar.className = 'ai-toolbar'; - Object.assign(toolbar.style, { - display: 'flex', - alignItems: 'center', - gap: '2px', - padding: '4px 8px', - borderBottom: '1px solid var(--border-color)', - background: 'var(--bg-secondary)', - flexWrap: 'wrap', - position: 'sticky', - top: '0', - zIndex: '5', - }); - - function ev() { return getEditorView(); } - - // ── Inline completion button ── - const aiBtn = document.createElement('button'); - aiBtn.className = 'ai-toolbar-btn'; - aiBtn.innerHTML = '✦ AI'; - Object.assign(aiBtn.style, { - color: '#60a5fa', - fontWeight: '600', - fontSize: '0.75rem', - background: 'none', - border: 'none', - cursor: 'pointer', - padding: '3px 8px', - borderRadius: '4px', - }); - aiBtn.title = t('ai.inline_completion_title'); - aiBtn.addEventListener('click', async () => { - const v = ev(); - if (!v) return; - const text = getSelection(v); - if (!text.trim()) return; - const origHTML = aiBtn.innerHTML; - aiBtn.innerHTML = '⏳ AI...'; - aiBtn.disabled = true; - try { - const result = await aiAction('inline-complete', text); - replaceSelection(v, result, 'append'); - showToast(t('ai.completion_added'), 'success'); - } catch (e) { - showToast('AI: ' + (String(e.message || e).includes('401') ? t('ai.error_invalid_key') : e.message), 'error'); - } finally { - aiBtn.innerHTML = origHTML; - aiBtn.disabled = false; - } - }); - - // ── Edit menu ── - const editBtn = createDropdownBtn(t('ai.edit'), [ - { label: '🪄 Improve writing', action: () => action('improve'), hint: t('ai.hint_improve') }, - { label: '🔤 Fix spelling & grammar', action: () => action('fix-spelling'), hint: 'Corrige les fautes' }, - { label: '📏 Make shorter', action: () => action('make-shorter'), hint: 'Rend le texte plus concis' }, - { label: '📐 Make longer', action: () => action('make-longer'), hint: t('ai.hint_add_details') }, - { label: '📋 Simplify language', action: () => action('simplify'), hint: 'Simplifie le langage' }, - ], t('ai.hint_edit_selection')); - - // ── Tone menu ── - const toneBtn = createDropdownBtn('Ton', [ - { label: '💼 Professional tone', action: () => action('tone', { tone: 'professional' }) }, - { label: '💬 Casual tone', action: () => action('tone', { tone: 'casual' }) }, - ], 'Change le ton du texte'); - - // ── Translate menu ── - const translateBtn = createDropdownBtn('Traduire', [ - { label: '🇬🇧 English', action: () => action('translate', { target_lang: 'English' }) }, - { label: '🇨🇳 Chinese', action: () => action('translate', { target_lang: 'Chinese' }) }, - { label: '🇯🇵 Japanese', action: () => action('translate', { target_lang: 'Japanese' }) }, - { label: '🇩🇪 German', action: () => action('translate', { target_lang: 'German' }) }, - { label: '🇫🇷 French', action: () => action('translate', { target_lang: 'French' }) }, - { label: '🇪🇸 Spanish', action: () => action('translate', { target_lang: 'Spanish' }) }, - ], t('ai.hint_translate')); - - // ── Generate menu ── - const genBtn = createDropdownBtn(t('ai.generate'), [ - { label: 'ℹ️ Explain this', action: () => action('explain', {}, 'append') }, - { label: '📝 Summarize', action: () => action('summarize', {}, 'append') }, - { label: '✏️ Continue writing', action: () => action('continue', {}, 'append') }, - ], t('ai.hint_generate')); - - // ── Custom Rewrite ── - const rewriteBtn = document.createElement('button'); - rewriteBtn.className = 'ai-toolbar-btn'; - rewriteBtn.innerHTML = t('ai.rewrite'); - rewriteBtn.title = t('ai.rewrite_title'); - Object.assign(rewriteBtn.style, { - fontSize: '0.7rem', - background: 'transparent', - border: 'none', - cursor: 'pointer', - padding: '3px 6px', - borderRadius: '4px', - color: 'var(--text-primary)', - }); - rewriteBtn.addEventListener('click', async () => { - const v = ev(); - if (!v) return; - const text = getSelection(v); - const instruction = prompt(t('ai.rewrite_prompt'), ''); - if (!instruction) return; - try { - const result = await aiAction('rewrite', text, { instruction }); - replaceSelection(v, result); - showToast(t('ai.text_rewritten'), 'success'); - } catch (e) { - showToast('AI: ' + (String(e.message || e).includes('401') ? t('ai.error_invalid_key') : e.message), 'error'); - } - }); - - // ── Toolbox menu ── - const toolboxBtn = createDropdownBtn(t('ai.toolbox'), [ - { label: '📋 Convert to list', action: () => action('to-list') }, - { label: '📊 Convert to table', action: () => action('to-table') }, - { label: '⚙️ Generate frontmatter', action: () => action('frontmatter', {}, 'before') }, - { label: '🔷 Convert to canvas', action: () => action('to-canvas', {}, 'append') }, - ], 'Outils de conversion'); - - toolbar.appendChild(aiBtn); - toolbar.appendChild(createSeparator()); - toolbar.appendChild(editBtn); - toolbar.appendChild(toneBtn); - toolbar.appendChild(translateBtn); - toolbar.appendChild(createSeparator()); - toolbar.appendChild(genBtn); - toolbar.appendChild(rewriteBtn); - toolbar.appendChild(toolboxBtn); - - container.insertBefore(toolbar, container.firstChild); - - // ── Action helper ── - async function action(endpoint, extra = {}, mode = 'replace') { - const v = ev(); - if (!v) return; - const text = getSelection(v); - if (!text.trim()) { - showToast(t('ai.select_text'), 'warning'); - return; - } - showToast(t('ai.processing'), 'info'); - - // Show processing indicator in the editor header - _showProcessingIndicator(true); - - // Dispatch AI processing start event - document.dispatchEvent(new CustomEvent('ai-processing-start', { detail: { endpoint, mode } })); - try { - const result = await aiAction(endpoint, text, extra); - replaceSelection(v, result, mode); - showToast(t('ai.text_processed'), 'success'); - } catch (e) { - const msg = String(e.message || e); - if (msg.includes('401')) { - showToast(t('ai.invalid_api_key'), 'error'); - } else if (msg.includes('402') || msg.includes('429')) { - showToast(t('ai.quota_exceeded'), 'error'); - } else { - showToast('AI: ' + msg, 'error'); - } - } finally { - _showProcessingIndicator(false); - // Dispatch AI processing end event - document.dispatchEvent(new CustomEvent('ai-processing-end')); - } - } - - // ── In-editor processing indicator ── - function _showProcessingIndicator(show) { - let el = document.getElementById('ai-processing-indicator'); - if (show) { - if (!el) { - el = document.createElement('span'); - el.id = 'ai-processing-indicator'; - el.className = 'ai-processing-indicator'; - el.innerHTML = ' AI...'; - el.title = 'Traitement AI en cours'; - const header = document.querySelector('#editor-modal .editor-header'); - if (header) header.appendChild(el); - } - el.style.display = 'inline-flex'; - } else if (el) { - el.style.display = 'none'; - } - } - // ── Keyboard shortcut Ctrl+J for inline completion ── - document.addEventListener('keydown', (e) => { - if (e.ctrlKey && e.key === 'j') { - const modal = document.getElementById('editor-modal'); - if (!modal || !modal.classList.contains('active')) return; - e.preventDefault(); - aiBtn.click(); - } - }); - - return toolbar; -} - -function createDropdownBtn(text, items, tooltip = '') { - const btn = document.createElement('button'); - btn.className = 'ai-toolbar-btn'; - btn.innerHTML = text + ' ▾'; - btn.title = tooltip || text; - Object.assign(btn.style, { - position: 'relative', - fontSize: '0.7rem', - background: 'none', - border: 'none', - cursor: 'pointer', - padding: '3px 6px', - borderRadius: '4px', - color: 'var(--text-primary)', - }); - btn.addEventListener('click', (e) => { - e.stopPropagation(); - createMenu(items, btn); - }); - btn.addEventListener('mouseenter', () => { btn.style.background = 'rgba(255,255,255,0.08)'; }); - btn.addEventListener('mouseleave', () => { btn.style.background = 'transparent'; }); - return btn; -} - -function createSeparator() { - const sep = document.createElement('span'); - sep.style.cssText = 'width:1px;height:16px;background:var(--border-color);margin:0 2px'; - return sep; -} diff --git a/desktop/frontend-static/js/app.js b/desktop/frontend-static/js/app.js deleted file mode 100644 index c878525..0000000 --- a/desktop/frontend-static/js/app.js +++ /dev/null @@ -1,107 +0,0 @@ -/* ObsiGate — Module orchestrator (ES modules). - Replaces the monolithic frontend/app.js IIFE. - All code lives in frontend/js/*.js modules. */ - -import * as UI from './ui.js'; -import * as Utils from './utils.js'; -import { initI18n, t } from './i18n.js'; - -// Wire up AI toolbar toast (avoids circular import in utils.js) -window._obsigateShowToast = UI.showToast; -import * as Sidebar from './sidebar.js'; -import * as Auth from './auth.js'; -import * as Viewer from './viewer.js'; -import * as Sync from './sync.js'; -import { initGraphView } from './graph.js'; -import * as Legacy from './legacy.js'; -import { initCommandPalette } from './palette.js'; -import { initMobileToolbar } from './mobile-toolbar.js'; -import { initDragDrop } from './dragdrop.js'; -import { initMermaid, setupFocusMode } from './mermaid-viewer.js'; -import PaneManager from './pane-manager.js'; - -// ========================================================================= -// Initialization — mirrors the original app.js init() ordering -// ========================================================================= -async function init() { - // 1. Init i18n FIRST — loads fallback (FR) + selected locale - // Server language check may fail (no auth yet), falls to localStorage - // LocalStorage has correct language if user set it previously - await initI18n(); - - // 2. Init auth — now t() works inside showApp()/renderUserMenu() - const authOk = await Auth.AuthManager.initAuth(); - - UI.initTheme(); - UI.initHeaderMenu(); - UI.initCustomDropdowns(); - - document.getElementById("theme-toggle").addEventListener("click", UI.toggleTheme); - document.getElementById("header-logo").addEventListener("click", Legacy.goHome); - const refreshBtn = document.getElementById("header-refresh-btn"); - if (refreshBtn) refreshBtn.addEventListener("click", Legacy.goHome); - - Legacy.initSearch(); - UI.initSidebarToggle(); - UI.initMobile(); - Sidebar.initVaultContext(); - Legacy.initSidebarTabs(); - Legacy.initHelpModal(); - Legacy.initConfigModal(); - Legacy.initAboutModal(); - Sidebar.initSidebarFilter(); - UI.initSidebarResize(); - Utils.initEditor(); - Auth.initLoginForm(); - Legacy.initRecentTab(); - - UI.RightSidebarManager.init(); - UI.FindInPageManager.init(); - UI.ContextMenuManager.init(); - UI.TabManager.init(); - PaneManager.init(); - initCommandPalette(); - initMobileToolbar(); - - if (authOk) { - Legacy.initSyncStatus(); - - try { - await Promise.all([Legacy.loadVaultSettings(), Sidebar.loadVaults(), Sidebar.loadTags()]); - - initDragDrop(); - - Legacy.DashboardRecentWidget.init(); - - const urlParams = new URLSearchParams(window.location.search); - if (urlParams.get("popup") === "true") { - document.body.classList.add("popup-mode"); - } - - if (window.location.hash && window.location.hash.startsWith("#file=")) { - const hashVal = window.location.hash.substring(6); - const sepIndex = hashVal.indexOf(":"); - if (sepIndex > -1) { - const vault = decodeURIComponent(hashVal.substring(0, sepIndex)); - const path = decodeURIComponent(hashVal.substring(sepIndex + 1)); - Viewer.openFile(vault, path); - } - } else if (urlParams.get("popup") !== "true") { - Legacy.showWelcome(); - } - } catch (err) { - console.error("Failed to initialize ObsiGate:", err); - UI.showToast(t("error.initialization"), "error"); - } - } - - initGraphView(); - initMermaid(); - setupFocusMode(); - Utils.safeCreateIcons(); -} - -document.addEventListener("DOMContentLoaded", () => { - init(); - Sync.init(); -}); diff --git a/desktop/frontend-static/js/auth.js b/desktop/frontend-static/js/auth.js deleted file mode 100644 index 6c2d8f4..0000000 --- a/desktop/frontend-static/js/auth.js +++ /dev/null @@ -1,579 +0,0 @@ -/* ObsiGate — Authentication: API helper, AuthManager, login form, AdminPanel */ -import { state } from './state.js'; -import { safeCreateIcons } from './utils.js'; -import { showToast, closeHeaderMenu } from './ui.js'; -import { t, getLocale, setLocale } from './i18n.js'; -import { showWelcome } from './viewer.js'; - -// ── Global logout handler for header dropdown onclick ──────────────────── -// Defined at module top level so it's always available, even if -// renderUserMenu() hasn't been called yet. -// Uses a getter to lazy-resolve AuthManager (defined later in this module). -window.handleLogout = () => { - AuthManager.logout(); -}; - -// --------------------------------------------------------------------------- -// API helpers -// --------------------------------------------------------------------------- - -/** - * Fetch JSON from an API endpoint with optional AbortSignal support. - * Surfaces errors to the user via toast instead of silently failing. - * - * @param {string} path - API URL path. - * @param {object} [opts] - Fetch options (may include signal). - * @returns {Promise} Parsed JSON response. - */ -async function api(path, opts) { - var res; - try { - // Inject auth header if authenticated - const authHeaders = AuthManager.getAuthHeaders(); - const mergedOpts = opts || {}; - // Auto-set Content-Type for JSON bodies - if (mergedOpts.body && typeof mergedOpts.body === "string" && !mergedOpts.headers?.["Content-Type"]) { - mergedOpts.headers = { ...mergedOpts.headers, "Content-Type": "application/json" }; - } - if (authHeaders) { - mergedOpts.headers = { ...mergedOpts.headers, ...authHeaders }; - } - mergedOpts.credentials = "include"; - res = await fetch(path, mergedOpts); - } catch (err) { - if (err.name === "AbortError") throw err; // let callers handle abort - showToast(t("auth.network_error"), "error"); - throw err; - } - if (res.status === 401 && AuthManager._authEnabled) { - // Token expired — try refresh - try { - await AuthManager.refreshAccessToken(); - // Retry the request with new token - const retryHeaders = AuthManager.getAuthHeaders(); - const retryOpts = opts || {}; - retryOpts.headers = { ...retryOpts.headers, ...retryHeaders }; - retryOpts.credentials = "include"; - res = await fetch(path, retryOpts); - } catch (refreshErr) { - AuthManager.clearSession(); - AuthManager.showLoginScreen(); - throw new Error("Session expirée"); - } - } - if (!res.ok) { - var detail = ""; - try { - var body = await res.json(); - detail = body.detail || ""; - } catch (_) { - /* no json body */ - } - showToast(detail || "Erreur API : " + res.status, "error"); - throw new Error(detail || "API error: " + res.status); - } - return res.json(); -} - - -// --------------------------------------------------------------------------- -// AuthManager — Authentication state & token management -// --------------------------------------------------------------------------- - -const AuthManager = { - ACCESS_TOKEN_KEY: "obsigate_access_token", - TOKEN_EXPIRY_KEY: "obsigate_token_expiry", - USER_KEY: "obsigate_user", - _authEnabled: false, - - // ── Token storage (sessionStorage) ───────────────────────────── - - saveToken(tokenData) { - const expiresAt = Date.now() + tokenData.expires_in * 1000; - sessionStorage.setItem(this.ACCESS_TOKEN_KEY, tokenData.access_token); - sessionStorage.setItem(this.TOKEN_EXPIRY_KEY, expiresAt.toString()); - if (tokenData.user) { - sessionStorage.setItem(this.USER_KEY, JSON.stringify(tokenData.user)); - } - }, - - getToken() { - return sessionStorage.getItem(this.ACCESS_TOKEN_KEY); - }, - - getUser() { - const raw = sessionStorage.getItem(this.USER_KEY); - return raw ? JSON.parse(raw) : null; - }, - - isTokenExpired() { - const expiry = sessionStorage.getItem(this.TOKEN_EXPIRY_KEY); - if (!expiry) return true; - // Renew 60s before expiration - return Date.now() > parseInt(expiry) - 60000; - }, - - clearSession() { - sessionStorage.removeItem(this.ACCESS_TOKEN_KEY); - sessionStorage.removeItem(this.TOKEN_EXPIRY_KEY); - sessionStorage.removeItem(this.USER_KEY); - }, - - getAuthHeaders() { - const token = this.getToken(); - if (!token || !this._authEnabled) return null; - return { Authorization: "Bearer " + token }; - }, - - // ── API calls ────────────────────────────────────────────────── - - async login(username, password, rememberMe) { - const response = await fetch("/api/auth/login", { - method: "POST", - headers: { "Content-Type": "application/json" }, - credentials: "include", - body: JSON.stringify({ username, password, remember_me: rememberMe || false }), - }); - if (!response.ok) { - const err = await response.json(); - throw new Error(err.detail || "Erreur de connexion"); - } - const data = await response.json(); - this.saveToken(data); - return data.user; - }, - - async logout() { - try { - const token = this.getToken(); - await fetch("/api/auth/logout", { - method: "POST", - headers: token ? { Authorization: "Bearer " + token } : {}, - credentials: "include", - }); - } catch (e) { - /* continue even if API fails */ - } - this.clearSession(); - this.showLoginScreen(); - }, - - async refreshAccessToken() { - const response = await fetch("/api/auth/refresh", { - method: "POST", - credentials: "include", - }); - if (!response.ok) { - this.clearSession(); - throw new Error("Session expirée"); - } - const data = await response.json(); - const expiry = Date.now() + data.expires_in * 1000; - sessionStorage.setItem(this.ACCESS_TOKEN_KEY, data.access_token); - sessionStorage.setItem(this.TOKEN_EXPIRY_KEY, expiry.toString()); - return data.access_token; - }, - - // ── UI controls ──────────────────────────────────────────────── - - showLoginScreen() { - const app = document.getElementById("app"); - const login = document.getElementById("login-screen"); - if (app) app.classList.add("hidden"); - if (login) { - login.classList.remove("hidden"); - const usernameInput = document.getElementById("login-username"); - if (usernameInput) usernameInput.focus(); - } - }, - - showApp() { - const login = document.getElementById("login-screen"); - const app = document.getElementById("app"); - if (login) login.classList.add("hidden"); - if (app) app.classList.remove("hidden"); - this.renderUserMenu(); - }, - - renderUserMenu() { - const user = this.getUser(); - const userMenu = document.getElementById("user-menu"); - if (!userMenu) return; - if (!user || !this._authEnabled) { - userMenu.innerHTML = ""; - return; - } - userMenu.innerHTML = '' + (user.display_name || user.username) + "" + ''; - safeCreateIcons(); - - const logoutBtn = document.getElementById("logout-btn"); - if (logoutBtn) logoutBtn.addEventListener("click", () => AuthManager.logout()); - - const adminRow = document.getElementById("admin-menu-row"); - if (adminRow) { - if (user.role === "admin") { - adminRow.classList.remove("hidden"); - // Important: use an inline function to ensure we don't bind multiple identical listeners on rerenders, or clean up before - adminRow.onclick = () => { - closeHeaderMenu(); - AdminPanel.show(); - }; - } else { - adminRow.classList.add("hidden"); - } - } - }, - - // ── Initialization ────────────────────────────────────────────── - - async checkAuthStatus() { - try { - const res = await fetch("/api/auth/status"); - const data = await res.json(); - this._authEnabled = data.auth_enabled; - return data; - } catch (e) { - this._authEnabled = false; - return { auth_enabled: false }; - } - }, - - async initAuth() { - const status = await this.checkAuthStatus(); - if (!status.auth_enabled) { - // Auth disabled — show app immediately - this.showApp(); - return true; - } - - // Auth enabled — check for existing session - if (this.getToken() && !this.isTokenExpired()) { - this.showApp(); - return true; - } - - // Try silent refresh - try { - await this.refreshAccessToken(); - // Fetch user info - const token = this.getToken(); - const res = await fetch("/api/auth/me", { - headers: { Authorization: "Bearer " + token }, - credentials: "include", - }); - if (res.ok) { - const user = await res.json(); - sessionStorage.setItem(this.USER_KEY, JSON.stringify(user)); - this.showApp(); - return true; - } - } catch (e) { - /* silent refresh failed */ - } - - // No valid session — show login - this.showLoginScreen(); - return false; - }, -}; - - -// --------------------------------------------------------------------------- -// Login form handler -// --------------------------------------------------------------------------- - -function initLoginForm() { - const form = document.getElementById("login-form"); - if (!form) return; - - form.addEventListener("submit", async (e) => { - e.preventDefault(); - const username = document.getElementById("login-username").value; - const password = document.getElementById("login-password").value; - const rememberMe = document.getElementById("remember-me").checked; - const errorEl = document.getElementById("login-error"); - const btn = document.getElementById("login-btn"); - - btn.disabled = true; - btn.querySelector(".btn-spinner").classList.remove("hidden"); - btn.querySelector(".btn-text").textContent = "Connexion..."; - errorEl.classList.add("hidden"); - - try { - await AuthManager.login(username, password, rememberMe); - AuthManager.showApp(); - - // Re-sync language from server now that we're authenticated - try { - const resp = await fetch('/api/auth/me', { credentials: 'include' }); - if (resp.ok) { - const user = await resp.json(); - if (user.language && user.language !== getLocale()) { - await setLocale(user.language); - } - } - } catch (e) { /* non-bloquant */ } - - // Load app data after successful login - try { - // Dynamic imports to avoid circular dependency with sidebar.js - const { loadVaults, loadTags } = await import('./sidebar.js'); - await Promise.all([loadVaults(), loadTags()]); - // Start SSE sync now that auth cookie is set (dynamic import to avoid circular dep) - const { IndexUpdateManager } = await import('./sync.js'); - IndexUpdateManager.connect(); - // Sync offline file index now that we're authenticated - const { syncFileIndexFromServer } = await import('./offline.js'); - syncFileIndexFromServer(); - // Show dashboard - showWelcome(); - } catch (err) { - console.error("Failed to load data after login:", err); - } - safeCreateIcons(); - } catch (err) { - errorEl.textContent = err.message; - errorEl.classList.remove("hidden"); - document.getElementById("login-password").value = ""; - document.getElementById("login-password").focus(); - } finally { - btn.disabled = false; - btn.querySelector(".btn-spinner").classList.add("hidden"); - btn.querySelector(".btn-text").textContent = "Se connecter"; - } - }); - - // Toggle password visibility - const toggleBtn = document.getElementById("toggle-password"); - if (toggleBtn) { - toggleBtn.addEventListener("click", () => { - const input = document.getElementById("login-password"); - input.type = input.type === "password" ? "text" : "password"; - }); - } -} - - -// --------------------------------------------------------------------------- -// Admin Panel — User management (admin only) -// --------------------------------------------------------------------------- - -const AdminPanel = { - _modal: null, - _allVaults: [], - - show() { - this._createModal(); - this._modal.classList.add("active"); - this._loadUsers(); - }, - - hide() { - if (this._modal) this._modal.classList.remove("active"); - }, - - _createModal() { - if (this._modal) return; - this._modal = document.createElement("div"); - this._modal.className = "editor-modal"; - this._modal.id = "admin-modal"; - this._modal.innerHTML = ` -
    -
    -
    ⚙️ ${t('admin.title')}
    -
    - -
    -
    -
    -
    - -
    -
    -
    -
    - `; - document.body.appendChild(this._modal); - safeCreateIcons(); - - document.getElementById("admin-close").addEventListener("click", () => this.hide()); - document.getElementById("admin-add-user").addEventListener("click", () => this._showUserForm(null)); - }, - - async _loadUsers() { - try { - const users = await api("/api/auth/admin/users"); - // Also load available vaults - try { - const vaultsData = await api("/api/vaults"); - this._allVaults = vaultsData.map((v) => v.name); - } catch (e) { - this._allVaults = []; - } - this._renderUsers(users); - } catch (err) { - document.getElementById("admin-users-list").innerHTML = '

    Erreur : ' + err.message + "

    "; - } - }, - - _renderUsers(users) { - const container = document.getElementById("admin-users-list"); - if (!users.length) { - container.innerHTML = '

    Aucun utilisateur.

    '; - return; - } - let html = '' + - '' + - ''; - users.forEach((u) => { - const vaults = u.vaults.includes("*") ? t('common.all') : u.vaults.join(", ") || t('common.none'); - const status = u.active ? "✅" : "🔴"; - const lastLogin = u.last_login ? new Date(u.last_login).toLocaleDateString(getLocale() === 'fr' ? 'fr-FR' : 'en-US', { day: "numeric", month: "short", year: "numeric", hour: "2-digit", minute: "2-digit" }) : t('common.never'); - html += - "" + - "" + - '" + - '" + - "" + - "" + - '"; - }); - html += "
    ' + t('admin.col_user') + '' + t('admin.col_role') + '' + t('admin.col_vaults') + '' + t('admin.col_status') + '' + t('admin.col_last_login') + '' + t('admin.col_actions') + '
    " + - u.username + - "" + - (u.display_name && u.display_name !== u.username ? "
    " + u.display_name + "" : "") + - "
    ' + - u.role + - "' + - vaults + - "" + - status + - "" + - lastLogin + - "' + - '' + - '' + - "
    "; - container.innerHTML = html; - - // Bind action buttons - container.querySelectorAll('[data-action="edit"]').forEach((btn) => { - btn.addEventListener("click", () => { - const user = users.find((u) => u.username === btn.dataset.username); - if (user) this._showUserForm(user); - }); - }); - container.querySelectorAll('[data-action="delete"]').forEach((btn) => { - btn.addEventListener("click", () => this._deleteUser(btn.dataset.username)); - }); - }, - - _showUserForm(user) { - const isEdit = !!user; - const title = isEdit ? "Modifier : " + user.username : "Nouvel utilisateur"; - const vaultCheckboxes = this._allVaults - .map((v) => { - const checked = user && (user.vaults.includes(v) || user.vaults.includes("*")) ? "checked" : ""; - return '"; - }) - .join(""); - const allVaultsChecked = user && user.vaults.includes("*") ? "checked" : ""; - - // Create form modal overlay - const overlay = document.createElement("div"); - overlay.className = "admin-form-overlay"; - overlay.innerHTML = ` -
    -

    ${title}

    -
    - ${!isEdit ? '
    ' : ""} -
    -
    -
    -
    - -
    ${vaultCheckboxes}
    - -
    - ${isEdit ? '
    " : ""} -
    - - -
    -
    -
    - `; - this._modal.appendChild(overlay); - - document.getElementById("admin-form-cancel").addEventListener("click", () => overlay.remove()); - - document.getElementById("admin-user-form").addEventListener("submit", async (e) => { - e.preventDefault(); - const form = e.target; - const allVaults = document.getElementById("admin-all-vaults").checked; - const selectedVaults = allVaults ? ["*"] : Array.from(form.querySelectorAll('input[name="vault"]:checked')).map((cb) => cb.value); - - try { - if (isEdit) { - const updates = { - display_name: form.display_name.value || null, - role: form.role.value, - vaults: selectedVaults, - }; - if (form.password.value) updates.password = form.password.value; - const activeCheckbox = form.querySelector('input[name="active"]'); - if (activeCheckbox) updates.active = activeCheckbox.checked; - await api("/api/auth/admin/users/" + user.username, { - method: "PATCH", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(updates), - }); - } else { - await api("/api/auth/admin/users", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - username: form.username.value, - password: form.password.value, - display_name: form.display_name.value || null, - role: form.role.value, - vaults: selectedVaults, - }), - }); - } - overlay.remove(); - this._loadUsers(); - showToast(isEdit ? "Utilisateur modifié" : "Utilisateur créé", "success"); - } catch (err) { - showToast(err.message, "error"); - } - }); - }, - - async _deleteUser(username) { - const currentUser = AuthManager.getUser(); - if (currentUser && currentUser.username === username) { - showToast(t("auth.cannot_delete_self"), "error"); - return; - } - if (!confirm("Supprimer l'utilisateur \"" + username + '" ?')) return; - try { - await api("/api/auth/admin/users/" + username, { method: "DELETE" }); - this._loadUsers(); - showToast(t("auth.user_deleted"), "success"); - } catch (err) { - showToast(err.message, "error"); - } - }, -}; - - -export { api, AuthManager, initLoginForm, AdminPanel }; diff --git a/desktop/frontend-static/js/autocomplete.js b/desktop/frontend-static/js/autocomplete.js deleted file mode 100644 index 86492aa..0000000 --- a/desktop/frontend-static/js/autocomplete.js +++ /dev/null @@ -1,350 +0,0 @@ -/* ObsiGate — Autocomplete intelligent - * Partagé entre éditeur Forge (textarea) et CodeMirror. - * Détecte le contexte autour du curseur et suggère des complétions. - * - * Contexte supporté : mermaid, code fence, frontmatter, markdown, wikilink, table, texte libre. - * - * API : - * suggest(text, cursorPos) → { context, items: [{label, detail, insert, from, to}] } - * CompletionSource pour CodeMirror : codeMirrorCompletionSource(context) - */ - -// ── Suggestion Data ────────────────────────────────────────────────── -var MERMAID_TYPES = [ - { label: 'flowchart TD', detail: 'Diagramme de flux (top-down)', insert: 'flowchart TD\n ' }, - { label: 'flowchart LR', detail: 'Diagramme de flux (gauche-droite)', insert: 'flowchart LR\n ' }, - { label: 'sequenceDiagram', detail: 'Sequence (acteurs + messages)', insert: 'sequenceDiagram\n ' }, - { label: 'classDiagram', detail: 'Diagramme de classes UML', insert: 'classDiagram\n ' }, - { label: 'stateDiagram-v2', detail: 'Diagramme d\'etats', insert: 'stateDiagram-v2\n ' }, - { label: 'erDiagram', detail: 'Diagramme Entite-Relation', insert: 'erDiagram\n ' }, - { label: 'journey', detail: 'Parcours utilisateur', insert: 'journey\n ' }, - { label: 'gantt', detail: 'Diagramme de Gantt', insert: 'gantt\n ' }, - { label: 'pie', detail: 'Diagramme circulaire', insert: 'pie\n ' }, - { label: 'gitGraph', detail: 'Historique Git', insert: 'gitGraph\n ' }, - { label: 'mindmap', detail: 'Carte mentale', insert: 'mindmap\n ' }, - { label: 'timeline', detail: 'Ligne du temps', insert: 'timeline\n ' }, - { label: 'quadrantChart', detail: 'Graphique quadrants', insert: 'quadrantChart\n ' }, - { label: 'xychart-beta', detail: 'Graphique XY', insert: 'xychart-beta\n ' }, - { label: 'block-beta', detail: 'Diagramme de blocs', insert: 'block-beta\n ' } -]; - -var MERMAID_SYNTAX = { - 'flowchart': [ - { label: 'A-->B', detail: 'Fleche', insert: '-->' }, - { label: 'A--text-->B', detail: 'Fleche avec texte', insert: '-- texte -->' }, - { label: 'A-.->B', detail: 'Fleche pointillee', insert: '-.->' }, - { label: 'A==>B', detail: 'Fleche epaisse', insert: '==>' }, - { label: 'subgraph', detail: 'Sous-graphe', insert: 'subgraph titre\n \nend' }, - { label: 'style A fill:#xxx', detail: 'Style de noeud', insert: 'style A fill:#333,stroke:#58a6ff' }, - { label: 'classDef', detail: 'Classe CSS', insert: 'classDef default fill:#333,stroke:#58a6ff' } - ], - 'sequenceDiagram': [ - { label: 'participant X', detail: 'Declarer acteur', insert: 'participant Nom' }, - { label: 'A->>B: msg', detail: 'Message', insert: '->> : ' }, - { label: 'A-->>B: msg', detail: 'Message asynchrone', insert: '-->> : ' }, - { label: 'Note over A,B', detail: 'Note', insert: 'Note over A,B: ' }, - { label: 'loop text', detail: 'Boucle', insert: 'loop description\n \nend' }, - { label: 'alt/else', detail: 'Alternative', insert: 'alt condition\n \nelse\n \nend' }, - { label: 'activate A', detail: 'Activer ligne de vie', insert: 'activate A' } - ], - 'classDiagram': [ - { label: 'class Nom {', detail: 'Declarer classe', insert: 'class Nom {\n \n}' }, - { label: '+methode()', detail: 'Methode publique', insert: '+nom() Type' }, - { label: '-attribut', detail: 'Attribut prive', insert: '-nom Type' }, - { label: 'Heritage', detail: 'Relation heritage', insert: ' <|-- ' }, - { label: 'Composition', detail: 'Relation composition', insert: ' *-- ' } - ], - 'gantt': [ - { label: 'dateFormat', detail: 'Format de date', insert: 'dateFormat YYYY-MM-DD' }, - { label: 'section', detail: 'Section Gantt', insert: 'section Nom' }, - { label: 'tache : apres', detail: 'Tache avec dependance', insert: ' : after tache1, 3d' } - ], - 'pie': [ - { label: 'title', detail: 'Titre du pie', insert: 'title Titre du graphique' }, - { label: '"Label" : val', detail: 'Valeur', insert: '"Label" : 50' } - ], - 'mindmap': [ - { label: 'root', detail: 'Racine', insert: 'root((Sujet))' }, - { label: 'branche', detail: 'Sous-sujet', insert: '\n Sous-sujet' }, - { label: 'leaf', detail: 'Feuille', insert: '\n Detail' } - ] -}; - -var CODE_LANGUAGES = [ - { label: 'python', detail: 'Python', insert: 'python' }, - { label: 'javascript', detail: 'JavaScript', insert: 'javascript' }, - { label: 'typescript', detail: 'TypeScript', insert: 'typescript' }, - { label: 'bash', detail: 'Bash / Shell', insert: 'bash' }, - { label: 'sql', detail: 'SQL', insert: 'sql' }, - { label: 'json', detail: 'JSON', insert: 'json' }, - { label: 'yaml', detail: 'YAML', insert: 'yaml' }, - { label: 'html', detail: 'HTML', insert: 'html' }, - { label: 'css', detail: 'CSS', insert: 'css' }, - { label: 'dockerfile', detail: 'Dockerfile', insert: 'dockerfile' }, - { label: 'mermaid', detail: 'Mermaid (diagrammes)', insert: 'mermaid' }, - { label: 'markdown', detail: 'Markdown', insert: 'markdown' }, - { label: 'rust', detail: 'Rust', insert: 'rust' }, - { label: 'go', detail: 'Go', insert: 'go' }, - { label: 'java', detail: 'Java', insert: 'java' } -]; - -var CODE_SNIPPETS = { - python: [ - { label: 'def', detail: 'Fonction', insert: 'def nom(params):\n ' }, - { label: 'class', detail: 'Classe', insert: 'class Nom:\n def __init__(self):\n ' }, - { label: 'if/else', detail: 'Condition', insert: 'if condition:\n \nelse:\n ' }, - { label: 'for', detail: 'Boucle for', insert: 'for item in iterable:\n ' }, - { label: 'try/except', detail: 'Try-except', insert: 'try:\n \nexcept Exception as e:\n ' }, - { label: 'import', detail: 'Import', insert: 'import ' }, - { label: 'print', detail: 'Print', insert: 'print()' }, - { label: 'lambda', detail: 'Lambda', insert: 'lambda x: ' } - ], - javascript: [ - { label: 'function', detail: 'Fonction', insert: 'function nom(params) {\n \n}' }, - { label: 'const', detail: 'Constante', insert: 'const nom = ' }, - { label: '=>', detail: 'Fleche', insert: '(params) => {\n \n}' }, - { label: 'if/else', detail: 'Condition', insert: 'if (cond) {\n \n} else {\n \n}' }, - { label: 'for', detail: 'Boucle for', insert: 'for (let i = 0; i < n; i++) {\n \n}' }, - { label: 'try/catch', detail: 'Try-catch', insert: 'try {\n \n} catch (e) {\n \n}' }, - { label: 'console.log', detail: 'Console log', insert: 'console.log()' }, - { label: 'async/await', detail: 'Async function', insert: 'async function nom() {\n await \n}' } - ], - bash: [ - { label: '#!/bin/bash', detail: 'Shebang', insert: '#!/bin/bash' }, - { label: 'if/fi', detail: 'Condition', insert: 'if [ condition ]; then\n \nfi' }, - { label: 'for', detail: 'Boucle for', insert: 'for item in list; do\n \ndone' }, - { label: 'case/esac', detail: 'Case', insert: 'case var in\n pattern)\n ;;\nesac' }, - { label: 'function', detail: 'Fonction', insert: 'nom() {\n \n}' } - ], - sql: [ - { label: 'SELECT', detail: 'Select', insert: 'SELECT colonnes\nFROM table' }, - { label: 'JOIN', detail: 'Join', insert: 'JOIN table2 ON table1.id = table2.id' }, - { label: 'WHERE', detail: 'Where', insert: 'WHERE condition' }, - { label: 'GROUP BY', detail: 'Group by', insert: 'GROUP BY colonne' }, - { label: 'ORDER BY', detail: 'Order by', insert: 'ORDER BY colonne DESC' }, - { label: 'INSERT INTO', detail: 'Insert', insert: 'INSERT INTO table (cols) VALUES (vals)' }, - { label: 'CREATE TABLE', detail: 'Create table', insert: 'CREATE TABLE nom (\n id INTEGER PRIMARY KEY,\n \n)' } - ] -}; - -var FRONTMATTER_FIELDS = [ - { label: 'title:', detail: 'Titre du document', insert: 'title: ' }, - { label: 'tags:', detail: 'Tags (liste)', insert: 'tags:\n - ' }, - { label: 'date:', detail: 'Date', insert: 'date: ' + new Date().toISOString().slice(0,10) }, - { label: 'status:', detail: 'Statut', insert: 'status: en cours' }, - { label: 'category:', detail: 'Categorie', insert: 'category: ' }, - { label: 'publish:', detail: 'Publier (true/false)', insert: 'publish: true' }, - { label: 'favoris:', detail: 'Favoris (true/false)', insert: 'favoris: true' }, - { label: 'author:', detail: 'Auteur', insert: 'author: ' }, - { label: 'description:', detail: 'Description', insert: 'description: ' } -]; - -var MARKDOWN_FORMAT = [ - { label: '# H1', detail: 'Titre niveau 1', insert: '# ' }, - { label: '## H2', detail: 'Titre niveau 2', insert: '## ' }, - { label: '### H3', detail: 'Titre niveau 3', insert: '### ' }, - { label: '**gras**', detail: 'Texte en gras', insert: '****' }, - { label: '*italique*', detail: 'Texte en italique', insert: '**' }, - { label: '`code`', detail: 'Code inline', insert: '``' }, - { label: '[lien](url)', detail: 'Lien', insert: '[]()' }, - { label: '![image](url)', detail: 'Image', insert: '![]()' }, - { label: '- liste', detail: 'Liste a puces', insert: '- ' }, - { label: '1. liste', detail: 'Liste numerotee', insert: '1. ' }, - { label: '> citation', detail: 'Citation', insert: '> ' }, - { label: '---', detail: 'Separateur horizontal', insert: '\n---\n' }, - { label: '> [!note]', detail: 'Callout Note', insert: '> [!note] Titre\n> Contenu' }, - { label: '> [!warning]', detail: 'Callout Warning', insert: '> [!warning] Titre\n> Contenu' }, - { label: '> [!tip]', detail: 'Callout Tip', insert: '> [!tip] Titre\n> Contenu' }, - { label: '> [!danger]', detail: 'Callout Danger', insert: '> [!danger] Titre\n> Contenu' } -]; - -// ── Context Detection ───────────────────────────────────────────────── -function detectContext(text, cursorPos) { - var before = text.slice(0, cursorPos); - var after = text.slice(cursorPos); - var lines = before.split('\n'); - var currentLine = lines[lines.length - 1] || ''; - var lineNum = lines.length; - - // Check for code fence context (look backwards for unclosed ```) - var inFence = null; - var fenceLang = ''; - var fenceStart = 0; - for (var i = lines.length - 1; i >= 0; i--) { - var l = lines[i].trim(); - var m = l.match(/^```(\w*)/); - if (m) { - if (inFence === null) { - inFence = true; - fenceLang = m[1] || ''; - fenceStart = i + 1; - } else { - inFence = false; - break; - } - } - } - - if (inFence) { - if (fenceLang === 'mermaid') return { type: 'mermaid', lang: '', line: currentLine }; - return { type: 'code', lang: fenceLang, line: currentLine }; - } - - // Check for frontmatter context (between first and second ---) - if (lineNum >= 2) { - var firstSep = -1, secondSep = -1; - for (var j = 0; j < lines.length; j++) { - if (lines[j].trim() === '---') { - if (firstSep === -1) firstSep = j; - else if (secondSep === -1) { secondSep = j; break; } - } - } - if (firstSep === 0 && secondSep === -1) { - return { type: 'frontmatter', line: currentLine }; - } - } - - // Check for wikilink - if (/\[\[$/.test(currentLine) || /\[\[[^\]]*$/.test(currentLine)) { - var partial = (currentLine.match(/\[\[([^\]]*)$/) || ['',''])[1]; - return { type: 'wikilink', partial: partial, line: currentLine }; - } - - // Check for markdown link - if (/\[.*\]\($/.test(currentLine)) { - return { type: 'link', line: currentLine }; - } - - // Check for triple backtick (about to open fence) - if (/```$/.test(before) || /^```\s*$/.test(currentLine)) { - return { type: 'fence_open', line: currentLine }; - } - - // Check if inside a markdown table - if (/^\|.*\|$/.test(currentLine.trim())) { - return { type: 'table', line: currentLine }; - } - - // Plain text / markdown - return { type: 'markdown', line: currentLine }; -} - -// ── Suggestion Engine ───────────────────────────────────────────────── -function suggest(text, cursorPos) { - var ctx = detectContext(text, cursorPos); - var items = []; - var prefix = ''; - - var currentLine = ctx.line; - - switch (ctx.type) { - case 'mermaid': - // Try to match mermaid type already declared - var mermaidMatch = text.match(/```mermaid\s*\n(\w+)/); - if (mermaidMatch) { - var mmType = mermaidMatch[1]; - items = MERMAID_SYNTAX[mmType] || []; - } - if (items.length === 0) { - items = MERMAID_TYPES; - } - break; - - case 'code': - items = CODE_SNIPPETS[ctx.lang] || []; - break; - - case 'fence_open': - items = CODE_LANGUAGES; - break; - - case 'frontmatter': - prefix = currentLine.trim(); - items = FRONTMATTER_FIELDS.filter(function(f) { - return f.label.startsWith(prefix) || prefix === ''; - }).map(function(f) { - return { label: f.label, detail: f.detail, insert: prefix ? f.insert : f.insert }; - }); - return { - context: ctx.type, - items: items.length > 0 ? items : FRONTMATTER_FIELDS.map(function(f) { - return { label: f.label, detail: f.detail, insert: f.insert }; - }) - }; - - case 'wikilink': - return { - context: 'wikilink', - items: [], - partial: ctx.partial, - async: true // requires file index lookup - }; - - case 'markdown': - default: - // At start of line: markdown formatting - if (currentLine.trim().length < 3) { - items = MARKDOWN_FORMAT; - } else { - items = []; - } - break; - } - - var filtered = items.filter(function(item) { - return !prefix || item.label.toLowerCase().indexOf(prefix.toLowerCase()) !== -1; - }); - - return { - context: ctx.type, - items: filtered.length > 0 ? filtered : items - }; -} - -// ── Wikilink async completion (fetches file list from server) ───────── -var _fileCache = null; -var _fileCacheTime = 0; - -function searchWikilinks(partial, callback) { - var now = Date.now(); - // Use cached file list if fresh (< 30s) - if (_fileCache && (now - _fileCacheTime) < 30000) { - callback(filterFiles(partial)); - return; - } - - try { - fetch('/api/search/advanced?q=**&vault=all&limit=500') - .then(function(r) { return r.json(); }) - .then(function(data) { - _fileCache = (data.results || []).map(function(r) { - return { - path: r.path, - title: r.title || r.path.replace(/\.md$/i, ''), - vault: r.vault, - name: r.path.split('/').pop().replace(/\.md$/i, '') - }; - }); - _fileCacheTime = now; - callback(filterFiles(partial)); - }) - .catch(function() { callback([]); }); - } catch(e) { callback([]); } -} - -function filterFiles(partial) { - if (!_fileCache) return []; - var q = (partial || '').toLowerCase(); - return _fileCache.filter(function(f) { - return f.name.toLowerCase().indexOf(q) !== -1 || f.path.toLowerCase().indexOf(q) !== -1; - }).slice(0, 20).map(function(f) { - return { - label: f.name, - detail: f.path, - insert: f.path + ']]', - vault: f.vault - }; - }); -} - -export { suggest, searchWikilinks, detectContext, MERMAID_TYPES, CODE_LANGUAGES, FRONTMATTER_FIELDS, MARKDOWN_FORMAT }; diff --git a/desktop/frontend-static/js/backup-manager.js b/desktop/frontend-static/js/backup-manager.js deleted file mode 100644 index d546cc1..0000000 --- a/desktop/frontend-static/js/backup-manager.js +++ /dev/null @@ -1,324 +0,0 @@ -/** - * Backup Manager module for ObsiGate. - * - * Full-page view to browse, preview, restore, and delete backups across vaults. - * Accessible from the backup/diff viewer footer. - */ -import { api } from './auth.js'; -import { showToast } from './ui.js'; -import { safeCreateIcons } from './utils.js'; - -var state = { backups: [], filter: '', preview: null }; - -export function openBackupManager() { - var area = document.getElementById('content-area'); - if (!area) return; - area.innerHTML = ''; - - var container = document.createElement('div'); - container.className = 'backup-manager'; - container.id = 'backup-manager'; - - container.innerHTML = - '
    ' + - '

    Gestion des backups

    ' + - '
    ' + - '' + - '' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '' + - '
    '; - - area.appendChild(container); - safeCreateIcons(); - - document.getElementById('bm-filter').addEventListener('input', function() { - state.filter = this.value.toLowerCase(); - render(); - }); - document.getElementById('bm-refresh').addEventListener('click', load); - document.getElementById('bm-preview-close').addEventListener('click', function() { - document.getElementById('bm-preview').style.display = 'none'; - }); - - state.preview = null; - load(); -} - -async function load() { - var list = document.getElementById('bm-list'); - list.innerHTML = '
    '; - - try { - var data = await api('/api/backups'); - state.backups = data.backups || []; - updateStats(data); - render(); - } catch (err) { - list.innerHTML = '
    Erreur: ' + escapeHtml(err.message || 'Inconnue') + '
    '; - } -} - -function updateStats(data) { - var stats = document.getElementById('bm-stats'); - if (!stats) return; - var totalSize = formatSize(data.total_size_bytes || 0); - stats.innerHTML = - '' + data.total + ' backups' + - '' + totalSize + ' total'; -} - -function render() { - var list = document.getElementById('bm-list'); - if (!list) return; - - var filtered = state.backups; - if (state.filter) { - filtered = state.backups.filter(function(b) { - return b.file.toLowerCase().indexOf(state.filter) !== -1 || b.vault.toLowerCase().indexOf(state.filter) !== -1; - }); - } - - if (filtered.length === 0) { - list.innerHTML = '
    Aucun backup trouve.
    '; - return; - } - - var grouped = {}; - filtered.forEach(function(b) { - if (!grouped[b.vault]) grouped[b.vault] = []; - grouped[b.vault].push(b); - }); - - var html = ''; - var vaultNames = Object.keys(grouped).sort(); - vaultNames.forEach(function(vault) { - var vaultBackups = grouped[vault]; - var vaultSize = vaultBackups.reduce(function(s, b) { return s + b.size; }, 0); - - html += '
    '; - html += '
    '; - html += '

    ' + escapeHtml(vault) + '

    '; - html += '' + vaultBackups.length + ' backups · ' + formatSize(vaultSize) + ''; - html += ''; - html += '
    '; - - var byFile = {}; - vaultBackups.forEach(function(b) { - if (!byFile[b.file]) byFile[b.file] = []; - byFile[b.file].push(b); - }); - - var fileNames = Object.keys(byFile).sort(); - fileNames.forEach(function(file) { - var backups = byFile[file]; - backups.sort(function(a, b) { return b.timestamp - a.timestamp; }); - var totalFileSize = backups.reduce(function(s, b) { return s + b.size; }, 0); - - html += '
    '; - html += '
    '; - html += ' ' + escapeHtml(file) + ''; - html += '' + backups.length + ' versions · ' + formatSize(totalFileSize) + ''; - html += ''; - html += '
    '; - - html += '
    '; - backups.forEach(function(b) { - var d = new Date(b.timestamp * 1000); - var ds = d.getFullYear() + '-' + pad(d.getMonth()+1) + '-' + pad(d.getDate()) + ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes()); - html += '
    '; - html += '' + ds + ''; - html += '' + formatSize(b.size) + ''; - html += '
    '; - html += ''; - html += ''; - html += ''; - html += '
    '; - html += '
    '; - }); - html += '
    '; - html += '
    '; - }); - - html += '
    '; - }); - - list.innerHTML = html; - safeCreateIcons(); - - // Bind vault purge - list.querySelectorAll('.bm-vault-purge').forEach(function(btn) { - btn.addEventListener('click', function(e) { - e.stopPropagation(); - if (confirm('Supprimer TOUS les backups du vault "' + btn.dataset.vault + '" ?')) { - purgeVault(btn.dataset.vault); - } - }); - }); - - // Bind file purge - list.querySelectorAll('.bm-file-purge').forEach(function(btn) { - btn.addEventListener('click', function(e) { - e.stopPropagation(); - if (confirm('Supprimer TOUS les backups de "' + btn.dataset.file + '" ?')) { - purgeFile(btn.dataset.vault, btn.dataset.file); - } - }); - }); - - // Bind backup item clicks (preview) and action buttons - list.querySelectorAll('.bm-backup-item').forEach(function(item) { - item.addEventListener('click', function(e) { - // Don't trigger preview if clicking an action button - if (e.target.closest('button')) return; - state.preview = item.dataset.path; - render(); - previewBackup(item.dataset.path); - }); - }); - - // Bind action buttons - list.querySelectorAll('.bm-backup-preview').forEach(function(btn) { - btn.addEventListener('click', function(e) { - e.stopPropagation(); - var item = btn.closest('.bm-backup-item'); - state.preview = item.dataset.path; - render(); - previewBackup(item.dataset.path); - }); - }); - - list.querySelectorAll('.bm-backup-restore').forEach(function(btn) { - btn.addEventListener('click', function(e) { - e.stopPropagation(); - var item = btn.closest('.bm-backup-item'); - restoreBackup(item.dataset.vault, item.dataset.file); - }); - }); - - list.querySelectorAll('.bm-backup-delete').forEach(function(btn) { - btn.addEventListener('click', function(e) { - e.stopPropagation(); - if (confirm('Supprimer ce backup ?')) { - deleteBackups([btn.dataset.path]); - } - }); - }); -} - -async function previewBackup(fpath) { - var panel = document.getElementById('bm-preview'); - var content = document.getElementById('bm-preview-content'); - var title = document.getElementById('bm-preview-title'); - panel.style.display = 'block'; - content.textContent = t("common.loading"); - - try { - var data = await api('/api/backups/content?path=' + encodeURIComponent(fpath)); - content.textContent = data.content || '(fichier vide)'; - title.textContent = 'Apercu - ' + (data.name || ''); - } catch (err) { - content.textContent = 'Erreur: ' + (err.message || 'Inconnue'); - } -} - -async function restoreBackup(vault, file) { - // Find the backup timestamp from the currently selected backup - var item = document.querySelector('.bm-backup-item.active'); - if (!item) { showToast(t('backup.select_to_restore'), 'error'); return; } - - var backupPath = item.dataset.path; - // Extract timestamp from the filename - var parts = backupPath.replace(/\\/g, '/').split('/').pop().split('.'); - // The timestamp is the second-to-last component before .bak - var ts = null; - for (var i = parts.length - 1; i >= 0; i--) { - if (parts[i] === 'bak' && i > 0 && /^\d+$/.test(parts[i-1])) { - ts = parseInt(parts[i-1]); - break; - } - } - if (!ts) { showToast(t('backup.timestamp_not_found'), 'error'); return; } - - if (!confirm('Restaurer "' + file + '" a la version du backup selectionne ?\nLa version actuelle sera sauvegardee.')) return; - - try { - var resp = await api('/api/file/' + encodeURIComponent(vault) + '/restore?path=' + encodeURIComponent(file), { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ version: ts }), - }); - if (resp && resp.success) { - showToast(t('backup.file_restored'), 'success'); - load(); - } - } catch (err) { - showToast('Erreur: ' + (err.message || 'Inconnue'), 'error'); - } -} - -async function deleteBackups(paths) { - try { - var resp = await api('/api/backups/delete', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ paths: paths }), - }); - showToast(resp.deleted + ' backup(s) supprime(s)', 'success'); - load(); - } catch (err) { - showToast('Erreur: ' + err.message, 'error'); - } -} - -async function purgeFile(vault, file) { - try { - var resp = await api('/api/backups/purge', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ vault: vault, file: file }), - }); - showToast(resp.deleted + ' backup(s) supprime(s)', 'success'); - load(); - } catch (err) { - showToast('Erreur: ' + err.message, 'error'); - } -} - -async function purgeVault(vault) { - try { - var resp = await api('/api/backups/purge', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ vault: vault }), - }); - showToast(resp.deleted + ' backup(s) supprime(s)', 'success'); - load(); - } catch (err) { - showToast('Erreur: ' + err.message, 'error'); - } -} - -function formatSize(bytes) { - if (bytes < 1024) return bytes + ' o'; - if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' Ko'; - return (bytes / (1024 * 1024)).toFixed(1) + ' Mo'; -} - -function pad(n) { return String(n).padStart(2, '0'); } - -function escapeHtml(str) { - var div = document.createElement('div'); - div.textContent = str; - return div.innerHTML; -} diff --git a/desktop/frontend-static/js/backups.js b/desktop/frontend-static/js/backups.js deleted file mode 100644 index 7ef01a9..0000000 --- a/desktop/frontend-static/js/backups.js +++ /dev/null @@ -1,501 +0,0 @@ -/** - * Backup & Diff viewer module for ObsiGate. - * - * Provides a modal UI to browse file backups, compare versions with - * a unified diff view, and restore previous versions. - * - * Usage: - * import { openBackupViewer } from './backups.js'; - * openBackupViewer(vaultName, filePath); - */ - -import { api } from './auth.js'; -import { showToast } from './ui.js'; -import { refreshSidebarTreePreservingState } from './sidebar.js'; -import { safeCreateIcons } from './utils.js'; - -// --------------------------------------------------------------------------- -// State -// --------------------------------------------------------------------------- - -const state = { - vault: null, - path: null, - backups: [], - overlay: null, - leftVersion: null, - rightVersion: null, - diffText: '', - diffLeft: '', - diffRight: '', - diffMode: 'unified', -}; - -// --------------------------------------------------------------------------- -// Public API -// --------------------------------------------------------------------------- - -export async function openBackupViewer(vault, path) { - state.vault = vault; - state.path = path; - state.backups = []; - state.leftVersion = null; - state.rightVersion = null; - state.diffText = ''; - state.diffLeft = ''; - state.diffRight = ''; - - const overlay = createOverlay(); - document.body.appendChild(overlay); - state.overlay = overlay; - requestAnimationFrame(function() { overlay.classList.add('active'); }); - - setBody(renderLoading()); - - try { - var url = '/api/file/' + encodeURIComponent(vault) + '/backups?path=' + encodeURIComponent(path); - var data = await api(url); - state.backups = data.backups || []; - } catch (err) { - var msg = err && err.detail || err && err.message || 'Erreur inconnue'; - setBody(renderError('Erreur API: ' + msg)); - return; - } - - if (state.backups.length === 0) { - setBody(renderEmpty()); - return; - } - - state.leftVersion = state.backups[0].timestamp; - state.rightVersion = null; - renderMainView(); - await loadDiff(); -} - -// --------------------------------------------------------------------------- -// DOM helpers -// --------------------------------------------------------------------------- - -var _escHandler = null; - -function createOverlay() { - var overlay = document.createElement('div'); - overlay.className = 'obsigate-modal-overlay backup-viewer-overlay'; - overlay.addEventListener('click', function(e) { - if (e.target === overlay) close(); - }); - - var panel = document.createElement('div'); - panel.className = 'backup-viewer-panel'; - panel.id = 'backup-viewer-panel'; - overlay.appendChild(panel); - - // Close button -- static, never replaced by innerHTML - var closeBtn = document.createElement('button'); - closeBtn.className = 'editor-btn backup-close-btn'; - closeBtn.id = 'backup-close'; - closeBtn.title = 'Fermer'; - closeBtn.style.cssText = 'position:absolute;top:12px;right:12px;z-index:1002;flex-shrink:0'; - closeBtn.innerHTML = ''; - closeBtn.addEventListener('click', function(e) { - e.stopPropagation(); - close(); - }); - overlay.appendChild(closeBtn); - - // Escape key - _escHandler = function(e) { - if (e.key === 'Escape' && state.overlay) close(); - }; - document.addEventListener('keydown', _escHandler); - - return overlay; -} - -function setBody(html) { - var panel = document.getElementById('backup-viewer-panel'); - if (panel) panel.innerHTML = html; -} - -function close() { - if (!state.overlay) return; - if (_escHandler) { - document.removeEventListener('keydown', _escHandler); - _escHandler = null; - } - state.overlay.classList.remove('active'); - setTimeout(function() { - if (state.overlay) state.overlay.remove(); - state.overlay = null; - }, 200); -} - -// Global click handler for close button -document.addEventListener('click', function(e) { - var btn = e.target.closest ? e.target.closest('#backup-close') : null; - if (btn && state.overlay) close(); -}); - -// --------------------------------------------------------------------------- -// Rendering -// --------------------------------------------------------------------------- - -function renderLoading() { - return '

    Backups

    ' + - '
    ' + - '
    ' + - '
    ' + - '

    Chargement des backups...

    ' + - '
    '; -} - -function renderError(msg) { - return '

    Backups

    ' + - '
    ' + - '

    ' + escapeHtml(msg) + '

    '; -} - -function renderEmpty() { - return '

    Backups - ' + escapeHtml(state.path) + '

    ' + - '
    ' + - '

    Aucun backup disponible pour ce fichier.

    ' + - '

    Les backups sont crees automatiquement avant chaque modification.

    ' + - '
    '; -} - -function renderMainView() { - var b = state.backups; - var leftOpts = b.map(function(bk) { - var sel = bk.timestamp === state.leftVersion ? ' selected' : ''; - return ''; - }).join(''); - - var rightOpts = [''] - .concat(b.map(function(bk) { - var sel = bk.timestamp === state.rightVersion ? ' selected' : ''; - return ''; - })).join(''); - - var html = - '
    ' + - '
    ' + - '

    '+t('backups.title')+'

    ' + - '' + escapeHtml(state.path) + '' + - '
    ' + - '
    ' + - '' + b.length + ' backup' + (b.length > 1 ? 's' : '') + '' + - '
    ' + - '
    ' + - - '
    ' + - '
    ' + - '' + - '' + - '
    ' + - 'vs' + - '
    ' + - '' + - '
    ' + - '' + - '' + - '
    ' + - - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - - ''; - - setBody(html); - bindEvents(); -} - -// --------------------------------------------------------------------------- -// Event bindings -// --------------------------------------------------------------------------- - -function bindEvents() { - var leftSelect = document.getElementById('backup-left-select'); - if (leftSelect) { - leftSelect.addEventListener('change', async function() { - state.leftVersion = parseInt(leftSelect.value); - await loadDiff(); - }); - } - - var rightSelect = document.getElementById('backup-right-select'); - if (rightSelect) { - rightSelect.addEventListener('change', async function() { - var val = rightSelect.value; - state.rightVersion = val === 'current' ? null : parseInt(val); - await loadDiff(); - }); - } - - var restoreBtn = document.getElementById('backup-restore-btn'); - if (restoreBtn) { - restoreBtn.addEventListener('click', async function() { - await restoreBackup(); - }); - } - - var modeBtn = document.getElementById('backup-diff-mode-btn'); - var manageBtn = document.getElementById('backup-manage-btn'); - if (manageBtn) { - manageBtn.addEventListener('click', function() { - close(); - import('./backup-manager.js').then(function(m) { m.openBackupManager(); }); - }); - } - - if (modeBtn) { - modeBtn.addEventListener('click', function() { - state.diffMode = state.diffMode === 'sidebyside' ? 'unified' : 'sidebyside'; - var container = document.getElementById('backup-diff-container'); - if (container) { - container.innerHTML = state.diffMode === 'sidebyside' - ? renderDiffSideBySide(state.diffLeft, state.diffRight) - : renderDiff(state.diffText); - } - var icon = modeBtn.querySelector('i'); - if (icon) icon.setAttribute('data-lucide', state.diffMode === 'sidebyside' ? 'columns-2' : 'align-justify'); - var textNodes = []; - for (var i = 0; i < modeBtn.childNodes.length; i++) { - if (modeBtn.childNodes[i].nodeType === 3) textNodes.push(modeBtn.childNodes[i]); - } - textNodes.forEach(function(n) { n.remove(); }); - modeBtn.appendChild(document.createTextNode(state.diffMode === 'sidebyside' ? ' Unifiee' : ' Cote-a-cote')); - safeCreateIcons(); - }); - } -} - -// --------------------------------------------------------------------------- -// Data loading -// --------------------------------------------------------------------------- - -async function loadDiff() { - var container = document.getElementById('backup-diff-container'); - if (!container) return; - - container.innerHTML = - '
    ' + - '
    ' + - '
    '; - - var url = '/api/file/' + encodeURIComponent(state.vault) + '/diff?path=' + encodeURIComponent(state.path) + '&version=' + state.leftVersion; - if (state.rightVersion !== null) { - url += '&compare_with=' + state.rightVersion; - } - - try { - var data = await api(url); - state.diffText = data.diff || ''; - state.diffLeft = data.left_content || ''; - state.diffRight = data.right_content || ''; - container.innerHTML = state.diffMode === 'sidebyside' - ? renderDiffSideBySide(state.diffLeft, state.diffRight) - : renderDiff(state.diffText); - } catch (err) { - container.innerHTML = '
    Erreur: ' + escapeHtml((err && err.detail) || (err && err.message) || 'Unknown') + '
    '; - } -} - -async function restoreBackup() { - if (!state.leftVersion) return; - - var confirmed = confirm( - 'Restaurer "' + state.path + '" a la version du ' + formatTimestamp(state.leftVersion) + ' ?\n\n' + - 'La version actuelle sera sauvegardee avant la restauration.' - ); - if (!confirmed) return; - - var restoreBtn = document.getElementById('backup-restore-btn'); - if (restoreBtn) { - restoreBtn.disabled = true; - restoreBtn.textContent = 'Restauration...'; - } - - try { - var resp = await api( - '/api/file/' + encodeURIComponent(state.vault) + '/restore?path=' + encodeURIComponent(state.path), - { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ version: state.leftVersion }), - } - ); - - if (resp && resp.success) { - showToast(t('backup.file_restored'), 'success'); - await refreshSidebarTreePreservingState(); - close(); - if (typeof TabManager !== 'undefined' && TabManager.reloadCurrent) { - TabManager.reloadCurrent(); - } - } else { - showToast(t('backup.restore_failed'), 'error'); - } - } catch (err) { - showToast('Erreur: ' + ((err && err.detail) || (err && err.message) || 'Unknown'), 'error'); - } finally { - if (restoreBtn) { - restoreBtn.disabled = false; - restoreBtn.innerHTML = ' Restaurer'; - safeCreateIcons(); - } - } -} - -// --------------------------------------------------------------------------- -// Diff rendering -// --------------------------------------------------------------------------- - -function renderDiff(diffText) { - if (!diffText) { - return '
    Aucune difference - les versions sont identiques.
    '; - } - - var html = '
    '; - var lines = diffText.split('\n'); - - for (var i = 0; i < lines.length; i++) { - var line = lines[i]; - var cssClass = 'diff-context'; - var prefix = ' '; - if (line.indexOf('@@') === 0) { cssClass = 'diff-hunk'; prefix = ''; } - else if (line.indexOf('+') === 0) { cssClass = 'diff-add'; prefix = '+'; } - else if (line.indexOf('-') === 0) { cssClass = 'diff-del'; prefix = '-'; } - else if (line.indexOf('---') === 0 || line.indexOf('+++') === 0) { cssClass = 'diff-header-line'; prefix = ''; } - - html += ''; - } - - html += '
    ' + prefix + '
    ' + escapeHtml(line) + '
    '; - return html; -} - -// --------------------------------------------------------------------------- -// Side-by-side diff rendering -// --------------------------------------------------------------------------- - -function renderDiffSideBySide(leftText, rightText) { - if (!leftText && !rightText) { - return '
    Aucune difference - les versions sont identiques.
    '; - } - - var leftLines = (leftText || '').split('\n'); - var rightLines = (rightText || '').split('\n'); - var sm = new DifflibSeqMatcher(leftLines, rightLines); - var ops = sm.getOpcodes(); - - var html = '
    '; - - for (var oi = 0; oi < ops.length; oi++) { - var op = ops[oi]; - var tag = op[0], i1 = op[1], i2 = op[2], j1 = op[3], j2 = op[4]; - - if (tag === 'equal') { - for (var k = 0; k < (i2 - i1); k++) { - html += ''; - } - } else if (tag === 'delete') { - for (var k2 = i1; k2 < i2; k2++) { - html += ''; - } - } else if (tag === 'insert') { - for (var k3 = j1; k3 < j2; k3++) { - html += ''; - } - } else if (tag === 'replace') { - var maxLen = Math.max(i2 - i1, j2 - j1); - for (var k4 = 0; k4 < maxLen; k4++) { - var leftLine = (i1 + k4 < i2) ? escapeHtml(leftLines[i1 + k4]) : ''; - var rightLine = (j1 + k4 < j2) ? escapeHtml(rightLines[j1 + k4]) : ''; - var leftClass = (i1 + k4 < i2) ? 'diff-del' : 'diff-empty-cell'; - var rightClass = (j1 + k4 < j2) ? 'diff-add' : 'diff-empty-cell'; - html += ''; - } - } - } - - html += '
    ' + escapeHtml(leftLines[i1 + k]) + '
    ' + escapeHtml(rightLines[j1 + k]) + '
    ' + escapeHtml(leftLines[k2]) + '
    ' + escapeHtml(rightLines[k3]) + '
    ' + leftLine + '
    ' + rightLine + '
    '; - return html; -} - -// Minimal SequenceMatcher for line-based diff -function DifflibSeqMatcher(a, b) { - this.a = a; - this.b = b; -} - -DifflibSeqMatcher.prototype.getOpcodes = function() { - var m = this.a.length, n = this.b.length; - var dp = []; - for (var i = 0; i <= m; i++) { dp[i] = []; for (var j = 0; j <= n; j++) dp[i][j] = 0; } - for (var i = 1; i <= m; i++) { - for (var j = 1; j <= n; j++) { - if (this.a[i - 1] === this.b[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1; - else dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); - } - } - var ops = []; - var i = m, j = n; - while (i > 0 || j > 0) { - if (i > 0 && j > 0 && this.a[i - 1] === this.b[j - 1]) { - var ei = i - 1, ej = j - 1; - while (ei > 0 && ej > 0 && this.a[ei - 1] === this.b[ej - 1]) { ei--; ej--; } - if (ei < i) ops.unshift(['equal', ei, i, ej, j]); - i = ei; j = ej; - } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) { - ops.unshift(['insert', i, i, j - 1, j]); - j--; - } else if (i > 0 && (j === 0 || dp[i][j - 1] < dp[i - 1][j])) { - ops.unshift(['delete', i - 1, i, j, j]); - i--; - } - } - var merged = []; - for (var k = 0; k < ops.length; k++) { - if (merged.length > 0 && merged[merged.length - 1][0] === 'delete' && ops[k][0] === 'insert' && - merged[merged.length - 1][4] === ops[k][3]) { - var del = merged.pop(); - merged.push(['replace', del[1], del[2], ops[k][3], ops[k][4]]); - } else { - merged.push(ops[k]); - } - } - return merged; -}; - -// --------------------------------------------------------------------------- -// Utility -// --------------------------------------------------------------------------- - -function formatTimestamp(ts) { - var d = new Date(ts * 1000); - var pad = function(n) { return String(n).padStart(2, '0'); }; - return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes()); -} - -function formatSize(bytes) { - if (bytes < 1024) return bytes + ' o'; - if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' Ko'; - return (bytes / (1024 * 1024)).toFixed(1) + ' Mo'; -} - -function escapeHtml(str) { - var div = document.createElement('div'); - div.textContent = str; - return div.innerHTML; -} diff --git a/desktop/frontend-static/js/config.js b/desktop/frontend-static/js/config.js deleted file mode 100644 index c06a0f4..0000000 --- a/desktop/frontend-static/js/config.js +++ /dev/null @@ -1,1570 +0,0 @@ -// config.js — extracted from app.js (3872-4865) -import { api, AuthManager } from './auth.js'; -import { state } from './state.js'; -import { el, icon, openFile } from './viewer.js'; -import { syncVaultSelectors, setSelectedVaultContext, refreshSidebarForContext, loadVaults, loadVaultSettings, loadTags, TagFilterService, refreshSidebarTreePreservingState } from './sidebar.js'; -import { escapeHtml, safeCreateIcons } from './utils.js'; -import { showToast, closeHeaderMenu, closeMobileSidebar } from './ui.js'; -import { t, setLocale, getLocale } from './i18n.js'; - -let _recentTimestampTimer = null; -let _recentFilesCache = []; -let _recentRefreshTimer = null; - -export async function loadRecentFiles(vaultFilter) { - const listEl = document.getElementById("recent-list"); - const emptyEl = document.getElementById("recent-empty"); - if (!listEl) return; - - let url = "/api/recent?mode=modified"; - if (vaultFilter) url += `&vault=${encodeURIComponent(vaultFilter)}`; - try { - const data = await api(url); - _recentFilesCache = data.files || []; - renderRecentList(_recentFilesCache); - } catch (err) { - console.error("Failed to load recent files:", err); - listEl.innerHTML = ""; - if (emptyEl) { - emptyEl.classList.remove("hidden"); - } - } -} - -function renderRecentList(files) { - const listEl = document.getElementById("recent-list"); - const emptyEl = document.getElementById("recent-empty"); - if (!listEl) return; - listEl.innerHTML = ""; - - if (!files || files.length === 0) { - if (emptyEl) { - emptyEl.classList.remove("hidden"); - safeCreateIcons(); - } - return; - } - if (emptyEl) emptyEl.classList.add("hidden"); - - files.forEach((f) => { - const item = el("div", { class: "recent-item", "data-vault": f.vault, "data-path": f.path }); - - // Header row: time + vault badge - const header = el("div", { class: "recent-item-header" }); - const timeSpan = el("span", { class: "recent-time" }, [icon("clock", 11), document.createTextNode(f.mtime_human)]); - const badge = el("span", { class: "recent-vault-badge" }, [document.createTextNode(f.vault)]); - header.appendChild(timeSpan); - header.appendChild(badge); - item.appendChild(header); - - // Title - const titleEl = el("div", { class: "recent-item-title" }, [document.createTextNode(f.title || f.path.split("/").pop())]); - item.appendChild(titleEl); - - // Path breadcrumb - const pathParts = f.path.split("/"); - if (pathParts.length > 1) { - const pathEl = el("div", { class: "recent-item-path" }, [document.createTextNode(pathParts.slice(0, -1).join(" / "))]); - item.appendChild(pathEl); - } - - // Preview - if (f.preview) { - const previewEl = el("div", { class: "recent-item-preview" }, [document.createTextNode(f.preview)]); - item.appendChild(previewEl); - } - - // Tags - if (f.tags && f.tags.length > 0) { - const tagsEl = el("div", { class: "recent-item-tags" }); - f.tags.forEach((t) => { - tagsEl.appendChild(el("span", { class: "tag-pill" }, [document.createTextNode(t)])); - }); - item.appendChild(tagsEl); - } - - // Click handler - item.addEventListener("click", () => { - openFile(f.vault, f.path); - closeMobileSidebar(); - }); - - listEl.appendChild(item); - }); - safeCreateIcons(); -} - -function _humanizeDelta(mtime) { - const delta = Date.now() / 1000 - mtime; - if (delta < 60) return t("config.just_now"); - if (delta < 3600) return `il y a ${Math.floor(delta / 60)} min`; - if (delta < 86400) return `il y a ${Math.floor(delta / 3600)} h`; - if (delta < 604800) return `il y a ${Math.floor(delta / 86400)} j`; - return new Date(mtime * 1000).toLocaleDateString("fr-FR", { day: "numeric", month: "short", year: "numeric" }); -} - -function _refreshRecentTimestamps() { - if (state.activeSidebarTab !== "recent" || !_recentFilesCache.length) return; - const items = document.querySelectorAll(".recent-item"); - items.forEach((item, i) => { - if (i < _recentFilesCache.length) { - const timeSpan = item.querySelector(".recent-time"); - if (timeSpan) { - // keep the icon, update text - const textNode = timeSpan.lastChild; - if (textNode && textNode.nodeType === Node.TEXT_NODE) { - textNode.textContent = _humanizeDelta(_recentFilesCache[i].mtime); - } - } - } - }); -} - -export function _populateRecentVaultFilter() { - const select = document.getElementById("recent-vault-filter"); - if (!select) return; - // keep first option "Tous les vaults" - while (select.options.length > 1) select.remove(1); - state.allVaults.forEach((v) => { - const opt = document.createElement("option"); - opt.value = v.name; - opt.textContent = v.name; - select.appendChild(opt); - }); - syncVaultSelectors(); -} - -function initRecentTab() { - const select = document.getElementById("recent-vault-filter"); - if (select) { - select.addEventListener("change", async () => { - const val = select.value || "all"; - await setSelectedVaultContext(val, { focusVault: val !== "all" }); - }); - } - // Periodic timestamp refresh (every 60s) - _recentTimestampTimer = setInterval(_refreshRecentTimestamps, 60000); -} - -// --------------------------------------------------------------------------- -// Sidebar tabs -// --------------------------------------------------------------------------- -function initSidebarTabs() { - document.querySelectorAll(".sidebar-tab").forEach((tab) => { - tab.addEventListener("click", () => switchSidebarTab(tab.dataset.tab)); - }); -} - -function switchSidebarTab(tab) { - state.activeSidebarTab = tab; - document.querySelectorAll(".sidebar-tab").forEach((btn) => { - const isActive = btn.dataset.tab === tab; - btn.classList.toggle("active", isActive); - btn.setAttribute("aria-selected", isActive ? "true" : "false"); - }); - document.querySelectorAll(".sidebar-tab-panel").forEach((panel) => { - const isActive = panel.id === `sidebar-panel-${tab}`; - panel.classList.toggle("active", isActive); - }); - const filterInput = document.getElementById("sidebar-filter-input"); - if (filterInput) { - const placeholders = { vaults: "Filtrer fichiers...", tags: "Filtrer tags...", recent: "" }; - filterInput.placeholder = placeholders[tab] || ""; - } - const query = filterInput ? (state.sidebarFilterCaseSensitive ? filterInput.value.trim() : filterInput.value.trim().toLowerCase()) : ""; - if (query) { - if (tab === "vaults") performTreeSearch(query); - else if (tab === "tags") filterTagCloud(query); - } - // Auto-load recent files when switching to the recent tab - if (tab === "recent") { - _populateRecentVaultFilter(); - const vaultFilter = document.getElementById("recent-vault-filter"); - loadRecentFiles(vaultFilter ? vaultFilter.value || null : null); - } -} - -function initHelpModal() { - const openBtn = document.getElementById("help-open-btn"); - const closeBtn = document.getElementById("help-close"); - const modal = document.getElementById("help-modal"); - if (!openBtn || !closeBtn || !modal) return; - - let helpNavInitialized = false; - - openBtn.addEventListener("click", () => { - modal.classList.add("active"); - closeHeaderMenu(); - safeCreateIcons(); - // Reset TOC to CSS default (mobile: hidden, desktop: visible) - const nav = document.getElementById("help-nav"); - if (nav) nav.style.display = ''; - if (!helpNavInitialized) { - initHelpNavigation(); - helpNavInitialized = true; - } - }); - - closeBtn.addEventListener("click", closeHelpModal); - modal.addEventListener("click", (e) => { - if (e.target === modal) { - closeHelpModal(); - } - }); - - document.addEventListener("keydown", (e) => { - if (e.key === "Escape" && modal.classList.contains("active")) { - closeHelpModal(); - } - }); -} - -function initEditorPocBtn() { - var btn = document.getElementById("editor-poc-btn"); - if (!btn) return; - btn.addEventListener("click", function() { - window.open("/editor-poc", "_blank"); - }); -} - -function initHelpNavigation() { - const helpBody = document.getElementById("help-body"); - const navList = document.getElementById("help-nav-list"); - const nav = document.getElementById("help-nav"); - const searchInput = document.getElementById("help-nav-search"); - const helpContent = document.querySelector(".help-content"); - - if (!helpBody || !navList || !nav) return; - - const allLinks = [...navList.querySelectorAll(".help-nav-link")]; - const allSections = [...document.querySelectorAll(".help-section")]; - const sectionMap = {}; - allSections.forEach(s => { sectionMap[s.id] = s; }); - - // Build text index for content search - const sectionTextCache = {}; - allSections.forEach(s => { - sectionTextCache[s.id] = (s.textContent || '').toLowerCase(); - }); - - // ── Mobile: simple display toggle ── - function isMobile() { return window.innerWidth <= 768; } - function toggleTOC() { - if (nav.style.display === 'none' || nav.style.display === '') { - nav.style.display = 'flex'; - if (searchInput) setTimeout(() => searchInput.focus(), 150); - } else { - nav.style.display = 'none'; - } - } - - // ── Scroll to section ── - function scrollToSection(targetId) { - const section = sectionMap[targetId]; - if (!section) return; - section.scrollIntoView({ behavior: "smooth", block: "start" }); - section.setAttribute("tabindex", "-1"); - if (isMobile()) nav.style.display = 'none'; - } - - // ── Focus the content pane ── - function focusContent() { - const activeLink = navList.querySelector(".help-nav-link.active:not(.hidden)"); - if (activeLink) { - const targetId = activeLink.getAttribute("href").substring(1); - const section = sectionMap[targetId]; - if (section) { - const h2 = section.querySelector("h2, h3"); - if (h2) { h2.setAttribute("tabindex", "-1"); h2.focus({ preventScroll: true }); return; } - } - } - if (helpContent) { helpContent.setAttribute("tabindex", "-1"); helpContent.focus({ preventScroll: true }); } - } - - // ── Focus TOC active link ── - function focusTOC() { - if (isMobile() && (nav.style.display === 'none' || nav.style.display === '')) { - nav.style.display = 'flex'; - } - const activeLink = navList.querySelector(".help-nav-link.active:not(.hidden)"); - if (activeLink) { activeLink.focus(); return; } - const firstLink = navList.querySelector(".help-nav-link:not(.hidden)"); - if (firstLink) firstLink.focus(); - } - - // ── Nav link click handler ── - allLinks.forEach((link) => { - link.addEventListener("click", (e) => { - e.preventDefault(); - const targetId = link.getAttribute("href").substring(1); - scrollToSection(targetId); - }); - }); - - // ── Keyboard navigation inside nav list ── - navList.addEventListener("keydown", (e) => { - const items = [...navList.querySelectorAll(".help-nav-link:not(.hidden)")]; - if (!items.length) return; - const currentIdx = items.indexOf(document.activeElement); - - if (e.key === "ArrowDown") { - e.preventDefault(); - const next = (currentIdx + 1) % items.length; - items[next].focus(); - } else if (e.key === "ArrowUp") { - e.preventDefault(); - const prev = (currentIdx - 1 + items.length) % items.length; - items[prev].focus(); - } else if (e.key === "ArrowRight") { - e.preventDefault(); - focusContent(); - } else if (e.key === "ArrowLeft") { - e.preventDefault(); - const prev = (currentIdx - 1 + items.length) % items.length; - items[prev].focus(); - } else if (e.key === "Home") { - e.preventDefault(); - items[0].focus(); - } else if (e.key === "End") { - e.preventDefault(); - items[items.length - 1].focus(); - } else if (e.key === "Enter" && currentIdx >= 0) { - e.preventDefault(); - const targetId = items[currentIdx].getAttribute("href").substring(1); - scrollToSection(targetId); - setTimeout(() => focusContent(), 400); - } - }); - - navList.querySelectorAll("li").forEach((li) => li.setAttribute("role", "none")); - - // ── Keyboard navigation in content pane ── - if (helpContent) { - helpContent.setAttribute("tabindex", "-1"); - helpContent.addEventListener("keydown", (e) => { - if (e.key === "ArrowLeft") { - e.preventDefault(); - focusTOC(); - } else if (e.key === "ArrowUp" && document.activeElement === helpContent) { - e.preventDefault(); - focusTOC(); - } - }); - } - - // ── Keyboard navigation in search input ── - if (searchInput) { - searchInput.addEventListener("keydown", (e) => { - if (e.key === "ArrowDown") { - e.preventDefault(); - const firstLink = navList.querySelector(".help-nav-link:not(.hidden)"); - if (firstLink) firstLink.focus(); - } - }); - } - - // ── Search: filter TOC + hide non-matching sections + highlight text ── - let currentQuery = ""; - if (searchInput) { - searchInput.addEventListener("input", () => { - currentQuery = searchInput.value.toLowerCase().trim(); - applySearchFilter(); - }); - searchInput.addEventListener("keydown", (e) => { - if (e.key === "Escape" && currentQuery) { - searchInput.value = ""; - currentQuery = ""; - applySearchFilter(); - } - }); - } - - function clearHighlights() { - allSections.forEach(section => { - section.querySelectorAll(".help-search-highlight").forEach(el => { - const parent = el.parentNode; - parent.replaceChild(document.createTextNode(el.textContent), el); - parent.normalize(); - }); - }); - } - - function highlightText(root, query) { - if (!query || query.length < 2) return; - const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false); - const textNodes = []; - while (walker.nextNode()) { - const node = walker.currentNode; - // Skip nodes inside script, style, or already-highlighted - if (node.parentElement && !node.parentElement.closest("script, style, .help-search-highlight, .help-nav")) { - textNodes.push(node); - } - } - const regex = new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'); - textNodes.forEach(node => { - const text = node.textContent; - if (!regex.test(text)) return; - regex.lastIndex = 0; - const frag = document.createDocumentFragment(); - let lastIdx = 0; - let match; - while ((match = regex.exec(text)) !== null) { - if (match.index > lastIdx) { - frag.appendChild(document.createTextNode(text.slice(lastIdx, match.index))); - } - const mark = document.createElement("mark"); - mark.className = "help-search-highlight"; - mark.textContent = match[0]; - frag.appendChild(mark); - lastIdx = regex.lastIndex; - if (match[0].length === 0) regex.lastIndex++; - } - if (lastIdx < text.length) { - frag.appendChild(document.createTextNode(text.slice(lastIdx))); - } - node.parentNode.replaceChild(frag, node); - }); - } - - function applySearchFilter() { - const q = currentQuery; - // Clear previous highlights - clearHighlights(); - // Filter TOC links - allLinks.forEach((link) => { - const text = link.textContent.toLowerCase(); - if (!q || text.includes(q)) { - link.classList.remove("hidden"); - } else { - link.classList.add("hidden"); - } - }); - // Filter content sections + highlight - allSections.forEach((section) => { - if (!q) { - section.classList.remove("help-hidden"); - return; - } - const sectionText = sectionTextCache[section.id] || ''; - const sectionTitle = (section.querySelector("h2, h3")?.textContent || '').toLowerCase(); - if (sectionTitle.includes(q) || sectionText.includes(q)) { - section.classList.remove("help-hidden"); - // Highlight matching text in this section - highlightText(section, q); - } else { - section.classList.add("help-hidden"); - } - }); - updateActiveLink(); - ensureNoResultsMessage(q); - } - - function ensureNoResultsMessage(q) { - const existing = document.getElementById("help-no-results"); - const visibleSections = allSections.filter(s => !s.classList.contains("help-hidden")); - if (q && visibleSections.length === 0) { - if (!existing) { - const msg = document.createElement("div"); - msg.id = "help-no-results"; - msg.style.cssText = "padding:40px;text-align:center;color:var(--text-muted);font-size:0.9rem"; - msg.innerHTML = `
    🔍

    Aucun résultat pour "${q}"

    Essayez un autre terme

    `; - if (helpContent) helpContent.appendChild(msg); - } - } else if (existing) { - existing.remove(); - } - } - - // ── Scroll spy ── - function updateActiveLink() { - const visibleLinks = allLinks.filter(l => !l.classList.contains("hidden")); - const visibleSections = allSections.filter(s => !s.classList.contains("help-hidden")); - let activeId = null; - for (const section of visibleSections) { - const rect = section.getBoundingClientRect(); - const contentRect = helpContent ? helpContent.getBoundingClientRect() : null; - if (rect.top < (contentRect ? contentRect.top + 120 : 200)) { - activeId = section.id; - } - } - visibleLinks.forEach((link) => { - const isMatch = link.getAttribute("href") === `#${activeId}`; - link.classList.toggle("active", isMatch); - }); - } - - const observer = new IntersectionObserver( - (entries) => { - let bestEntry = null; - for (const entry of entries) { - if (entry.isIntersecting) { - if (!bestEntry || entry.boundingClientRect.top < bestEntry.boundingClientRect.top) { - bestEntry = entry; - } - } - } - if (bestEntry) { - const id = bestEntry.target.getAttribute("id"); - allLinks.forEach((link) => { - const isMatch = link.getAttribute("href") === `#${id}`; - link.classList.toggle("active", isMatch); - }); - } - }, - { - root: helpBody, - rootMargin: "-10% 0px -75% 0px", - threshold: [0, 0.25, 0.5], - } - ); - - allSections.forEach((section) => observer.observe(section)); - - // ── Keyboard: Ctrl+↑/↓ to jump between sections ── - helpBody.addEventListener("keydown", (e) => { - if ((e.ctrlKey || e.metaKey) && (e.key === "ArrowDown" || e.key === "ArrowUp")) { - e.preventDefault(); - const visibleSections = allSections.filter(s => !s.classList.contains("help-hidden")); - const currentSection = visibleSections.find((s) => { - const rect = s.getBoundingClientRect(); - const contentRect = helpContent ? helpContent.getBoundingClientRect() : null; - return rect.top >= (contentRect ? contentRect.top : 0) && rect.top < (contentRect ? contentRect.top + 120 : 120); - }); - if (!currentSection) return; - const currentIdx = visibleSections.indexOf(currentSection); - if (e.key === "ArrowDown" && currentIdx < visibleSections.length - 1) { - visibleSections[currentIdx + 1].scrollIntoView({ behavior: "smooth", block: "start" }); - } else if (e.key === "ArrowUp" && currentIdx > 0) { - visibleSections[currentIdx - 1].scrollIntoView({ behavior: "smooth", block: "start" }); - } - } - }); -} - -function closeHelpModal() { - const modal = document.getElementById("help-modal"); - if (modal) modal.classList.remove("active"); -} - -function initConfigModal() { - const openBtn = document.getElementById("config-open-btn"); - const closeBtn = document.getElementById("config-close"); - const modal = document.getElementById("config-modal"); - const addBtn = document.getElementById("config-add-btn"); - const patternInput = document.getElementById("config-pattern-input"); - - if (!openBtn || !closeBtn || !modal) return; - - openBtn.addEventListener("click", async () => { - modal.classList.add("active"); - closeHeaderMenu(); - renderConfigFilters(); - loadConfigFields(); - loadDiagnostics(); - loadAbout(); - await loadHiddenFilesSettings(); - loadWebhooksUI(); - loadSharesUI(); - safeCreateIcons(); - }); - - closeBtn.addEventListener("click", closeConfigModal); - modal.addEventListener("click", (e) => { - if (e.target === modal) { - closeConfigModal(); - } - }); - - addBtn.addEventListener("click", addConfigFilter); - patternInput.addEventListener("keypress", (e) => { - if (e.key === "Enter") { - addConfigFilter(); - } - }); - - patternInput.addEventListener("input", updateRegexPreview); - - // Frontend config fields — save to localStorage on change - ["cfg-debounce", "cfg-results-per-page", "cfg-min-query", "cfg-timeout"].forEach((id) => { - const input = document.getElementById(id); - if (input) input.addEventListener("change", saveFrontendConfig); - }); - - // Backend save button - const saveBtn = document.getElementById("cfg-save-backend"); - if (saveBtn) saveBtn.addEventListener("click", saveBackendConfig); - - // Force reindex - const reindexBtn = document.getElementById("cfg-reindex"); - if (reindexBtn) reindexBtn.addEventListener("click", forceReindex); - - // Reset defaults - const resetBtn = document.getElementById("cfg-reset-defaults"); - if (resetBtn) resetBtn.addEventListener("click", resetConfigDefaults); - - // Refresh diagnostics - const diagBtn = document.getElementById("cfg-refresh-diag"); - if (diagBtn) diagBtn.addEventListener("click", loadDiagnostics); - - // Hidden files configuration - const saveHiddenBtn = document.getElementById("cfg-save-hidden-files"); - if (saveHiddenBtn) saveHiddenBtn.addEventListener("click", saveHiddenFilesSettings); - - // AI Keys - const saveAIKeysBtn = document.getElementById("cfg-save-ai-keys"); - if (saveAIKeysBtn) saveAIKeysBtn.addEventListener("click", saveAIKeys); - const testAIKeysBtn = document.getElementById("cfg-test-ai-keys"); - if (testAIKeysBtn) testAIKeysBtn.addEventListener("click", testAIKeys); - // Load existing keys on modal open - document.getElementById("config-open-btn").addEventListener("click", loadAIKeys); - - // Profile menu button: open config modal and scroll to profile section - var profileBtn = document.getElementById("profile-open-btn"); - if (profileBtn) { - profileBtn.addEventListener("click", function() { - var modal = document.getElementById("config-modal"); - if (modal) modal.classList.add("active"); - setTimeout(function() { - var el = document.getElementById("cfg-profile"); - if (el) el.scrollIntoView({ behavior: 'smooth' }); - }, 300); - }); - } - - // Logout button — handled inline in index.html (onclick) - - // Config nav search - var cfgSearch = document.getElementById("config-nav-search"); - if (cfgSearch) { - cfgSearch.addEventListener("input", function() { - var q = cfgSearch.value.toLowerCase(); - document.querySelectorAll("#config-scroll .config-section").forEach(function(s) { - var text = s.textContent.toLowerCase(); - s.style.display = (q && !text.includes(q)) ? "none" : ""; - }); - document.querySelectorAll("#config-nav .help-nav-link").forEach(function(a) { - var li = a.closest("li"); - if (li) li.style.display = (q && !a.textContent.toLowerCase().includes(q)) ? "none" : ""; - }); - }); - } - - document.addEventListener("keydown", (e) => { - if (e.key === "Escape" && modal.classList.contains("active")) { - closeConfigModal(); - } - }); - - // Load saved frontend config on startup - applyFrontendConfig(); - - // Init theme picker - initThemePicker(); - - // Init profile - initProfile(); -} - -function closeConfigModal() { - const modal = document.getElementById("config-modal"); - if (modal) modal.classList.remove("active"); -} - -// --- Config field helpers --- -const _FRONTEND_CONFIG_KEY = "obsigate-perf-config"; - -function _getFrontendConfig() { - try { - return JSON.parse(localStorage.getItem(_FRONTEND_CONFIG_KEY) || "{}"); - } catch { - return {}; - } -} - -function applyFrontendConfig() { - const cfg = _getFrontendConfig(); - if (cfg.debounce_ms) { - /* applied dynamically in debounce setTimeout */ - } - if (cfg.results_per_page) { - /* used as ADVANCED_SEARCH_LIMIT override */ - } - if (cfg.min_query_length) { - /* used as MIN_SEARCH_LENGTH override */ - } - if (cfg.search_timeout_ms) { - /* used as SEARCH_TIMEOUT_MS override */ - } -} - -export function _getEffective(key, fallback) { - const cfg = _getFrontendConfig(); - return cfg[key] !== undefined ? cfg[key] : fallback; -} - -async function loadConfigFields() { - // Frontend fields from localStorage - const cfg = _getFrontendConfig(); - _setField("cfg-debounce", cfg.debounce_ms || 300); - _setField("cfg-results-per-page", cfg.results_per_page || 50); - _setField("cfg-min-query", cfg.min_query_length || 2); - _setField("cfg-timeout", cfg.search_timeout_ms || 30000); - - // Backend fields from API - try { - const data = await api("/api/config"); - _setField("cfg-workers", data.search_workers); - _setField("cfg-max-content", data.max_content_size); - _setField("cfg-title-boost", data.title_boost); - _setField("cfg-tag-boost", data.tag_boost); - _setField("cfg-prefix-exp", data.prefix_max_expansions); - _setField("cfg-recent-limit", data.recent_files_limit || 20); - _setField("cfg-max-backups", data.max_backups_per_file || 10); - // Watcher config - _setCheckbox("cfg-watcher-enabled", data.watcher_enabled !== false); - _setCheckbox("cfg-watcher-polling", data.watcher_use_polling === true); - _setField("cfg-watcher-interval", data.watcher_polling_interval || 5); - _setField("cfg-watcher-debounce", data.watcher_debounce || 2); - } catch (err) { - console.error("Failed to load backend config:", err); - } -} - -function _setField(id, value) { - const el = document.getElementById(id); - if (el && value !== undefined) el.value = value; -} - -function _setCheckbox(id, checked) { - const el = document.getElementById(id); - if (el) el.checked = !!checked; -} - -function _getCheckbox(id) { - const el = document.getElementById(id); - return el ? el.checked : false; -} - -function _getFieldNum(id, fallback) { - const el = document.getElementById(id); - if (!el) return fallback; - const v = parseFloat(el.value); - return isNaN(v) ? fallback : v; -} - -function saveFrontendConfig() { - const cfg = { - debounce_ms: _getFieldNum("cfg-debounce", 300), - results_per_page: _getFieldNum("cfg-results-per-page", 50), - min_query_length: _getFieldNum("cfg-min-query", 2), - search_timeout_ms: _getFieldNum("cfg-timeout", 30000), - }; - localStorage.setItem(_FRONTEND_CONFIG_KEY, JSON.stringify(cfg)); - showToast(t("toast.config_client_saved"), "success"); -} - -async function saveBackendConfig() { - const body = { - search_workers: _getFieldNum("cfg-workers", 2), - max_content_size: _getFieldNum("cfg-max-content", 100000), - title_boost: _getFieldNum("cfg-title-boost", 3.0), - tag_boost: _getFieldNum("cfg-tag-boost", 2.0), - prefix_max_expansions: _getFieldNum("cfg-prefix-exp", 50), - recent_files_limit: _getFieldNum("cfg-recent-limit", 20), - max_backups_per_file: _getFieldNum("cfg-max-backups", 10), - watcher_enabled: _getCheckbox("cfg-watcher-enabled"), - watcher_use_polling: _getCheckbox("cfg-watcher-polling"), - watcher_polling_interval: _getFieldNum("cfg-watcher-interval", 5.0), - watcher_debounce: _getFieldNum("cfg-watcher-debounce", 2.0), - }; - try { - const res = await fetch("/api/config", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(body), - }); - if (res.ok) { - showToast(t("toast.config_saved"), "success"); - } else { - const errorData = await res.json().catch(() => ({})); - showToast(errorData.detail || "Erreur de sauvegarde", "error"); - } - } catch (err) { - console.error("Failed to save backend config:", err); - showToast(t("config.save_error"), "error"); - } -} - -async function forceReindex() { - const btn = document.getElementById("cfg-reindex"); - if (btn) { - btn.disabled = true; - btn.textContent = t('config.reindexing'); - } - try { - await api("/api/index/reload"); - showToast(t("toast.reindex_done"), "success"); - loadDiagnostics(); - await Promise.all([loadVaults(), loadTags()]); - } catch (err) { - console.error("Reindex error:", err); - showToast(t("config.reindex_error"), "error"); - } finally { - if (btn) { - btn.disabled = false; - btn.textContent = t('config.force_reindex'); - } - } -} - -async function resetConfigDefaults() { - // Reset frontend - localStorage.removeItem(_FRONTEND_CONFIG_KEY); - // Reset backend - try { - await fetch("/api/config", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - search_workers: 2, - debounce_ms: 300, - results_per_page: 50, - min_query_length: 2, - search_timeout_ms: 30000, - max_content_size: 100000, - title_boost: 3.0, - path_boost: 1.5, - tag_boost: 2.0, - prefix_max_expansions: 50, - snippet_context_chars: 120, - max_snippet_highlights: 5, - }), - }); - } catch (err) { - console.error("Reset config error:", err); - } - loadConfigFields(); - showToast(t("toast.config_reset"), "success"); -} - -async function loadDiagnostics() { - const container = document.getElementById("config-diagnostics"); - if (!container) return; - container.innerHTML = '
    Chargement...
    '; - try { - const data = await api("/api/diagnostics"); - renderDiagnostics(container, data); - } catch (err) { - container.innerHTML = '
    Erreur de chargement
    '; - } -} - -function renderDiagnostics(container, data) { - container.innerHTML = ""; - const sections = [ - { - title: "Index", - rows: [ - [t("about.files_indexed"), data.index.total_files], - [t("dashboard.stats_tags"), data.index.total_tags], - [t("dashboard.stats_vaults"), Object.keys(data.index.vaults).join(", ")], - ], - }, - { - title: "Index inversé", - rows: [ - ["Tokens uniques", data.inverted_index.unique_tokens.toLocaleString()], - ["Postings total", data.inverted_index.total_postings.toLocaleString()], - ["Documents", data.inverted_index.documents], - ["Mémoire estimée", data.inverted_index.memory_estimate_mb + " MB"], - ["Stale", data.inverted_index.is_stale ? "Oui" : "Non"], - ], - }, - { - title: "Moteur de recherche", - rows: [ - ["Executor actif", data.search_executor.active ? "Oui" : "Non"], - ["Workers max", data.search_executor.max_workers], - ], - }, - ]; - sections.forEach((section) => { - const div = document.createElement("div"); - div.className = "config-diag-section"; - const title = document.createElement("div"); - title.className = "config-diag-section-title"; - title.textContent = section.title; - div.appendChild(title); - section.rows.forEach(([label, value]) => { - const row = document.createElement("div"); - row.className = "config-diag-row"; - row.innerHTML = `${label}${value}`; - div.appendChild(row); - }); - container.appendChild(div); - }); -} - -// --- About Section --- - -function loadAbout() { - const container = document.getElementById("config-about"); - if (!container) return; - - // Fetch health info for version - api("/api/health").then((health) => { - container.innerHTML = ""; - - const sections = [ - { - title: t("about.section_app"), - rows: [ - [t("about.name"), "ObsiGate"], - [t("about.version"), state.APP_VERSION], - [t("about.api_version"), health.version || "—"], - [t("about.status"), health.status || "—"], - ], - }, - { - title: t("about.section_env"), - rows: [ - [t("about.vaults_configured"), health.vaults || "—"], - [t("about.files_indexed"), health.total_files || "—"], - [t("about.browser"), navigator.userAgent.split(" ").pop()], - [t("about.platform"), navigator.platform || "—"], - [t("about.language"), navigator.language || "—"], - ], - }, - { - title: t("about.section_components"), - rows: [ - [t("about.backend"), "FastAPI (Python)"], - [t("about.markdown_renderer"), "mistune"], - [t("about.file_watcher"), "watchdog"], - [t("about.frontend"), "Vanilla JavaScript"], - [t("about.icons"), "Lucide Icons"], - [t("about.syntax_highlight"), "highlight.js"], - [t("about.editor"), "CodeMirror 6"], - ], - }, - ]; - - sections.forEach((section) => { - const div = document.createElement("div"); - div.className = "config-diag-section"; - const title = document.createElement("div"); - title.className = "config-diag-section-title"; - title.textContent = section.title; - div.appendChild(title); - section.rows.forEach(([label, value]) => { - const row = document.createElement("div"); - row.className = "config-diag-row"; - row.innerHTML = `${label}${value}`; - div.appendChild(row); - }); - container.appendChild(div); - }); - }).catch(() => { - container.innerHTML = '
    Erreur de chargement
    '; - }); -} - -// --- Hidden Files Configuration --- - -async function loadHiddenFilesSettings() { - const container = document.getElementById("hidden-files-vault-list"); - if (!container) return; - - container.innerHTML = '
    Chargement...
    '; - - try { - const settings = await api("/api/vaults/settings/all"); - renderHiddenFilesSettings(container, settings); - } catch (err) { - console.error("Failed to load hidden files settings:", err); - container.innerHTML = '
    Erreur de chargement
    '; - } -} - -function renderHiddenFilesSettings(container, allSettings) { - container.innerHTML = ""; - - if (!state.allVaults || state.allVaults.length === 0) { - container.innerHTML = '
    Aucun vault configuré
    '; - return; - } - - state.allVaults.forEach((vault) => { - const settings = allSettings[vault.name] || { hideHiddenFiles: false }; - - const vaultCard = el("div", { class: "hidden-files-vault-card", "data-vault": vault.name }); - - // Vault header - const header = el("div", { class: "hidden-files-vault-header" }, [el("h3", {}, [document.createTextNode(vault.name)]), el("span", { class: "hidden-files-vault-type" }, [document.createTextNode(vault.type || "VAULT")])]); - - // Hide hidden files toggle - const toggleRow = el("div", { class: "config-row" }, [ - el("label", { class: "config-label", for: `hide-hidden-${vault.name}` }, [document.createTextNode("Masquer les fichiers/dossiers cachés")]), - el("label", { class: "config-toggle" }, [ - el("input", { - type: "checkbox", - id: `hide-hidden-${vault.name}`, - "data-vault": vault.name, - checked: settings.hideHiddenFiles ? "true" : false, - }), - el("span", { class: "config-toggle-slider" }), - ]), - el("span", { class: "config-hint" }, [document.createTextNode("Masquer les fichiers/dossiers commençant par un point dans l'interface (ils restent indexés et cherchables)")]), - ]); - - vaultCard.appendChild(header); - vaultCard.appendChild(toggleRow); - - container.appendChild(vaultCard); - }); -} - -async function saveHiddenFilesSettings() { - const btn = document.getElementById("cfg-save-hidden-files"); - if (btn) { - btn.disabled = true; - btn.textContent = t("config.saving") + "..."; - } - - try { - const vaultCards = document.querySelectorAll(".hidden-files-vault-card"); - const promises = []; - - vaultCards.forEach((card) => { - const vaultName = card.dataset.vault; - const hideHiddenFiles = document.getElementById(`hide-hidden-${vaultName}`)?.checked || false; - - const settings = { - hideHiddenFiles, - }; - - promises.push( - api(`/api/vaults/${encodeURIComponent(vaultName)}/settings`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(settings), - }), - ); - }); - - await Promise.all(promises); - - // Reload vault settings to update the cache - await loadVaultSettings(); - - showToast(t("config.settings_saved"), "success"); - - // Refresh the UI to apply the filter - await Promise.all([refreshSidebarTreePreservingState(), refreshTagsForContext()]); - } catch (err) { - console.error("Failed to save hidden files settings:", err); - const errorMsg = err.message || t("config.error_unknown"); - showToast(t("config.error_prefix") + ": " + errorMsg, "error"); - } finally { - if (btn) { - btn.disabled = false; - btn.textContent = "💾 " + t("config.save"); - } - } -} - -// ── Webhooks UI ── -async function loadWebhooksUI() { - const list = document.getElementById("webhooks-list"); - if (!list) return; - try { - const webhooks = await api("/api/webhooks"); - renderWebhooksUI(webhooks); - } catch { list.innerHTML = '
    Admin uniquement
    '; } -} -function renderWebhooksUI(webhooks) { - const list = document.getElementById("webhooks-list"); - if (!list) return; - if (!webhooks.length) { list.innerHTML = '
    Aucun webhook configuré.
    '; return; } - list.innerHTML = webhooks.map(w => ` -
    - ${escapeHtml(w.name)} - ${escapeHtml(w.url)} - ${(w.events||[]).join(", ")} - -
    - `).join(""); - list.querySelectorAll(".webhook-delete").forEach(b => b.addEventListener("click", async () => { - await api(`/api/webhooks/${b.dataset.id}`, { method: "DELETE" }); - loadWebhooksUI(); - })); -} -document.addEventListener("click", function(e) { - if (e.target.id === "webhook-add-btn") { - const name = document.getElementById("webhook-name-input").value.trim(); - const url = document.getElementById("webhook-url-input").value.trim(); - if (!url) { showToast(t("config.url_required"), "error"); return; } - api("/api/webhooks", { method: "POST", body: JSON.stringify({ name: name || "Webhook", url, events: ["file_created","file_deleted","file_modified","file_renamed"] }) }).then(() => { loadWebhooksUI(); document.getElementById("webhook-name-input").value = ""; document.getElementById("webhook-url-input").value = ""; }).catch(err => showToast(err.message, "error")); - } -}); - -// ── Shares UI ── -async function loadSharesUI() { - const list = document.getElementById("shares-list"); - if (!list) return; - try { - const shares = await api("/api/shares"); - renderSharesUI(shares); - } catch { list.innerHTML = '
    Chargement...
    '; } -} -function renderSharesUI(shares) { - const list = document.getElementById("shares-list"); - if (!list) return; - if (!shares.length) { list.innerHTML = '
    Aucun partage actif.
    '; return; } - list.innerHTML = shares.map(s => ` - - `).join(""); - list.querySelectorAll(".share-revoke").forEach(b => b.addEventListener("click", async () => { - await api(`/api/share/${b.dataset.id}`, { method: "DELETE" }); - loadSharesUI(); - })); -} - -// ── Share Dialog (professional) ── -export async function openShareDialog(vault, path) { - // First check if already shared - let existingShare = null; - try { - const shares = await api("/api/shares"); - existingShare = shares.find(s => s.vault === vault && s.path === path); - } catch (e) { /* ignore */ } - - const div = document.createElement("div"); - div.className = "share-dialog-overlay"; - - const renderContent = () => { - if (existingShare) { - const url = window.location.origin + existingShare.url; - const expiresInfo = existingShare.expires_at - ? `

    Expire le ${new Date(existingShare.expires_at).toLocaleDateString("fr-FR")}

    ` - : '

    Sans expiration

    '; - div.innerHTML = ` - `; - div.querySelector(".share-copy-btn").addEventListener("click", async () => { - try { - await navigator.clipboard.writeText(url); - } catch (e) { - // Fallback for non-HTTPS contexts - const ta = document.createElement("textarea"); - ta.value = url; ta.style.position = "fixed"; ta.style.left = "-9999px"; - document.body.appendChild(ta); ta.select(); document.execCommand("copy"); - document.body.removeChild(ta); - } - showToast(t("config.link_copied"), "success"); - div.remove(); - }); - div.querySelector(".share-revoke-btn").addEventListener("click", async () => { - try { - await api(`/api/share/${existingShare.id}`, { method: "DELETE" }); - showToast(t("config.share_revoked"), "success"); - existingShare = null; - renderContent(); - } catch (err) { showToast("Erreur: " + err.message, "error"); } - }); - } else { - div.innerHTML = ` - `; - div.querySelector(".share-create-btn").addEventListener("click", async () => { - try { - const expiry = document.getElementById("share-expiry")?.value; - const share = await api(`/api/share/${encodeURIComponent(vault)}`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ path, expires_in_hours: expiry ? parseInt(expiry) : null }), - }); - existingShare = share; - renderContent(); - showToast(t("config.link_created"), "success"); - } catch (err) { showToast("Erreur: " + err.message, "error"); } - }); - } - div.querySelector(".share-close-btn").addEventListener("click", () => div.remove()); - div.addEventListener("click", (e) => { if (e.target === div) div.remove(); }); - }; - - renderContent(); - document.body.appendChild(div); -} - -function renderConfigFilters() { - const config = TagFilterService.getConfig(); - const filters = config.tagFilters || TagFilterService.defaultFilters; - const container = document.getElementById("config-filters-list"); - - container.innerHTML = ""; - - filters.forEach((filter, index) => { - const badge = el("div", { class: `config-filter-badge ${!filter.enabled ? "disabled" : ""}` }, [ - el("span", {}, [document.createTextNode(filter.pattern)]), - el( - "button", - { - class: "config-filter-toggle", - title: filter.enabled ? "Désactiver" : "Activer", - type: "button", - }, - [document.createTextNode(filter.enabled ? "✓" : "○")], - ), - el( - "button", - { - class: "config-filter-remove", - title: "Supprimer", - type: "button", - }, - [document.createTextNode("×")], - ), - ]); - - const toggleBtn = badge.querySelector(".config-filter-toggle"); - const removeBtn = badge.querySelector(".config-filter-remove"); - - toggleBtn.addEventListener("click", (e) => { - e.stopPropagation(); - toggleConfigFilter(index); - }); - - removeBtn.addEventListener("click", (e) => { - e.stopPropagation(); - removeConfigFilter(index); - }); - - container.appendChild(badge); - }); -} - -function toggleConfigFilter(index) { - const config = TagFilterService.getConfig(); - const filters = config.tagFilters || TagFilterService.defaultFilters; - if (filters[index]) { - filters[index].enabled = !filters[index].enabled; - config.tagFilters = filters; - TagFilterService.saveConfig(config); - renderConfigFilters(); - refreshTagsForContext().catch((err) => console.error("Error refreshing tags:", err)); - } -} - -function removeConfigFilter(index) { - const config = TagFilterService.getConfig(); - let filters = config.tagFilters || TagFilterService.defaultFilters; - filters = filters.filter((_, i) => i !== index); - config.tagFilters = filters; - TagFilterService.saveConfig(config); - renderConfigFilters(); - refreshTagsForContext().catch((err) => console.error("Error refreshing tags:", err)); -} - -function addConfigFilter() { - const input = document.getElementById("config-pattern-input"); - const pattern = input.value.trim(); - - if (!pattern) return; - - const regex = TagFilterService.patternToRegex(pattern); - const config = TagFilterService.getConfig(); - const filters = config.tagFilters || TagFilterService.defaultFilters; - - const newFilter = { pattern, regex, enabled: true }; - filters.push(newFilter); - config.tagFilters = filters; - TagFilterService.saveConfig(config); - - input.value = ""; - renderConfigFilters(); - refreshTagsForContext().catch((err) => console.error("Error refreshing tags:", err)); - updateRegexPreview(); -} - -function updateRegexPreview() { - const input = document.getElementById("config-pattern-input"); - const preview = document.getElementById("config-regex-preview"); - const code = document.getElementById("config-regex-code"); - const pattern = input.value.trim(); - - if (pattern) { - const regex = TagFilterService.patternToRegex(pattern); - code.textContent = `^${regex}$`; - preview.style.display = "block"; - } else { - preview.style.display = "none"; - } -} - - -// ── AI Keys management ── -async function loadAIKeys() { - try { - const data = await api("/api/config/ai-keys"); - ["DEEPSEEK_API_KEY","OPENROUTER_API_KEY","GEMINI_API_KEY"].forEach(k => { - const id = "cfg-" + k.toLowerCase().replace(/_api_key/g, "") + "-key"; - const input = document.getElementById(id); - if (input && data[k]) input.placeholder = data[k]; - }); - } catch(e) {} -} - -async function saveAIKeys() { - const keys = {}; - const map = { "cfg-deepseek-key": "DEEPSEEK_API_KEY", "cfg-openrouter-key": "OPENROUTER_API_KEY", "cfg-gemini-key": "GEMINI_API_KEY" }; - for (const [id, name] of Object.entries(map)) { - const input = document.getElementById(id); - if (input && input.value.trim()) keys[name] = input.value.trim(); - } - if (!Object.keys(keys).length) { showToast(t("config.no_keys"), "warning"); return; } - try { - await api("/api/config/ai-keys", { method: "POST", body: JSON.stringify(keys) }); - showToast(t("config.api_keys_saved"), "success"); - // Clear inputs - Object.keys(map).forEach(id => { const el = document.getElementById(id); if (el) el.value = ""; }); - loadAIKeys(); - } catch(e) { showToast("Erreur: " + e.message, "error"); } -} - -async function testAIKeys() { - const status = document.getElementById("cfg-ai-status"); - if (status) status.textContent = "Test en cours..."; - try { - // Test connectivity - const results = await api("/api/config/ai-keys/test", { method: "POST" }); - var msg = Object.entries(results).map(([k,v]) => k + ": " + v).join(" | "); - if (status) status.textContent = msg; - // Fetch models for configured providers - for (const p of ["deepseek","openrouter","gemini"]) { - if (results[p] === "ok") { - try { - const m = await api("/api/config/ai-models?provider=" + p); - var sel = document.getElementById("cfg-" + p + "-model"); - if (sel && m.models && m.models.length) { - sel.innerHTML = ''; - m.models.forEach(function(md) { - sel.innerHTML += ''; - }); - } - } catch(e) { console.warn("Failed to fetch models for", p, e); } - } - } - } catch(e) { - if (status) status.textContent = "Erreur: " + e.message; - } -} - - -export { - initSidebarTabs, - initConfigModal, - initConfigModal as initConfigPanel, - initHelpModal, - closeHelpModal, - initRecentTab, - initEditorPocBtn, - loadAbout as initAboutSection, - loadHiddenFilesSettings as initHiddenFilesConfig, - initThemePicker, - initAboutModal, - initProfile, - switchSidebarTab, -}; - -// ── Theme Picker ───────────────────────────────────────────────────── -function initThemePicker() { - import('./themes.js').then(function(mod) { - var THEMES = mod.THEMES; - var applyTheme = mod.applyTheme; - var getCurrentTheme = mod.getCurrentTheme; - var getCurrentMode = mod.getCurrentMode; - - var grid = document.getElementById('theme-grid'); - if (!grid) return; - - var themeKeys = Object.keys(THEMES); - - function renderCards() { - var current = getCurrentTheme(); - var mode = getCurrentMode(); - grid.innerHTML = ''; - themeKeys.forEach(function(key) { - var t = THEMES[key]; - var v = t.modes[mode]; - if (!v) return; - var card = document.createElement('div'); - card.className = 'theme-card' + (key === current ? ' active' : ''); - card.innerHTML = - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + t.name + '
    ' + - '
    ' + t.desc + '
    '; - card.addEventListener('click', function() { - applyTheme(key, mode); - renderCards(); - }); - grid.appendChild(card); - }); - // Mode toggle - var toggle = document.createElement('div'); - toggle.className = 'theme-mode-toggle'; - var dBtn = elBtn(t('theme.dark'), 'dark', mode); - var lBtn = elBtn(t('theme.light'), 'light', mode); - toggle.appendChild(dBtn); - toggle.appendChild(lBtn); - grid.appendChild(toggle); - } - - function elBtn(label, m, currentMode) { - var btn = document.createElement('button'); - btn.className = 'theme-mode-btn' + (m === currentMode ? ' active' : ''); - btn.textContent = label; - btn.addEventListener('click', function() { - applyTheme(getCurrentTheme(), m); - renderCards(); - }); - return btn; - } - - renderCards(); - }); -} - -// ── About Modal ────────────────────────────────────────────────────── -function initAboutModal() { - var overlay = document.getElementById('about-overlay'); - var closeBtn = document.getElementById('about-close'); - if (!overlay) return; - - // Open button - var openBtn = document.getElementById('about-open-btn'); - if (openBtn) { - openBtn.addEventListener('click', function() { - overlay.classList.add('active'); - populateAbout(); - }); - } - - // Close - closeBtn.addEventListener('click', function() { overlay.classList.remove('active'); }); - overlay.addEventListener('click', function(e) { if (e.target === overlay) overlay.classList.remove('active'); }); - document.addEventListener('keydown', function(e) { if (e.key === 'Escape' && overlay.classList.contains('active')) overlay.classList.remove('active'); }); - - function populateAbout() { - // Live stats from health endpoint - fetch('/api/health') - .then(function(r) { return r.json(); }) - .then(function(d) { - var fEl = document.getElementById('about-stat-files'); - var vEl = document.getElementById('about-stat-vaults'); - if (fEl) fEl.textContent = d.total_files || '—'; - if (vEl) vEl.textContent = d.vaults || '—'; - }) - .catch(function() {}); - - // Build date (today) - var now = new Date(); - var months = [t('month.january'),t('month.february'),t('month.march'),t('month.april'),t('month.may'),t('month.june'),t('month.july'),t('month.august'),t('month.september'),t('month.october'),t('month.november'),t('month.december')]; - var dateEl = document.getElementById('about-build-date'); - if (dateEl) dateEl.textContent = months[now.getMonth()] + ' ' + now.getFullYear(); - - // Random joke - var jokes = [ - t('about.joke_0'), - t('about.joke_1'), - t('about.joke_2'), - t('about.joke_3'), - t('about.joke_4'), - t('about.joke_5'), - t('about.joke_6'), - t('about.joke_7'), - t('about.joke_8'), - t('about.joke_9') - ]; - var jokeEl = document.getElementById('about-joke'); - if (jokeEl) jokeEl.textContent = jokes[Math.floor(Math.random() * jokes.length)]; - } -} - -// ── Profile ────────────────────────────────────────────────────────── -function initProfile() { - var langSel = document.getElementById('profile-lang'); - var nameInp = document.getElementById('profile-name'); - var saveBtn = document.getElementById('profile-save'); - var logoutBtn = document.getElementById('profile-logout'); - var savedEl = document.getElementById('profile-saved'); - if (!langSel || !saveBtn) return; - - // Load saved profile - try { - var lang = getLocale(); - var name = localStorage.getItem('obsigate-name') || ''; - if (langSel) langSel.value = lang; - if (nameInp) nameInp.value = name; - } catch(e) {} - - saveBtn.addEventListener('click', async function() { - try { - var newLang = langSel.value; - await setLocale(newLang); // Live-reload all translations - if (nameInp) localStorage.setItem('obsigate-name', nameInp.value.trim()); - - // Persist language to server (survives clear site data) - try { - await fetch('/api/auth/me', { - method: 'PATCH', - headers: { 'Content-Type': 'application/json' }, - credentials: 'include', - body: JSON.stringify({ language: newLang }), - }); - } catch (e) { /* non-bloquant */ } - - if (savedEl) { savedEl.style.display = 'inline'; setTimeout(function() { savedEl.style.display = 'none'; }, 2000); } - } catch(e) {} - }); - - // Logout button — handled inline in index.html (onclick) -} diff --git a/desktop/frontend-static/js/dashboard.js b/desktop/frontend-static/js/dashboard.js deleted file mode 100644 index 697a908..0000000 --- a/desktop/frontend-static/js/dashboard.js +++ /dev/null @@ -1,484 +0,0 @@ -// dashboard.js — extracted from app.js (3414-3806) + DashboardBookmarkWidget (3810-3870) -import { api } from './auth.js'; -import { state } from './state.js'; -import { escapeHtml, safeCreateIcons, getFileIcon } from './utils.js'; -import { icon, openFile } from './viewer.js'; -import { TabManager, showToast } from './ui.js'; -import { t, getLocale } from './i18n.js'; - -// --------------------------------------------------------------------------- -// Recent files -// --------------------------------------------------------------------------- -let _recentRefreshTimer = null; -let _recentTimestampTimer = null; -let _recentFilesCache = []; - -// --------------------------------------------------------------------------- -// Dashboard Recent Files Widget -// --------------------------------------------------------------------------- -// ── Dashboard Stats Widget ── -const DashboardStatsWidget = { - async load() { - const grid = document.getElementById("dashboard-stats-grid"); - if (!grid) return; - grid.innerHTML = `
    ${t('common.loading')}
    `; - try { - const data = await api("/api/dashboard"); - this.render(data); - } catch (err) { - grid.innerHTML = `
    ${t('dashboard.error_prefix')}${escapeHtml(err.message)}
    `; - } - }, - render(data) { - const grid = document.getElementById("dashboard-stats-grid"); - if (!grid) return; - const fmtSize = (bytes) => bytes < 1024 ? `${bytes}${t('dashboard.size_bytes')}` : bytes < 1048576 ? `${(bytes/1024).toFixed(1)}${t('dashboard.size_kb')}` : bytes < 1073741824 ? `${(bytes/1048576).toFixed(1)}${t('dashboard.size_mb')}` : `${(bytes/1073741824).toFixed(1)}${t('dashboard.size_gb')}`; - const items = [ - { icon: "files", label: t('dashboard.stats_files'), value: data.total_files.toLocaleString() }, - { icon: "tags", label: t('dashboard.stats_tags'), value: data.total_tags.toLocaleString() }, - { icon: "hard-drive", label: t('dashboard.stats_size'), value: fmtSize(data.total_size_bytes) }, - { icon: "folder-open", label: t('dashboard.stats_vaults'), value: data.vaults.length.toString() }, - ]; - grid.innerHTML = items.map(i => ` -
    - - ${i.value} - ${i.label} -
    - `).join(""); - safeCreateIcons(); - } -}; - -// ── Dashboard Shared Widget ── -const DashboardSharedWidget = { - async load() { - const grid = document.getElementById("dashboard-shared-grid"); - const empty = document.getElementById("dashboard-shared-empty"); - if (!grid) return; - try { - const shares = await api("/api/shares"); - if (!shares.length) { if (empty) empty.style.display = ""; grid.innerHTML = ""; return; } - if (empty) empty.style.display = "none"; - grid.innerHTML = shares.map(s => ` -
    -
    - - ${escapeHtml(s.path.split("/").pop().replace(/\.md$/i, ""))} - ${escapeHtml(s.vault)} -
    -
    - ${s.access_count || 0} ${t('dashboard.views', {count: s.access_count || 0})} - ${s.expires_at ? `${t('dashboard.expires', {date: new Date(s.expires_at).toLocaleDateString(getLocale() === 'fr' ? 'fr-FR' : 'en-US')})}` : ""} -
    -
    - - - -
    -
    - `).join(""); - lucide.createIcons(); - grid.querySelectorAll(".shared-copy-btn").forEach(b => b.addEventListener("click", async (e) => { - e.stopPropagation(); - const url = b.dataset.url; - try { await navigator.clipboard.writeText(url); } catch { const ta = document.createElement("textarea"); ta.value=url; ta.style.position="fixed"; ta.style.left="-9999px"; document.body.appendChild(ta); ta.select(); document.execCommand("copy"); document.body.removeChild(ta); } - showToast(t("config.link_copied"), "success"); - })); - grid.querySelectorAll(".shared-open-btn").forEach(b => b.addEventListener("click", (e) => { - e.stopPropagation(); - const card = b.closest(".shared-card"); - if (card) TabManager.openPreview(card.dataset.vault, card.dataset.path); - })); - grid.querySelectorAll(".shared-revoke-btn").forEach(b => b.addEventListener("click", async (e) => { - e.stopPropagation(); - await api(`/api/share/${b.dataset.id}`, { method: "DELETE" }); - showToast(t("config.share_revoked"), "success"); - this.load(); - })); - grid.querySelectorAll(".shared-card").forEach(card => card.addEventListener("click", () => { - TabManager.openPreview(card.dataset.vault, card.dataset.path); - })); - } catch (err) { if (empty) empty.style.display = ""; } - } -}; - -// ── Dashboard Conflicts Widget ── -const DashboardConflictsWidget = { - async load() { - const container = document.getElementById("dashboard-conflicts-container"); - if (!container) return; - try { - const data = await api("/api/conflicts"); - if (data.total === 0) { container.innerHTML = ""; return; } - this.render(data.conflicts, container); - } catch (err) { container.innerHTML = ""; } - }, - render(conflicts, container) { - container.innerHTML = ` -
    -
    -
    - -

    ${t('dashboard.conflicts_title')}

    - ${conflicts.length} -
    -
    -
    - ${conflicts.map(c => ` -
    -
    - ${escapeHtml(c.vault)} - ${escapeHtml(c.conflict_path.split("/").pop())} - ${t('dashboard.conflict_date')}${c.conflict_date.replace(/(\d{4})(\d{2})(\d{2})-(\d{2})(\d{2})/, "$3/$2/$1 $4:$5")} -
    -
    - - -
    -
    - `).join("")} -
    -
    `; - lucide.createIcons(); - container.querySelectorAll(".keep-local").forEach(btn => btn.addEventListener("click", () => this._resolve(btn.dataset, "keep_local"))); - container.querySelectorAll(".keep-conflict").forEach(btn => btn.addEventListener("click", () => this._resolve(btn.dataset, "keep_conflict"))); - }, - async _resolve(d, action) { - try { - await api("/api/conflicts/resolve", { method: "POST", body: JSON.stringify({ vault: d.vault, conflict_path: d.conflict, original_path: d.original, action }) }); - showToast(t("dashboard.conflict_resolved"), "success"); - this.load(); - } catch (err) { showToast(t('dashboard.error_prefix') + err.message, "error"); } - } -}; - -const DashboardRecentWidget = { - _cache: [], - _currentFilter: "", - - async load(vaultFilter = "") { - const v = vaultFilter || state.selectedContextVault || "all"; - this._currentFilter = v; - this.showLoading(); - - let url = "/api/recent?mode=opened"; - if (v !== "all") url += `&vault=${encodeURIComponent(v)}`; - - try { - const data = await api(url); - this._cache = data.files || []; - this.render(); - } catch (err) { - console.error("Dashboard: Failed to load recent files:", err); - this.showError(); - } - }, - - async toggleBookmark(vault, path, title, card) { - try { - const data = await api("/api/bookmarks/toggle", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ vault, path, title }), - }); - - // Refresh both widgets to keep sync - DashboardBookmarkWidget.load(); - - // Update current card icon if it exists - if (card) { - const btn = card.querySelector(".dashboard-card-bookmark-btn"); - if (btn) { - btn.classList.toggle("active", data.bookmarked); - const icon = btn.querySelector("i"); - if (icon) icon.setAttribute("data-lucide", data.bookmarked ? "bookmark" : "bookmark-plus"); - safeCreateIcons(); - } - } - - // Check if we need to refresh the current list to reflect bookmark status across all cards - // To avoid flickering, just update the cache and re-render if needed or do a silent refresh - this._cache.forEach(f => { - if (f.vault === vault && f.path === path) f.bookmarked = data.bookmarked; - }); - } catch (err) { - console.error("Failed to toggle bookmark:", err); - showToast(t("dashboard.pin_error"), "error"); - } - }, - - showLoading() { - const grid = document.getElementById("dashboard-recent-grid"); - const loading = document.getElementById("dashboard-loading"); - const empty = document.getElementById("dashboard-recent-empty"); - const count = document.getElementById("dashboard-count"); - - if (grid) grid.innerHTML = ""; - if (loading) loading.classList.add("active"); - if (empty) empty.classList.add("hidden"); - if (count) count.textContent = ""; - }, - - render() { - const grid = document.getElementById("dashboard-recent-grid"); - const loading = document.getElementById("dashboard-loading"); - const empty = document.getElementById("dashboard-recent-empty"); - const count = document.getElementById("dashboard-count"); - - if (loading) loading.classList.remove("active"); - - if (!this._cache || this._cache.length === 0) { - this.showEmpty(); - return; - } - - if (empty) empty.classList.add("hidden"); - if (count) count.textContent = `${this._cache.length} ${this._cache.length > 1 ? t('dashboard.count_files_plural') : t('dashboard.count_files')}`; - - if (!grid) return; - grid.innerHTML = ""; - - this._cache.forEach((f, index) => { - const card = this._createCard(f, index); - grid.appendChild(card); - }); - - safeCreateIcons(); - }, - - _createCard(file, index) { - const card = document.createElement("div"); - card.className = "dashboard-card"; - card.setAttribute("data-vault", file.vault); - card.setAttribute("data-path", file.path); - card.style.animationDelay = `${Math.min(index * 50, 400)}ms`; - - // Header with icon and vault badge - const header = document.createElement("div"); - header.className = "dashboard-card-header"; - - const iconContainer = document.createElement("div"); - iconContainer.className = "dashboard-card-icon"; - const fileIconName = getFileIcon(file.path); - try { - iconContainer.appendChild(icon(fileIconName, 24)); - } catch (e) { - console.error("Error creating icon:", fileIconName, e); - // Fallback to default file icon - iconContainer.appendChild(icon("file", 24)); - } - - const badge = document.createElement("span"); - badge.className = "dashboard-vault-badge"; - badge.textContent = file.vault; - - const bookmarkBtn = document.createElement("button"); - bookmarkBtn.className = `dashboard-card-bookmark-btn ${file.bookmarked ? "active" : ""}`; - bookmarkBtn.title = file.bookmarked ? t('dashboard.bookmark_remove') : t('dashboard.bookmark_add'); - bookmarkBtn.innerHTML = ``; - - bookmarkBtn.addEventListener("click", (e) => { - e.stopPropagation(); - this.toggleBookmark(file.vault, file.path, file.title, card); - }); - - header.appendChild(iconContainer); - header.appendChild(badge); - header.appendChild(bookmarkBtn); - card.appendChild(header); - - // Title - const title = document.createElement("h3"); - title.className = "dashboard-card-title"; - title.textContent = file.title || file.path.split("/").pop(); - title.title = file.title || file.path; - card.appendChild(title); - - // Path (compact) - const pathParts = file.path.split("/"); - if (pathParts.length > 1) { - const path = document.createElement("div"); - path.className = "dashboard-card-path"; - path.textContent = pathParts.slice(0, -1).join(" / "); - path.title = file.path; - card.appendChild(path); - } - - // Footer with time and tags - const footer = document.createElement("div"); - footer.className = "dashboard-card-footer"; - - const time = document.createElement("span"); - time.className = "dashboard-card-time"; - time.innerHTML = ` ${file.mtime_human || this._humanizeDelta(file.mtime)}`; - - footer.appendChild(time); - - // Tags - if (file.tags && file.tags.length > 0) { - const tags = document.createElement("div"); - tags.className = "dashboard-card-tags"; - file.tags.slice(0, 3).forEach((tag) => { - const tagEl = document.createElement("span"); - tagEl.className = "tag-pill"; - tagEl.textContent = tag; - tags.appendChild(tagEl); - }); - footer.appendChild(tags); - } - - card.appendChild(footer); - - // Click handler - card.addEventListener("click", () => { - openFile(file.vault, file.path); - }); - - return card; - }, - - showEmpty() { - const grid = document.getElementById("dashboard-recent-grid"); - const loading = document.getElementById("dashboard-loading"); - const empty = document.getElementById("dashboard-recent-empty"); - const count = document.getElementById("dashboard-count"); - - if (grid) grid.innerHTML = ""; - if (loading) loading.classList.remove("active"); - if (empty) empty.classList.remove("hidden"); - if (count) count.textContent = t('dashboard.zero_files'); - safeCreateIcons(); - }, - - showError() { - this.showEmpty(); - const empty = document.getElementById("dashboard-recent-empty"); - if (empty) { - const msg = empty.querySelector("span"); - if (msg) msg.textContent = t('dashboard.load_error'); - } - }, - - _humanizeDelta(mtime) { - const delta = Date.now() / 1000 - mtime; - if (delta < 60) return t('dashboard.just_now'); - if (delta < 3600) return t('dashboard.min_ago', { n: Math.floor(delta / 60) }); - if (delta < 86400) return t('dashboard.hour_ago', { n: Math.floor(delta / 3600) }); - if (delta < 604800) return t('dashboard.day_ago', { n: Math.floor(delta / 86400) }); - return new Date(mtime * 1000).toLocaleDateString(getLocale() === 'fr' ? 'fr-FR' : 'en-US', { day: "numeric", month: "short", year: "numeric" }); - }, - - populateVaultFilter() { - const select = document.getElementById("dashboard-vault-filter"); - if (!select) return; - - // Keep first option "Tous les vaults" - while (select.options.length > 1) select.remove(1); - - if (typeof state.allVaults !== "undefined" && Array.isArray(state.allVaults)) { - state.allVaults.forEach((v) => { - const opt = document.createElement("option"); - opt.value = v.name; - opt.textContent = v.name; - select.appendChild(opt); - }); - } - syncVaultSelectors(); - }, - - init() { - const select = document.getElementById("dashboard-vault-filter"); - if (select) { - select.addEventListener("change", async () => { - await setSelectedVaultContext(select.value, { focusVault: select.value !== "all" }); - }); - } - - this.populateVaultFilter(); - - // Quick Help toggle (with localStorage persistence) - var qhToggle = document.getElementById('qh-toggle'); - var qhBody = document.getElementById('qh-body'); - if (qhToggle && qhBody) { - // Restore saved state - if (localStorage.getItem('obsigate-qh-collapsed') === '1') { - qhBody.classList.add('collapsed'); - qhToggle.textContent = '+'; - qhToggle.title = t('dashboard.show'); - } - qhToggle.addEventListener('click', function() { - var collapsed = qhBody.classList.toggle('collapsed'); - qhToggle.textContent = collapsed ? '+' : '\u2212'; - qhToggle.title = collapsed ? t('dashboard.show') : t('dashboard.hide'); - localStorage.setItem('obsigate-qh-collapsed', collapsed ? '1' : '0'); - }); - } - }, -}; - -// ── Dashboard Bookmarks Widget ── -// (moved from app.js 3810-3870; logically belongs with dashboard widgets) -const DashboardBookmarkWidget = { - _cache: [], - _currentFilter: "", - - async load(vaultFilter = "") { - const v = vaultFilter || state.selectedContextVault || "all"; - this._currentFilter = v; - this.showLoading(); - - let url = "/api/bookmarks"; - if (v !== "all") url += `?vault=${encodeURIComponent(v)}`; - - try { - const data = await api(url); - this._cache = data.files || []; - this.render(); - } catch (err) { - console.error("Dashboard: Failed to load bookmarks:", err); - this.showEmpty(); - } - }, - - showLoading() { - const grid = document.getElementById("dashboard-bookmarks-grid"); - const empty = document.getElementById("dashboard-bookmarks-empty"); - const section = document.getElementById("dashboard-bookmarks-section"); - - if (grid) grid.innerHTML = ""; - if (empty) empty.classList.add("hidden"); - }, - - render() { - const grid = document.getElementById("dashboard-bookmarks-grid"); - const empty = document.getElementById("dashboard-bookmarks-empty"); - const section = document.getElementById("dashboard-bookmarks-section"); - - if (!this._cache || this._cache.length === 0) { - if (grid) grid.innerHTML = ""; - if (empty) empty.classList.remove("hidden"); - return; - } - - if (empty) empty.classList.add("hidden"); - if (!grid) return; - grid.innerHTML = ""; - - this._cache.forEach((f, idx) => { - const card = DashboardRecentWidget._createCard(f, idx); - grid.appendChild(card); - }); - - safeCreateIcons(); - }, - - showEmpty() { - const grid = document.getElementById("dashboard-bookmarks-grid"); - const empty = document.getElementById("dashboard-bookmarks-empty"); - if (grid) grid.innerHTML = ""; - if (empty) empty.classList.remove("hidden"); - } -}; - -export { DashboardRecentWidget, DashboardStatsWidget, DashboardBookmarkWidget, DashboardSharedWidget, DashboardConflictsWidget }; diff --git a/desktop/frontend-static/js/dragdrop.js b/desktop/frontend-static/js/dragdrop.js deleted file mode 100644 index 2c56e27..0000000 --- a/desktop/frontend-static/js/dragdrop.js +++ /dev/null @@ -1,329 +0,0 @@ -/** - * Drag & Drop module for ObsiGate sidebar tree. - * - * Allows drag-and-drop of tree items (files and directories) onto - * target directories or vault roots to reorganize the vault. - * - * Usage: import { initDragDrop } from './dragdrop.js'; - * initDragDrop() after the vault tree is ready. - */ - -import { api } from './auth.js'; -import { showToast } from './ui.js'; -import { refreshSidebarTreePreservingState } from './sidebar.js'; - -// --------------------------------------------------------------------------- -// State -// --------------------------------------------------------------------------- - -/** Currently dragged item: { vault, path, type, element } */ -let dragState = null; - -// --------------------------------------------------------------------------- -// CSS classes applied during drag operations -// --------------------------------------------------------------------------- - -const DRAG_OVER_CLASS = 'drag-over'; -const DRAG_SOURCE_CLASS = 'drag-source'; -const DRAG_VALID_TARGET_CLASS = 'drag-valid-target'; - -// --------------------------------------------------------------------------- -// Helpers -// --------------------------------------------------------------------------- - -/** - * Walk up the DOM to find the closest ancestor matching the selector. - */ -function closest(selector, el) { - while (el && el !== document) { - if (el.matches && el.matches(selector)) return el; - el = el.parentNode; - } - return null; -} - -/** - * Determine if an element is a valid drop target (directory or vault root). - * Returns { vault, targetDir } or null. - */ -function getDropTarget(el) { - // Directory tree item - const dirItem = closest('.tree-item[data-path]', el); - if (dirItem) { - // Only directories are valid targets - const icon = dirItem.querySelector('[data-lucide]'); - const isDir = icon && (icon.getAttribute('data-lucide') === 'folder' - || icon.getAttribute('data-lucide') === 'chevron-right' - || icon.getAttribute('data-lucide') === 'chevron-down'); - // Heuristic: if the tree item has a child container sibling, it's a directory - const hasChildren = dirItem.nextElementSibling - && dirItem.nextElementSibling.classList.contains('tree-children'); - if (isDir || hasChildren) { - return { - vault: dirItem.dataset.vault, - targetDir: dirItem.dataset.path, - }; - } - return null; - } - - // Vault item (root of a vault) - const vaultItem = closest('.tree-item.vault-item[data-vault]', el); - if (vaultItem) { - return { - vault: vaultItem.dataset.vault, - targetDir: '', // empty = vault root - }; - } - - return null; -} - -/** - * Highlight drop target and its parent chain. - */ -function highlightDropTarget(el) { - const target = getDropTarget(el); - if (!target) return; - - if (target.targetDir) { - // Highlight the directory - const dirEl = document.querySelector( - `.tree-item[data-vault="${CSS.escape(target.vault)}"][data-path="${CSS.escape(target.targetDir)}"]` - ); - if (dirEl) dirEl.classList.add(DRAG_OVER_CLASS); - } else { - // Highlight the vault - const vaultEl = document.querySelector(`.tree-item.vault-item[data-vault="${CSS.escape(target.vault)}"]`); - if (vaultEl) vaultEl.classList.add(DRAG_OVER_CLASS); - } -} - -/** - * Remove all drop target highlights. - */ -function clearAllHighlights() { - document.querySelectorAll(`.${DRAG_OVER_CLASS}`).forEach(el => el.classList.remove(DRAG_OVER_CLASS)); -} - -/** - * Check if the source item is being dropped on itself or inside itself. - */ -function isInvalidDrop(source, target) { - if (source.vault !== target.vault) return true; // cross-vault not supported - if (!target.targetDir) { - // Target is vault root — check if source is already at root - const sourceParent = source.path.includes('/') - ? source.path.substring(0, source.path.lastIndexOf('/')) - : ''; - return sourceParent === ''; - } - // Can't drop a directory into itself or its children - if (source.type === 'directory') { - if (source.path === target.targetDir) return true; // dropping on itself - if (target.targetDir.startsWith(source.path + '/')) return true; // dropping into a child - } - // Check if source is already in this directory - const sourceParent = source.path.includes('/') - ? source.path.substring(0, source.path.lastIndexOf('/')) - : ''; - if (sourceParent === target.targetDir) return true; // same directory - return false; -} - -// --------------------------------------------------------------------------- -// Event handlers -// --------------------------------------------------------------------------- - -function onDragStart(e) { - const treeItem = closest('.tree-item', e.target); - if (!treeItem) return; - - // Don't allow dragging vault items themselves - if (treeItem.classList.contains('vault-item')) return; - - const vault = treeItem.dataset.vault; - const path = treeItem.dataset.path; - if (!vault || path === undefined) return; - - // Determine type: directory or file - const hasChildren = treeItem.nextElementSibling - && treeItem.nextElementSibling.classList.contains('tree-children'); - const type = hasChildren ? 'directory' : 'file'; - - dragState = { vault, path, type, element: treeItem }; - - // Set drag data and visual feedback - e.dataTransfer.effectAllowed = 'move'; - e.dataTransfer.setData('text/plain', path); - - // Visual: reduce opacity of source - treeItem.classList.add(DRAG_SOURCE_CLASS); - - // Add valid-target indicator to all directories and vaults - setTimeout(() => { - document.querySelectorAll('.tree-item').forEach(item => { - if (item === treeItem) return; - if (item.classList.contains('vault-item')) { - item.classList.add(DRAG_VALID_TARGET_CLASS); - } else { - const icon = item.querySelector('[data-lucide]'); - const hasChildContainer = item.nextElementSibling - && item.nextElementSibling.classList.contains('tree-children'); - if (icon && (icon.getAttribute('data-lucide') === 'folder' || hasChildContainer)) { - item.classList.add(DRAG_VALID_TARGET_CLASS); - } - } - }); - }, 0); -} - -function onDragOver(e) { - if (!dragState) return; - e.preventDefault(); // Required to allow drop - e.dataTransfer.dropEffect = 'move'; - - clearAllHighlights(); - - const target = getDropTarget(e.target); - if (!target || isInvalidDrop(dragState, target)) { - e.dataTransfer.dropEffect = 'none'; - return; - } - - highlightDropTarget(e.target); -} - -function onDragLeave(e) { - // Only clear when actually leaving the container, not entering a child - const container = document.getElementById('vault-tree'); - if (!container) return; - // Use a small delay to avoid flickering when moving between children - clearAllHighlights(); -} - -function onDragEnd() { - clearAllHighlights(); - - // Remove drag source visual - if (dragState && dragState.element) { - dragState.element.classList.remove(DRAG_SOURCE_CLASS); - } - - // Remove valid-target indicators - document.querySelectorAll(`.${DRAG_VALID_TARGET_CLASS}`).forEach(el => { - el.classList.remove(DRAG_VALID_TARGET_CLASS); - }); - - dragState = null; -} - -async function onDrop(e) { - e.preventDefault(); - e.stopPropagation(); - - if (!dragState) return; - - const target = getDropTarget(e.target); - if (!target || isInvalidDrop(dragState, target)) { - onDragEnd(); - return; - } - - const { vault, path, type } = dragState; - const { vault: targetVault, targetDir } = target; - - // Don't move if source and target are the same vault - if (vault !== targetVault) { - showToast(t('dragdrop.cross_vault_unsupported'), 'error'); - onDragEnd(); - return; - } - - // Save drag state before cleanup - const savedState = { ...dragState }; - - // Clean up visual state immediately - onDragEnd(); - - // Call API - try { - const response = await api(`/api/move/${encodeURIComponent(vault)}`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - source_path: path, - destination_dir: targetDir, - }), - }); - - if (response && response.success) { - showToast(`Moved ${type} to ${targetDir || 'vault root'}`, 'success'); - // Refresh the tree preserving expanded state - await refreshSidebarTreePreservingState(); - } else { - showToast(t('dragdrop.move_failed'), 'error'); - } - } catch (err) { - console.error('Drag & drop move failed:', err); - const detail = err?.detail || err?.message || 'Unknown error'; - showToast(`Move failed: ${detail}`, 'error'); - // Refresh anyway in case the filesystem state changed - try { await refreshSidebarTreePreservingState(); } catch (_) { /* ignore */ } - } -} - -// --------------------------------------------------------------------------- -// Initialization -// --------------------------------------------------------------------------- - -/** - * Attach drag-and-drop event listeners to the vault tree container. - * Uses event delegation on the #vault-tree element. - */ -export function initDragDrop() { - const container = document.getElementById('vault-tree'); - if (!container) { - console.warn('DragDrop: vault-tree container not found'); - return; - } - - // Remove previous listeners if any (idempotent) - container.removeEventListener('dragstart', onDragStart); - container.removeEventListener('dragover', onDragOver); - container.removeEventListener('dragleave', onDragLeave); - container.removeEventListener('dragend', onDragEnd); - container.removeEventListener('drop', onDrop); - - // Attach listeners with delegation - container.addEventListener('dragstart', onDragStart); - container.addEventListener('dragover', onDragOver); - container.addEventListener('dragleave', onDragLeave); - container.addEventListener('dragend', onDragEnd); - container.addEventListener('drop', onDrop); - - // Make all existing tree items draggable - makeAllDraggable(); - - // Re-apply draggable after any DOM mutation in the tree - const observer = new MutationObserver(() => { - makeAllDraggable(); - }); - observer.observe(container, { childList: true, subtree: true }); -} - -/** - * Make all tree items (files and directories) draggable. - * Vault items themselves are NOT draggable. - */ -function makeAllDraggable() { - const container = document.getElementById('vault-tree'); - if (!container) return; - - container.querySelectorAll('.tree-item').forEach(item => { - if (item.classList.contains('vault-item')) return; - if (!item.hasAttribute('draggable')) { - item.setAttribute('draggable', 'true'); - } - }); -} diff --git a/desktop/frontend-static/js/graph.js b/desktop/frontend-static/js/graph.js deleted file mode 100644 index 3ba24c0..0000000 --- a/desktop/frontend-static/js/graph.js +++ /dev/null @@ -1,949 +0,0 @@ -/* ObsiGate — Graph View: interactive file/folder relationship visualization. - Phase 2: theme colors, tooltips, depth slider, full-vault, search, backlinks. */ -import { api } from './auth.js'; -import { t } from './i18n.js'; -import { safeCreateIcons } from './utils.js'; -import { openFile } from './viewer.js'; - -// --------------------------------------------------------------------------- -// Theme-aware color helpers -// --------------------------------------------------------------------------- -function _cssVar(name, fallback) { - return getComputedStyle(document.body).getPropertyValue(name).trim() || fallback; -} - -const COLORS = { - get bg() { return _cssVar('--bg-primary', '#1e1e1e'); }, - get text() { return _cssVar('--text-primary', '#ddd'); }, - get accent() { return _cssVar('--accent-color', '#2563eb'); }, - get muted() { return _cssVar('--text-muted', '#888'); }, - get border() { return _cssVar('--border-color', '#333'); }, - dir: '#5b9bd5', - md: '#70ad47', - other: '#999', - vault: '#ffc000', - backlink: '#e74c3c', - highlight: '#ff6b6b', -}; - -// --------------------------------------------------------------------------- -// GraphViewManager -// --------------------------------------------------------------------------- -export const GraphViewManager = { - _canvas: null, - _ctx: null, - _nodes: [], - _edges: [], - _offsetX: 0, - _offsetY: 0, - _zoom: 1, - _dragging: false, - _dragNode: null, - _panning: false, - _panStartX: 0, - _panStartY: 0, - _animFrame: null, - _vault: null, - _path: null, - _nodePositions: {}, - _width: 0, - _height: 0, - _scope: 'directory', - _depth: 1, - _searchTerm: '', - _tagFilter: '', - _hoveredNode: null, - _infoPanel: null, - _infoContent: null, - _previewPanel: null, - _previewContent: null, - _previewCache: {}, - _previewPending: null, - _ctrlHoverNode: null, - _navHistory: [], - _navIndex: -1, - - async open(vault, path, type) { - // Push current state to history before navigating (unless navigating via back/fwd) - if (this._vault && !this._navNavigating) { - this._pushHistory(this._vault, this._path || ''); - } - this._navNavigating = false; - - this._vault = vault; - this._path = path; - - const modal = document.getElementById('graph-modal'); - const title = document.getElementById('graph-title'); - const statusEl = document.getElementById('graph-status'); - const canvas = document.getElementById('graph-canvas'); - const depthSlider = document.getElementById('graph-depth'); - - if (!modal || !canvas) return; - - this._infoPanel = document.getElementById('graph-info-panel'); - this._infoContent = document.getElementById('graph-info-content'); - this._previewPanel = document.getElementById('graph-preview-panel'); - this._previewContent = document.getElementById('graph-preview-content'); - this._depth = depthSlider ? parseInt(depthSlider.value) : 1; - this._scope = 'directory'; - - title.textContent = t('graph.title', { vault, path: path ? '/' + path : '' }); - statusEl.textContent = t('graph.loading'); - modal.classList.add('active'); - - this._canvas = canvas; - this._ctx = canvas.getContext('2d'); - this._resetView(); - - await this._fetchAndRender(); - this._updateNavButtons(); - safeCreateIcons(); - }, - - _cache: {}, - _cacheKey: '', - - _getCacheKey() { - return `${this._vault}|${this._path}|${this._depth}|${this._scope}|${this._searchTerm}|${this._tagFilter}`; - }, - - async _fetchAndRender() { - const statusEl = document.getElementById('graph-status'); - if (!statusEl) return; - - const cacheKey = this._getCacheKey(); - - // Use cache if same parameters - if (this._cache[cacheKey]) { - const cached = this._cache[cacheKey]; - this._nodes = cached.nodes; - this._edges = cached.edges; - this._scope = cached.scope; - const scopeLabel = this._scope === 'full' ? t('graph.scope_full') : t('graph.scope_directory'); - statusEl.textContent = `${t('graph.nodes_count', { count: this._nodes.length })}, ${t('graph.edges_count', { count: this._edges.length })} · ${scopeLabel} · ${t('graph.depth_label', { depth: this._depth })} ${t('graph.cache_label')}`; - this._initLayout(); - this._startRender(); - return; - } - - const params = new URLSearchParams(); - if (this._path) params.set('path', this._path); - params.set('depth', String(this._depth)); - params.set('scope', this._scope); - if (this._tagFilter) params.set('tag', this._tagFilter); - - try { - const data = await api( - `/api/graph/${encodeURIComponent(this._vault)}?${params.toString()}` - ); - this._nodes = data.nodes || []; - this._edges = data.edges || []; - this._scope = data.scope || 'directory'; - - // Cache the result - this._cache[cacheKey] = { - nodes: this._nodes, - edges: this._edges, - scope: this._scope, - }; - this._cacheKey = cacheKey; - - const scopeLabel = this._scope === 'full' ? t('graph.scope_full') : t('graph.scope_directory'); - statusEl.textContent = `${t('graph.nodes_count', { count: this._nodes.length })}, ${t('graph.edges_count', { count: this._edges.length })} · ${scopeLabel} · ${t('graph.depth_label', { depth: this._depth })}`; - this._initLayout(); - this._startRender(); - } catch (err) { - statusEl.textContent = t('graph.error_loading'); - console.error('Graph error:', err); - } - }, - - reload() { - // Called when depth slider or full-vault button changes - this._resetView(); - this._fetchAndRender(); - }, - - setDepth(depth) { - this._depth = depth; - this.reload(); - }, - - toggleScope() { - this._scope = this._scope === 'full' ? 'directory' : 'full'; - const btn = document.getElementById('graph-full-vault'); - if (btn) btn.textContent = this._scope === 'full' ? t('graph.btn_directory') : t('graph.btn_full'); - this.reload(); - }, - - setSearch(term) { - this._searchTerm = term; - // Parse unified search: #tag → tag filter, otherwise → node search - if (term.startsWith('#')) { - const tag = term.substring(1).trim(); - if (tag && tag !== this._tagFilter) { - this._tagFilter = tag; - this.reload(); - } else if (!tag && this._tagFilter) { - this._tagFilter = ''; - this.reload(); - } - } else { - if (this._tagFilter) { - this._tagFilter = ''; - this.reload(); - return; - } - if (term && term.length >= 2) { - this.reload(); - } else if (!term && this._searchTerm !== term) { - this.reload(); - } - } - }, - - close() { - const modal = document.getElementById('graph-modal'); - if (modal) modal.classList.remove('active'); - this._navHistory = []; - this._navIndex = -1; - if (this._animFrame) { - cancelAnimationFrame(this._animFrame); - this._animFrame = null; - } - this._hideTooltip(); - }, - - _resetView() { - this._offsetX = 0; - this._offsetY = 0; - this._zoom = 1; - this._nodePositions = {}; - }, - - _pushHistory(vault, path) { - // Truncate forward history if we navigated back then took a new path - if (this._navIndex < this._navHistory.length - 1) { - this._navHistory = this._navHistory.slice(0, this._navIndex + 1); - } - this._navHistory.push({ vault, path }); - this._navIndex = this._navHistory.length - 1; - // Keep max 50 entries - if (this._navHistory.length > 50) { - this._navHistory.shift(); - this._navIndex--; - } - this._updateNavButtons(); - }, - - _updateNavButtons() { - const backBtn = document.getElementById('graph-nav-back'); - const fwdBtn = document.getElementById('graph-nav-fwd'); - const upBtn = document.getElementById('graph-nav-up'); - if (backBtn) { - backBtn.disabled = this._navIndex <= 0; - backBtn.style.opacity = this._navIndex > 0 ? '1' : '0.3'; - } - if (fwdBtn) { - fwdBtn.disabled = this._navIndex >= this._navHistory.length - 1; - fwdBtn.style.opacity = this._navIndex < this._navHistory.length - 1 ? '1' : '0.3'; - } - // Show "↑ Parent" if we have a path (subfolder) or history - if (upBtn) { - const hasParent = !!(this._path && this._path.includes('/')); - const hasHistory = this._navIndex > 0; - upBtn.style.display = (hasParent || hasHistory) ? '' : 'none'; - } - }, - - goBack() { - if (this._navIndex <= 0) return; - this._navIndex--; - const entry = this._navHistory[this._navIndex]; - this._navNavigating = true; - this.open(entry.vault, entry.path); - }, - - goForward() { - if (this._navIndex >= this._navHistory.length - 1) return; - this._navIndex++; - const entry = this._navHistory[this._navIndex]; - this._navNavigating = true; - this.open(entry.vault, entry.path); - }, - - goUp() { - if (!this._path || !this._path.includes('/')) { - // No subfolder — go to previous history entry - this.goBack(); - return; - } - // Go to parent directory - const parentPath = this._path.split('/').slice(0, -1).join('/'); - this.open(this._vault, parentPath); - }, - - _initLayout() { - const w = this._canvas.parentElement.clientWidth; - const h = this._canvas.parentElement.clientHeight; - this._canvas.width = w * devicePixelRatio; - this._canvas.height = h * devicePixelRatio; - this._canvas.style.width = w + 'px'; - this._canvas.style.height = h + 'px'; - this._width = w; - this._height = h; - this._ctx.setTransform(1, 0, 0, 1, 0, 0); - this._ctx.scale(devicePixelRatio, devicePixelRatio); - - const cx = w / 2; - const cy = h / 2; - const radius = Math.min(w, h) * 0.35; - - this._nodes.forEach((node, i) => { - const angle = (2 * Math.PI * i) / Math.max(this._nodes.length, 1); - this._nodePositions[node.id] = { - x: cx + radius * Math.cos(angle), - y: cy + radius * Math.sin(angle), - vx: 0, - vy: 0, - }; - }); - }, - - _startRender() { - const self = this; - let lastTime = 0; - - const loop = (time) => { - const dt = Math.min((time - lastTime) / 1000, 0.1); - lastTime = time; - self._simulate(dt); - self._draw(); - self._animFrame = requestAnimationFrame(loop); - }; - - this._animFrame = requestAnimationFrame(loop); - }, - - _simulate(dt) { - if (this._dragging || this._dragNode) return; - - const positions = this._nodePositions; - const cx = this._width / 2; - const cy = this._height / 2; - - // Spring forces (edges) — unchanged - for (const edge of this._edges) { - const a = positions[edge.source]; - const b = positions[edge.target]; - if (!a || !b) continue; - - const dx = b.x - a.x; - const dy = b.y - a.y; - const dist = Math.sqrt(dx * dx + dy * dy) || 1; - const targetLen = 80; - const force = (dist - targetLen) * 0.01; - const fx = (dx / dist) * force; - const fy = (dy / dist) * force; - - a.vx += fx; - a.vy += fy; - b.vx -= fx; - b.vy -= fy; - } - - // Repulsion: Barnes-Hut for >200 nodes, naive O(n²) otherwise - if (this._nodes.length > 200) { - this._barnesHutRepulsion(positions); - } else { - this._naiveRepulsion(positions); - } - - // Center gravity - for (const node of this._nodes) { - const p = positions[node.id]; - if (!p) continue; - p.vx += (cx - p.x) * 0.001; - p.vy += (cy - p.y) * 0.001; - } - - // Apply velocities with damping - for (const node of this._nodes) { - const p = positions[node.id]; - if (!p) continue; - p.vx *= 0.9; - p.vy *= 0.9; - p.x += p.vx * dt * 60; - p.y += p.vy * dt * 60; - } - }, - - _naiveRepulsion(positions) { - for (const n1 of this._nodes) { - for (const n2 of this._nodes) { - if (n1.id === n2.id) continue; - const a = positions[n1.id]; - const b = positions[n2.id]; - if (!a || !b) continue; - const dx = b.x - a.x; - const dy = b.y - a.y; - const dist = Math.sqrt(dx * dx + dy * dy) || 1; - const force = 2000 / (dist * dist); - const fx = (dx / dist) * force; - const fy = (dy / dist) * force; - a.vx -= fx; - a.vy -= fy; - } - } - }, - - // Barnes-Hut quadtree for O(n log n) repulsion - _barnesHutRepulsion(positions) { - // Build quadtree - let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity; - for (const node of this._nodes) { - const p = positions[node.id]; - if (!p) continue; - if (p.x < minX) minX = p.x; - if (p.y < minY) minY = p.y; - if (p.x > maxX) maxX = p.x; - if (p.y > maxY) maxY = p.y; - } - const root = this._buildQuadTree(positions, minX, minY, maxX, maxY); - - // Apply forces from quadtree - const theta = 0.9; // Barnes-Hut opening angle - for (const node of this._nodes) { - const p = positions[node.id]; - if (!p) continue; - this._applyQuadTreeForce(root, p, theta); - } - }, - - _buildQuadTree(positions, x0, y0, x1, y1) { - const cx = (x0 + x1) / 2; - const cy = (y0 + y1) / 2; - const cell = { x0, y0, x1, y1, cx, cy, mass: 0, mx: 0, my: 0, children: null }; - - // Collect nodes in this cell - const contained = []; - for (const node of this._nodes) { - const p = positions[node.id]; - if (p && p.x >= x0 && p.x < x1 && p.y >= y0 && p.y < y1) { - contained.push(p); - } - } - - if (contained.length === 0) return cell; - if (contained.length === 1) { - cell.mass = 1; - cell.mx = contained[0].x; - cell.my = contained[0].y; - return cell; - } - - // Subdivide - const midX = cx; - const midY = cy; - cell.children = [ - this._buildQuadTree(positions, x0, y0, midX, midY), // NW - this._buildQuadTree(positions, midX, y0, x1, midY), // NE - this._buildQuadTree(positions, x0, midY, midX, y1), // SW - this._buildQuadTree(positions, midX, midY, x1, y1), // SE - ]; - - // Compute center of mass - let totalMass = 0; - let sumX = 0, sumY = 0; - for (const child of cell.children) { - if (child.mass > 0) { - totalMass += child.mass; - sumX += child.mx * child.mass; - sumY += child.my * child.mass; - } - } - cell.mass = totalMass; - cell.mx = sumX / totalMass; - cell.my = sumY / totalMass; - - return cell; - }, - - _applyQuadTreeForce(cell, p, theta) { - if (cell.mass === 0) return; - - const dx = cell.mx - p.x; - const dy = cell.my - p.y; - const dist = Math.sqrt(dx * dx + dy * dy) || 1; - const size = cell.x1 - cell.x0; - - // If cell is far enough or is a leaf, apply force from center of mass - if (!cell.children || size / dist < theta) { - const force = 2000 * cell.mass / (dist * dist); - const fx = (dx / dist) * force; - const fy = (dy / dist) * force; - p.vx -= fx; - p.vy -= fy; - return; - } - - // Otherwise recurse into children - for (const child of cell.children) { - this._applyQuadTreeForce(child, p, theta); - } - }, - - _draw() { - const ctx = this._ctx; - const w = this._width; - const h = this._height; - - ctx.save(); - ctx.clearRect(0, 0, w, h); - - ctx.translate(this._offsetX, this._offsetY); - ctx.scale(this._zoom, this._zoom); - - // Draw edges - for (const edge of this._edges) { - const a = this._nodePositions[edge.source]; - const b = this._nodePositions[edge.target]; - if (!a || !b) continue; - - ctx.beginPath(); - ctx.moveTo(a.x, a.y); - ctx.lineTo(b.x, b.y); - - if (edge.relation === 'backlink') { - ctx.strokeStyle = COLORS.backlink; - ctx.lineWidth = 1.5; - ctx.setLineDash([3, 3]); - } else if (edge.relation === 'wikilink') { - ctx.strokeStyle = COLORS.accent; - ctx.lineWidth = 2; - ctx.setLineDash([4, 4]); - } else { - ctx.strokeStyle = COLORS.muted; - ctx.lineWidth = 1; - ctx.setLineDash([]); - } - ctx.stroke(); - } - ctx.setLineDash([]); - - // Draw nodes - const searchLower = this._searchTerm.toLowerCase(); - for (const node of this._nodes) { - if (!this._isNodeVisible(node)) continue; - const p = this._nodePositions[node.id]; - if (!p) continue; - - const links = (node.incoming_count || 0) + (node.outgoing_count || 0); - const r = Math.max(5, Math.min(22, 6 + Math.sqrt(Math.max(node.size || 100, links * 200)) / 100)); - - // Highlight if search match - const isHighlighted = searchLower && ( - node.name.toLowerCase().includes(searchLower) || - (node.tags || []).some(t => t.toLowerCase().includes(searchLower)) - ); - - ctx.beginPath(); - ctx.arc(p.x, p.y, r, 0, Math.PI * 2); - - switch (node.type) { - case 'directory': - ctx.fillStyle = COLORS.dir; - break; - case 'file': - ctx.fillStyle = (node.path || '').endsWith('.md') ? COLORS.md : COLORS.other; - break; - case 'vault': - ctx.fillStyle = COLORS.vault; - break; - default: - ctx.fillStyle = COLORS.other; - } - - if (isHighlighted) { - ctx.shadowColor = COLORS.highlight; - ctx.shadowBlur = 12; - } - - ctx.fill(); - - if (isHighlighted) { - ctx.shadowBlur = 0; - ctx.strokeStyle = COLORS.highlight; - ctx.lineWidth = 2.5; - } else { - ctx.strokeStyle = COLORS.bg; - ctx.lineWidth = 1.5; - } - ctx.stroke(); - - // Node label - const label = node.name.length > 20 ? node.name.slice(0, 18) + '...' : node.name; - ctx.font = `${isHighlighted ? 12 : 11} / ${this._zoom}px -apple-system, sans-serif`; - ctx.fillStyle = isHighlighted ? COLORS.highlight : COLORS.text; - ctx.textAlign = 'center'; - ctx.fillText(label, p.x, p.y + r + 12 / this._zoom); - } - - ctx.restore(); - }, - - _getNodeAt(screenX, screenY) { - const x = (screenX - this._offsetX) / this._zoom; - const y = (screenY - this._offsetY) / this._zoom; - - for (const node of this._nodes) { - const p = this._nodePositions[node.id]; - if (!p) continue; - const links = (node.incoming_count || 0) + (node.outgoing_count || 0); - const r = Math.max(5, Math.min(22, 6 + Math.sqrt(Math.max(node.size || 100, links * 200)) / 100)); - const dx = x - p.x; - const dy = y - p.y; - if (dx * dx + dy * dy <= r * r + 100) { - return { node, pos: p }; - } - } - return null; - }, - - _showTooltip(node, screenX, screenY, isPreview) { - if (isPreview) return; // Handled by _showPreviewTooltip - if (!this._infoContent) return; - const cacheKey = `${this._vault}:${node.path}`; - const cached = this._previewCache[cacheKey]; - const meta = cached?.meta; - // Build metadata summary - let metaRows = ''; - if (meta?.frontmatter && Object.keys(meta.frontmatter).length > 0) { - const fm = meta.frontmatter; - const rows = []; - if (fm.auteur) rows.push(`
    ✍️ Auteur ${fm.auteur}
    `); - if (fm.date || fm.creation_date) rows.push(`
    📅 Date ${fm.date || fm.creation_date}
    `); - if (fm.statut) rows.push(`
    📌 Statut ${fm.statut}
    `); - if (fm.catégorie || fm.categorie) rows.push(`
    ${t('graph.category')} ${fm.catégorie || fm.categorie}
    `); - if (fm.publish) rows.push(`
    ✅ ${t('graph.published')}
    `); - if (fm.favoris) rows.push('
    ⭐ ' + t('graph.favorites') + '
    '); - if (rows.length > 0) metaRows = rows.join(''); - } - const tags = (meta?.tags || node.tags || []).slice(0, 6); - const inc = node.incoming_count || 0; - const out = node.outgoing_count || 0; - const typeIcon = node.type === 'directory' ? '📁' : '📄'; - const typeLabel = node.type === 'directory' ? t('graph.type_directory') : (node.path || '').endsWith('.md') ? t('graph.type_markdown') : t('graph.type_file'); - - this._infoContent.innerHTML = ` -
    - ${typeIcon} -
    -
    ${meta?.title || node.name}
    -
    ${node.path}
    -
    -
    -
    - ${typeLabel} - ${inc + out > 0 ? `🔗 ${out}→ · ${inc}←` : ''} -
    - ${metaRows ? `
    ${metaRows}
    ` : ''} - ${tags.length > 0 ? `
    ${tags.map(t => `#${t}`).join('')}
    ` : ''} - ${node.type === 'file' ? '
    ' + t('graph.ctrl_hover_preview') + '
    ' : ''} - `; - this._infoPanel.style.display = 'block'; - }, - - _hideTooltip() { - // Panels are now sticky — only hide via close button - }, - - _showPreviewTooltip(node, preview, screenX, screenY) { - if (!this._previewContent || this._ctrlHoverNode !== node) return; - const cacheKey = `${this._vault}:${node.path}`; - const cached = this._previewCache[cacheKey]; - const meta = cached?.meta; - // Format frontmatter summary - let fmSummary = ''; - if (meta?.frontmatter && Object.keys(meta.frontmatter).length > 0) { - const fm = meta.frontmatter; - const items = []; - if (fm.auteur) items.push(`✍️ ${fm.auteur}`); - if (fm.date || fm.creation_date) items.push(`📅 ${fm.date || fm.creation_date}`); - if (fm.statut) items.push(`📌 ${fm.statut}`); - if (fm.publish) items.push(t('graph.published_badge')); - if (fm.favoris) items.push('⭐ favoris'); - if (items.length > 0) fmSummary = `
    ${items.join(' · ')}
    `; - } - const tags = (meta?.tags || node.tags || []).slice(0, 8); - this._previewContent.innerHTML = ` -
    ${meta?.title || node.name}
    -
    ${node.path}
    - ${fmSummary} - ${tags.length > 0 ? `
    ${tags.map(t => `#${t}`).join('')}
    ` : ''} -
    ${preview}
    - `; - this._previewPanel.style.display = 'block'; - }, - - // --- Advanced controls --- - - _isNodeVisible(node) { - const showDir = document.getElementById('graph-filter-dir')?.checked ?? true; - const showMd = document.getElementById('graph-filter-md')?.checked ?? true; - const showOther = document.getElementById('graph-filter-other')?.checked ?? true; - if (node.type === 'directory') return showDir; - if (node.type === 'file' && (node.path || '').endsWith('.md')) return showMd; - if (node.type === 'file') return showOther; - return true; - }, - - applyTypeFilter() { - // Filters are applied during _draw() — nodes/edges not in visible set are skipped - }, - - exportPNG() { - const link = document.createElement('a'); - link.download = `obsigate-graph-${this._vault}-${Date.now()}.png`; - link.href = this._canvas.toDataURL('image/png'); - link.click(); - }, - - toggleFullscreen() { - const container = this._canvas?.parentElement?.parentElement; // editor-container - if (!container) return; - if (document.fullscreenElement) { - document.exitFullscreen(); - } else { - container.requestFullscreen(); - } - // Re-init layout after fullscreen change - setTimeout(() => this._onResize(), 300); - }, - - focusNode(nodeId) { - const pos = this._nodePositions[nodeId]; - if (!pos) return; - this._offsetX = this._width / 2 - pos.x * this._zoom; - this._offsetY = this._height / 2 - pos.y * this._zoom; - }, - - _onMouseDown(e) { - const rect = this._canvas.getBoundingClientRect(); - const mx = e.clientX - rect.left; - const my = e.clientY - rect.top; - - const hit = this._getNodeAt(mx, my); - if (hit) { - this._dragging = true; - this._dragNode = hit; - this._canvas.style.cursor = 'grabbing'; - } else { - this._panning = true; - this._panStartX = e.clientX - this._offsetX; - this._panStartY = e.clientY - this._offsetY; - this._canvas.style.cursor = 'grabbing'; - } - }, - - _onMouseMove(e) { - const rect = this._canvas.getBoundingClientRect(); - const mx = e.clientX - rect.left; - const my = e.clientY - rect.top; - - if (this._dragging && this._dragNode) { - this._dragNode.pos.x = (mx - this._offsetX) / this._zoom; - this._dragNode.pos.y = (my - this._offsetY) / this._zoom; - this._dragNode.pos.vx = 0; - this._dragNode.pos.vy = 0; - } else if (this._panning) { - this._offsetX = e.clientX - this._panStartX; - this._offsetY = e.clientY - this._panStartY; - } else { - const hit = this._getNodeAt(mx, my); - if (hit) { - this._canvas.style.cursor = 'pointer'; - this._canvas.title = hit.node.type === 'file' - ? `📄 ${hit.node.name} (${t('graph.click_to_open')}${e.ctrlKey ? ', ' + t('graph.ctrl_hover_preview_short') : ''})` - : `📁 ${hit.node.name} (cliquer pour explorer)`; - - // Ctrl+hover: fetch content preview for file nodes - if (e.ctrlKey && hit.node.type === 'file') { - if (this._ctrlHoverNode !== hit.node) { - this._ctrlHoverNode = hit.node; - this._fetchPreview(hit.node, e.clientX, e.clientY); - } - this._showTooltip(hit.node, e.clientX, e.clientY, true); - } else { - this._ctrlHoverNode = null; - this._showTooltip(hit.node, e.clientX, e.clientY, false); - } - } else { - this._canvas.style.cursor = 'grab'; - this._canvas.title = ''; - this._ctrlHoverNode = null; - this._hideTooltip(); - } - } - }, - - async _fetchPreview(node, screenX, screenY) { - const cacheKey = `${this._vault}:${node.path}`; - if (this._previewCache[cacheKey] !== undefined) { - const cached = this._previewCache[cacheKey]; - this._showPreviewTooltip(node, cached.preview, screenX, screenY); - return; - } - // Show loading indicator - this._showPreviewTooltip(node, '' + t('common.loading') + '', screenX, screenY); - try { - const data = await api(`/api/file/${encodeURIComponent(this._vault)}?path=${encodeURIComponent(node.path)}`); - // Strip HTML tags, keep line breaks, limit to 600 chars - const text = (data.html || '').replace(/<[^>]*>/g, '').replace(/\n+/g, '\n').trim(); - const preview = text.substring(0, 600) + (text.length > 600 ? '…' : ''); - // Cache both preview text and full metadata for tooltips - this._previewCache[cacheKey] = { - preview, - meta: { - title: data.title, - frontmatter: data.frontmatter || {}, - tags: data.tags || [], - path: node.path, - } - }; - this._showPreviewTooltip(node, preview, screenX, screenY); - } catch { - this._previewCache[cacheKey] = { preview: '(impossible de charger)', meta: null }; - this._showPreviewTooltip(node, '(impossible de charger le contenu)', screenX, screenY); - } - }, - - _onMouseUp(e) { - if (this._dragging && this._dragNode) { - const node = this._dragNode.node; - this._dragging = false; - this._dragNode = null; - this._canvas.style.cursor = 'grab'; - - if (node.type === 'file') { - this.close(); - openFile(this._vault, node.path); - } else if (node.type === 'directory' || node.type === 'vault') { - this.close(); - this._path = node.path || ''; - this.open(this._vault, this._path, node.type); - } - } - this._panning = false; - }, - - _onWheel(e) { - e.preventDefault(); - const rect = this._canvas.getBoundingClientRect(); - const mx = e.clientX - rect.left; - const my = e.clientY - rect.top; - - const zoomFactor = e.deltaY < 0 ? 1.1 : 0.9; - const newZoom = Math.max(0.2, Math.min(3, this._zoom * zoomFactor)); - - this._offsetX = mx - (mx - this._offsetX) * (newZoom / this._zoom); - this._offsetY = my - (my - this._offsetY) * (newZoom / this._zoom); - this._zoom = newZoom; - }, - - _onResize() { - if (!this._canvas || !this._nodes.length) return; - const w = this._canvas.parentElement.clientWidth; - const h = this._canvas.parentElement.clientHeight; - this._canvas.width = w * devicePixelRatio; - this._canvas.height = h * devicePixelRatio; - this._canvas.style.width = w + 'px'; - this._canvas.style.height = h + 'px'; - this._width = w; - this._height = h; - this._ctx.setTransform(1, 0, 0, 1, 0, 0); - this._ctx.scale(devicePixelRatio, devicePixelRatio); - }, -}; - -// --------------------------------------------------------------------------- -// Init graph view event listeners -// --------------------------------------------------------------------------- -export function initGraphView() { - const gm = GraphViewManager; - const closeBtn = document.getElementById('graph-close'); - const zoomIn = document.getElementById('graph-zoom-in'); - const zoomOut = document.getElementById('graph-zoom-out'); - const reset = document.getElementById('graph-reset'); - const fullVault = document.getElementById('graph-full-vault'); - const depthSlider = document.getElementById('graph-depth'); - const searchInput = document.getElementById('graph-search'); - const modal = document.getElementById('graph-modal'); - const canvas = document.getElementById('graph-canvas'); - - if (closeBtn) closeBtn.addEventListener('click', () => gm.close()); - if (modal) modal.addEventListener('click', (e) => { if (e.target === modal) gm.close(); }); - - // Navigation buttons - const navBack = document.getElementById('graph-nav-back'); - if (navBack) navBack.addEventListener('click', () => gm.goBack()); - const navFwd = document.getElementById('graph-nav-fwd'); - if (navFwd) navFwd.addEventListener('click', () => gm.goForward()); - const navUp = document.getElementById('graph-nav-up'); - if (navUp) navUp.addEventListener('click', () => gm.goUp()); - - if (zoomIn) zoomIn.addEventListener('click', () => { gm._zoom = Math.min(3, gm._zoom * 1.2); }); - if (zoomOut) zoomOut.addEventListener('click', () => { gm._zoom = Math.max(0.2, gm._zoom * 0.8); }); - if (reset) reset.addEventListener('click', () => { gm._offsetX = 0; gm._offsetY = 0; gm._zoom = 1; }); - if (fullVault) fullVault.addEventListener('click', () => gm.toggleScope()); - if (depthSlider) depthSlider.addEventListener('input', () => gm.setDepth(parseInt(depthSlider.value))); - if (searchInput) { - let debounce; - searchInput.addEventListener('input', () => { - clearTimeout(debounce); - debounce = setTimeout(() => gm.setSearch(searchInput.value.trim()), 300); - }); - } - - // Export PNG - const exportBtn = document.getElementById('graph-export'); - if (exportBtn) exportBtn.addEventListener('click', () => gm.exportPNG()); - - // Fullscreen - const fullscreenBtn = document.getElementById('graph-fullscreen'); - if (fullscreenBtn) fullscreenBtn.addEventListener('click', () => gm.toggleFullscreen()); - - // Type filters - ['dir', 'md', 'other'].forEach(type => { - const cb = document.getElementById(`graph-filter-${type}`); - if (cb) cb.addEventListener('change', () => gm.applyTypeFilter()); - }); - - if (canvas) { - canvas.addEventListener('mousedown', (e) => gm._onMouseDown(e)); - canvas.addEventListener('mousemove', (e) => gm._onMouseMove(e)); - canvas.addEventListener('mouseup', (e) => gm._onMouseUp(e)); - canvas.addEventListener('mouseleave', () => { - gm._dragging = false; - gm._dragNode = null; - gm._panning = false; - canvas.style.cursor = 'grab'; - // Panels stay visible until closed via button - }); - canvas.addEventListener('wheel', (e) => gm._onWheel(e), { passive: false }); - window.addEventListener('resize', () => gm._onResize()); - } - - document.addEventListener('keydown', (e) => { - if (modal && modal.classList.contains('active') && e.key === 'Escape') { - gm.close(); - } - }); - - // Close buttons for sticky panels - const infoClose = document.getElementById('graph-info-close'); - if (infoClose) infoClose.addEventListener('click', () => { if (gm._infoPanel) gm._infoPanel.style.display = 'none'; }); - const previewClose = document.getElementById('graph-preview-close'); - if (previewClose) previewClose.addEventListener('click', () => { if (gm._previewPanel) gm._previewPanel.style.display = 'none'; }); -} diff --git a/desktop/frontend-static/js/i18n.js b/desktop/frontend-static/js/i18n.js deleted file mode 100644 index 0e49e4b..0000000 --- a/desktop/frontend-static/js/i18n.js +++ /dev/null @@ -1,193 +0,0 @@ -/* ObsiGate — i18n (internationalisation). - * - * Architecture: - * Flat key→string JSON locale files in /static/locales/{fr,en,...}.json - * Static DOM: data-i18n="key" → textContent - * data-i18n-placeholder="key" → placeholder - * data-i18n-attr:title="key" → title attribute - * data-i18n-html="key" → innerHTML (use sparingly) - * Dynamic JS: import { t } from './i18n.js'; t('key', {param: 'val'}) - * Live reload: setLocale('en') updates every data-i18n element instantly. - * - * Key naming: section.what — lowercase, dot-separated, descriptive. - * e.g. header.search_placeholder button.save error.network - * - * Usage: - * import { t, setLocale, getLocale, initI18n } from './i18n.js'; - * await initI18n(); // early, before any rendering - * el.textContent = t('button.cancel'); // dynamic string - * setLocale('en'); // user switches language - */ - -// ── State ────────────────────────────────────────────────────────────────── -let _currentLocale = 'fr'; -let _strings = {}; // { key: translated_string } -let _fallbackStrings = {}; // FR fallback, loaded once -let _loaded = false; - -// ── Public helpers ───────────────────────────────────────────────────────── - -/** Return the currently active locale code ('fr', 'en', ...). */ -export function getLocale() { - return _currentLocale; -} - -/** Translate a key. If params provided, replace {name} placeholders. - * Falls back: key → French → key itself. Never throws. */ -export function t(key, params) { - let s = _strings[key]; - if (s === undefined) { - s = _fallbackStrings[key]; - if (s === undefined) { - console.warn('obsigate i18n: missing key', key); - s = key; // last resort — show the key so the dev notices - } - } - if (params) { - for (const [k, v] of Object.entries(params)) { - s = s.replace(new RegExp('\\{' + k + '\\}', 'g'), String(v)); - } - } - return s; -} - -// ── Reverse-lookup cache (French text → key) ──────────────────────────── -let _reverseCache = null; - -function _buildReverseCache() { - _reverseCache = {}; - for (const [k, v] of Object.entries(_fallbackStrings)) { - if (k.startsWith('_')) continue; - // Prefer shorter keys when multiple keys map to the same French text - if (!_reverseCache[v] || k.length < _reverseCache[v].length) { - _reverseCache[v] = k; - } - } -} - -/** Translate a French string to the current locale by reverse lookup. - * "Paramètres client sauvegardés" → fr: same, en: "Client settings saved". - * If the string is not found in the FR locale, returns it unchanged. */ -export function tr(frenchText) { - if (!frenchText || _currentLocale === 'fr') return frenchText; - if (!_reverseCache) _buildReverseCache(); - var key = _reverseCache[frenchText]; - return key ? t(key) : frenchText; -} - -/** Change locale and re-translate the entire DOM. - * Persists to localStorage. */ -export async function setLocale(locale) { - locale = locale || 'fr'; - if (!_loaded) { - // Too early — store intent and apply after init - try { localStorage.setItem('obsigate-lang', locale); } catch (e) { /* */ } - return; - } - await _loadLocaleStrings(locale); - _applyDOM(); - document.documentElement.lang = locale; - try { localStorage.setItem('obsigate-lang', locale); } catch (e) { /* */ } -} - -/** Initialise the i18n system. Call once, early, before any rendering. - * Priority: server profile > localStorage > navigator.language > 'fr'. */ -export async function initI18n() { - // 1. Determine locale: server profile > localStorage > navigator.language > 'fr' - let locale = null; - - // Try server-side language preference (survives clear site data) - try { - const resp = await fetch('/api/auth/me', { credentials: 'include' }); - if (resp.ok) { - const user = await resp.json(); - if (user.language === 'en' || user.language === 'fr') { - locale = user.language; - } - } - } catch (e) { /* not logged in or network error — fall through */ } - - // Fall back to localStorage - if (!locale) { - try { locale = localStorage.getItem('obsigate-lang'); } catch (e) { /* */ } - } - - // Fall back to navigator.language - if (!locale) { - const nav = (navigator.language || '').toLowerCase(); - locale = nav.startsWith('fr') ? 'fr' - : nav.startsWith('en') ? 'en' - : 'fr'; - } - - // 2. Load fallback (FR) — always needed - _fallbackStrings = await _fetchLocale('fr'); - - // 3. Load selected locale - await _loadLocaleStrings(locale); - - // 4. Apply to DOM - _applyDOM(); - document.documentElement.lang = locale; - _loaded = true; -} - -// ── Internal ─────────────────────────────────────────────────────────────── - -async function _fetchLocale(locale) { - try { - const resp = await fetch('/static/locales/' + locale + '.json'); - if (!resp.ok) throw new Error('HTTP ' + resp.status); - return await resp.json(); - } catch (err) { - console.warn('obsigate i18n: failed to load locale ' + locale, err); - return {}; - } -} - -async function _loadLocaleStrings(locale) { - _currentLocale = locale; - if (locale === 'fr') { - _strings = _fallbackStrings; - } else { - _strings = await _fetchLocale(locale); - } -} - -// ── Global exports for non-module scripts (legacy app.js) ────────────────── -window.t = t; -window.tr = tr; -window.getLocale = getLocale; -window.setLocale = setLocale; -window.initI18n = initI18n; - -/** Walk the DOM and update every element with a data-i18n* attribute. */ -function _applyDOM() { - // textContent - document.querySelectorAll('[data-i18n]').forEach(function (el) { - const key = el.getAttribute('data-i18n'); - el.textContent = t(key); - }); - - // placeholder - document.querySelectorAll('[data-i18n-placeholder]').forEach(function (el) { - const key = el.getAttribute('data-i18n-placeholder'); - el.setAttribute('placeholder', t(key)); - }); - - // innerHTML (use sparingly — XSS risk if keys ever hold user content) - document.querySelectorAll('[data-i18n-html]').forEach(function (el) { - const key = el.getAttribute('data-i18n-html'); - el.innerHTML = t(key); - }); - - // data-i18n-attr:TITLE → sets any attribute - document.querySelectorAll('[data-i18n-attr]').forEach(function (el) { - const raw = el.getAttribute('data-i18n-attr'); - const colon = raw.indexOf(':'); - if (colon === -1) return; - const attr = raw.substring(0, colon); - const key = raw.substring(colon + 1); - el.setAttribute(attr, t(key)); - }); -} diff --git a/desktop/frontend-static/js/legacy.js b/desktop/frontend-static/js/legacy.js deleted file mode 100644 index ba4e83b..0000000 --- a/desktop/frontend-static/js/legacy.js +++ /dev/null @@ -1,417 +0,0 @@ -/* ObsiGate — Legacy module: remaining functions for the orchestrator - Extracted from the monolithic frontend/app.js IIFE. - Functions already in other modules are re-exported. */ - -import { api } from './auth.js'; -import { state } from './state.js'; -import { escapeHtml, safeCreateIcons } from './utils.js'; -import { TabManager, closeMobileSidebar } from './ui.js'; -import { showProgressBar, hideProgressBar, showWelcome } from './viewer.js'; - -// --- Search imports --- -import { - AutocompleteDropdown, - SearchChips, - SearchHistory, - performAdvancedSearch, -} from './search.js'; - -// --- Dashboard imports --- -import { - DashboardRecentWidget, - DashboardStatsWidget, - DashboardBookmarkWidget, - DashboardSharedWidget, -} from './dashboard.js'; - -// --- Re-exports from modules that already have these functions --- -export { initSidebarTabs, initConfigModal, initHelpModal, initRecentTab, initAboutModal } from './config.js'; -export { initSyncStatus } from './sync.js'; -export { DashboardRecentWidget } from './dashboard.js'; - - -// ========================================================================= -// Helpers -// ========================================================================= - -async function loadVaultSettings() { - try { - const settings = await api("/api/vaults/settings/all"); - state.vaultSettings = settings; - } catch (err) { - console.error("Failed to load vault settings:", err); - state.vaultSettings = {}; - } -} - -// ========================================================================= -// Config helpers (needed by initSearch) -// ========================================================================= - -const _FRONTEND_CONFIG_KEY = "obsigate-perf-config"; - -function _getFrontendConfig() { - try { - return JSON.parse(localStorage.getItem(_FRONTEND_CONFIG_KEY) || "{}"); - } catch { - return {}; - } -} - -function _getEffective(key, fallback) { - const cfg = _getFrontendConfig(); - return cfg[key] !== undefined ? cfg[key] : fallback; -} - -/** Check if user is focused on an input/textarea/contenteditable */ -function _isInputFocused() { - const tag = document.activeElement?.tagName; - if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true; - return document.activeElement?.isContentEditable === true; -} - -// ========================================================================= -// initSearch -// ========================================================================= - -function initSearch() { - const input = document.getElementById("search-input"); - if (!input) return; - const caseBtn = document.getElementById("rb-case"); - const wordBtn = document.getElementById("rb-word"); - const regexBtn = document.getElementById("rb-regex"); - const filterBtn = document.getElementById("search-filter-btn"); - const clearBtn = document.getElementById("search-clear-btn"); - const filterRow = document.getElementById("search-filter-row"); - const prevBtn = document.getElementById("rb-prev"); - const nextBtn = document.getElementById("rb-next"); - const countEl = document.getElementById("rb-count"); - const resultsBar = document.getElementById("results-bar"); - - function _showResultsBar() { if (resultsBar) resultsBar.style.display = 'flex'; } - function _hideResultsBar() { if (resultsBar) resultsBar.style.display = 'none'; } - - function _updateToggleUI() { - if (caseBtn) caseBtn.classList.toggle("active", state.searchCaseSensitive); - if (wordBtn) wordBtn.classList.toggle("active", state.searchWholeWord); - if (regexBtn) regexBtn.classList.toggle("active", state.searchRegex); - if (filterBtn) filterBtn.classList.toggle("active", state.searchFilterVisible); - } - - // Toggle buttons - if (caseBtn) caseBtn.addEventListener("click", () => { state.searchCaseSensitive = !state.searchCaseSensitive; _updateToggleUI(); _research(); }); - if (wordBtn) wordBtn.addEventListener("click", () => { state.searchWholeWord = !state.searchWholeWord; _updateToggleUI(); _research(); }); - if (regexBtn) regexBtn.addEventListener("click", () => { state.searchRegex = !state.searchRegex; _updateToggleUI(); _research(); }); - if (filterBtn) filterBtn.addEventListener("click", () => { state.searchFilterVisible = !state.searchFilterVisible; if (filterRow) filterRow.style.display = state.searchFilterVisible ? "flex" : "none"; _updateToggleUI(); }); - - // Result navigation (up/down arrows + Enter) - let _searchResultIdx = -1; - let _searchResultItems = []; - - function _updateResultHighlight() { - _searchResultItems.forEach((el, i) => { - el.classList.toggle("search-result-active", i === _searchResultIdx); - }); - if (_searchResultIdx >= 0 && _searchResultIdx < _searchResultItems.length) { - _searchResultItems[_searchResultIdx].scrollIntoView({ block: "nearest", behavior: "smooth" }); - } - const countEl = document.getElementById("rb-count"); - if (countEl) countEl.textContent = _searchResultIdx >= 0 ? `${_searchResultIdx + 1}/${_searchResultItems.length}` : `0/${_searchResultItems.length}`; - } - - function _refreshResultItems() { - _searchResultItems = Array.from(document.querySelectorAll(".search-result-item")); - _searchResultIdx = _searchResultItems.length > 0 ? 0 : -1; - _updateResultHighlight(); - if (_searchResultItems.length > 0) _showResultsBar(); else _hideResultsBar(); - } - - window.navigateSearchResults = function(delta) { - _searchResultItems = Array.from(document.querySelectorAll(".search-result-item")); - if (_searchResultItems.length === 0) return; - _searchResultIdx = Math.max(0, Math.min(_searchResultItems.length - 1, _searchResultIdx + delta)); - _updateResultHighlight(); - }; - - if (prevBtn) prevBtn.addEventListener("click", () => navigateSearchResults(-1)); - if (nextBtn) nextBtn.addEventListener("click", () => navigateSearchResults(1)); - - function _research() { - const q = input.value.trim(); - if (q.length >= _getEffective("min_query_length", 2)) { - clearTimeout(state.searchTimeout); - state.searchTimeout = setTimeout(() => { - const vault = document.getElementById("vault-filter").value; - const tagFilter = state.selectedTags.length > 0 ? state.selectedTags.join(",") : null; - state.advancedSearchOffset = 0; - performAdvancedSearch(q, vault, tagFilter); - }, _getEffective("debounce_ms", 300)); - } - } - - // Keyboard shortcuts - document.addEventListener("keydown", (e) => { - if (e.altKey && !e.ctrlKey && !e.metaKey) { - if (e.key === "c" || e.key === "C") { e.preventDefault(); caseBtn.click(); } - else if (e.key === "w" || e.key === "W") { e.preventDefault(); if (wordBtn) wordBtn.click(); } - else if (e.key === "r" || e.key === "R") { e.preventDefault(); if (regexBtn) regexBtn.click(); } - else if (e.key === "f" || e.key === "F") { e.preventDefault(); if (filterBtn) filterBtn.click(); input.focus(); } - } - }); - - // Initialize sub-controllers - AutocompleteDropdown.init(); - SearchChips.init(); - - // Initially hide clear button - if (clearBtn) clearBtn.style.display = "none"; - - // Input handler: autocomplete dropdown only (search triggered on Enter or selection) - input.addEventListener("input", () => { - const hasText = input.value.length > 0; - clearBtn.style.display = hasText ? "flex" : "none"; - - // Show autocomplete dropdown while typing - AutocompleteDropdown.populate(input.value, input.selectionStart); - - // Clear results when input becomes empty - if (!hasText) { - SearchChips.clear(); - showWelcome(); - } - }); - - // Focus handler: show history dropdown - input.addEventListener("focus", () => { - if (input.value.length === 0) { - const historyItems = SearchHistory.filter("").slice(0, 5); - if (historyItems.length > 0) { - AutocompleteDropdown.populate("", 0); - } - } - }); - - // Keyboard navigation in dropdown - input.addEventListener("keydown", (e) => { - if (AutocompleteDropdown.isVisible()) { - if (e.key === "ArrowDown") { - e.preventDefault(); - AutocompleteDropdown.navigateDown(); - } else if (e.key === "ArrowUp") { - e.preventDefault(); - AutocompleteDropdown.navigateUp(); - } else if (e.key === "Enter") { - // First: check dropdown suggestions (higher priority than search results) - if (AutocompleteDropdown.selectActive()) { - e.preventDefault(); - return; - } - // Second: navigate search results if visible - const results = document.querySelectorAll(".search-result-item"); - if (results.length > 0 && _searchResultIdx >= 0) { - const el = results[_searchResultIdx]; - if (el) { - const vault = el.dataset.vault; - const path = el.dataset.path; - if (vault && path) { TabManager.openPreview(vault, path); e.preventDefault(); return; } - } - } - // Third: execute search - AutocompleteDropdown.hide(); - const q = input.value.trim(); - if (q) { - SearchHistory.add(q); - clearTimeout(state.searchTimeout); - state.advancedSearchOffset = 0; - const vault = document.getElementById("vault-filter").value; - const tagFilter = state.selectedTags.length > 0 ? state.selectedTags.join(",") : null; - performAdvancedSearch(q, vault, tagFilter); - } - e.preventDefault(); - } else if (e.key === "Escape") { - AutocompleteDropdown.hide(); - e.stopPropagation(); - } - } else { - // Dropdown not visible: navigate search results or execute search - if (e.key === "ArrowDown") { - if (window.navigateSearchResults) { window.navigateSearchResults(1); e.preventDefault(); } - } else if (e.key === "ArrowUp") { - if (window.navigateSearchResults) { window.navigateSearchResults(-1); e.preventDefault(); } - } else if (e.key === "Enter") { - const q = input.value.trim(); - if (q) { - SearchHistory.add(q); - clearTimeout(state.searchTimeout); - state.advancedSearchOffset = 0; - const vault = document.getElementById("vault-filter").value; - const tagFilter = state.selectedTags.length > 0 ? state.selectedTags.join(",") : null; - performAdvancedSearch(q, vault, tagFilter); - } - e.preventDefault(); - } - } - }); - - clearBtn.addEventListener("click", () => { - input.value = ""; - if (clearBtn) clearBtn.style.display = "none"; - state.searchCaseSensitive = false; - state.searchWholeWord = false; - state.searchRegex = false; - _updateToggleUI(); - _hideResultsBar(); - SearchChips.clear(); - AutocompleteDropdown.hide(); - showWelcome(); - }); - - // Global keyboard shortcuts - document.addEventListener("keydown", (e) => { - // Ctrl+K or Cmd+K: focus search - if ((e.ctrlKey || e.metaKey) && e.key === "k") { - e.preventDefault(); - input.focus(); - input.select(); - } - // "/" key: focus search (when not in an input/textarea) - if (e.key === "/" && !_isInputFocused()) { - e.preventDefault(); - input.focus(); - } - // Escape: blur search input and close dropdown - if (e.key === "Escape" && document.activeElement === input) { - AutocompleteDropdown.hide(); - input.blur(); - } - }); -} - -function goHome() { - const searchInput = document.getElementById("search-input"); - if (searchInput) searchInput.value = ""; - - document.querySelectorAll(".tree-item.active").forEach((el) => el.classList.remove("active")); - - state.currentVault = null; - state.currentPath = null; - state.showingSource = false; - state.cachedRawSource = null; - - closeMobileSidebar(); - showWelcome(); -} - -// ========================================================================= -// loadSavedSearches (needed by showWelcome) -// ========================================================================= - -async function loadSavedSearches() { - const list = document.getElementById("saved-searches-list"); - const empty = document.getElementById("saved-searches-empty"); - if (!list) return; - try { - const searches = await api("/api/saved-searches"); - if (!searches.length) { - list.innerHTML = ""; - if (empty) empty.style.display = ""; - return; - } - if (empty) empty.style.display = "none"; - list.innerHTML = searches.map(s => { - var isDirSearch = (!s.query || s.query.trim() === '') && s.include_paths; - var displayQuery = isDirSearch ? (s.include_paths || 'Dossier') : escapeHtml(s.query); - var typeIcon = isDirSearch - ? '' - : ''; - const badges = []; - if (s.case_sensitive) badges.push('Aa'); - if (s.whole_word) badges.push('wd'); - if (s.regex) badges.push('.*'); - const pathFilters = []; - if (s.include_paths) pathFilters.push(`\u{1F4E5} ${escapeHtml(s.include_paths)}`); - if (s.exclude_paths) pathFilters.push(`\u{1F4E4} ${escapeHtml(s.exclude_paths)}`); - const vaultStr = s.vault && s.vault !== "all" ? `\u{1F4C1} ${escapeHtml(s.vault)}` : ""; - return ` -
    -
    ${displayQuery}
    -
    - ${badges.join("")} ${vaultStr} - ${typeIcon} -
    - ${pathFilters.length ? '
    ' + pathFilters.join(" ") + '
    ' : ""} - -
    - `}).join(""); - // Apply saved filter + init filter bar - if (typeof _applySavedFilter === 'function') _applySavedFilter(); - if (typeof _initSavedFilter === 'function') _initSavedFilter(); - list.querySelectorAll(".saved-search-item").forEach(item => { - item.addEventListener("click", (e) => { - if (e.target.classList.contains("saved-search-delete")) return; - const idx = Array.from(list.children).indexOf(item); - const s = searches[idx]; - if (!s) return; - // Apply the saved search - const input = document.getElementById("search-input"); - if (input) input.value = s.query; - state.searchCaseSensitive = s.case_sensitive || false; - state.searchWholeWord = s.whole_word || false; - state.searchRegex = s.regex || false; - if (typeof _updateToggleUI === "function") _updateToggleUI(); - if (s.include_paths) { - const incl = document.getElementById("search-include-input"); - if (incl) incl.value = s.include_paths; - } - if (s.exclude_paths) { - const excl = document.getElementById("search-exclude-input"); - if (excl) excl.value = s.exclude_paths; - } - // Execute the search - AutocompleteDropdown.hide(); - AutocompleteDropdown._suppressNext = true; - const vault = s.vault || "all"; - if (input) { input.dispatchEvent(new Event("input")); } - clearTimeout(state.searchTimeout); - state.advancedSearchOffset = 0; - performAdvancedSearch(s.query, vault, null); - }); - }); - list.querySelectorAll(".saved-search-delete").forEach(b => b.addEventListener("click", async (e) => { - e.stopPropagation(); - await api(`/api/saved-searches/${b.dataset.id}`, { method: "DELETE" }); - loadSavedSearches(); - })); - safeCreateIcons(); - } catch (err) { /* silently ignore */ } -} - -// ========================================================================= -// initDashboardTabs (needed by showWelcome) -// ========================================================================= - -function initDashboardTabs() { - document.querySelectorAll(".dashboard-tab").forEach(tab => { - // Remove existing listeners by cloning - const newTab = tab.cloneNode(true); - tab.parentNode.replaceChild(newTab, tab); - newTab.addEventListener("click", function() { - document.querySelectorAll(".dashboard-tab").forEach(t => t.classList.remove("active")); - document.querySelectorAll(".dashboard-panel").forEach(p => p.classList.remove("active")); - this.classList.add("active"); - const panel = document.getElementById("dashboard-panel-" + this.dataset.tab); - if (panel) panel.classList.add("active"); - }); - }); -} - -// ========================================================================= -// Exports -// ========================================================================= - -export { - loadVaultSettings, - initSearch, - showWelcome, - goHome, -}; diff --git a/desktop/frontend-static/js/mermaid-viewer.js b/desktop/frontend-static/js/mermaid-viewer.js deleted file mode 100644 index ff4437a..0000000 --- a/desktop/frontend-static/js/mermaid-viewer.js +++ /dev/null @@ -1,845 +0,0 @@ -/** - * Mermaid.js integration for ObsiGate. - * - * Handles initialization, rendering, templates, zoom/pan, - * fullscreen, focus mode, theme sync, and Obsidian compatibility. - * - * Usage: import { initMermaid, renderMermaidBlocks } from './mermaid-viewer.js'; - */ -import { safeCreateIcons } from './utils.js'; - -// --------------------------------------------------------------------------- -// Configuration (#20) -// --------------------------------------------------------------------------- - -var _mermaidReady = false; -var _currentTheme = 'default'; - -export function initMermaid() { - if (typeof mermaid === 'undefined') { - console.warn('[Mermaid] library not loaded'); - return; - } - mermaid.initialize(_getMermaidConfig(_currentTheme === 'dark')); - _mermaidReady = true; -} - -export function updateMermaidTheme(isDark) { - _currentTheme = isDark ? 'dark' : 'default'; - if (_mermaidReady) { - mermaid.initialize(_getMermaidConfig(isDark)); - } - - // Re-render all existing Mermaid containers with the new theme - var containers = document.querySelectorAll('.mermaid-container'); - for (var i = 0; i < containers.length; i++) { - reRenderContainer(containers[i]); - } -} - -// Unified theme config — used by both init and theme toggle -function _getMermaidConfig(isDark) { - return { - startOnLoad: false, - securityLevel: 'strict', - theme: 'base', - fontFamily: 'inherit', - themeVariables: isDark ? DARK_THEME : LIGHT_THEME, - }; -} - -// Dark theme — optimized for readability on dark backgrounds -var DARK_THEME = { - // Flowchart / general shapes - primaryColor: '#1e3a5f', - primaryTextColor: '#c8daf0', - primaryBorderColor: '#4a7ab5', - lineColor: '#5a7a9a', - secondaryColor: '#2a4a6a', - tertiaryColor: '#3a6090', - // Background & containers - background: '#0f1117', - mainBkg: '#1a2030', - nodeBorder: '#4a7ab5', - clusterBkg: '#1a2235', - clusterBorder: '#3a5a80', - titleColor: '#a0c0e0', - edgeLabelBackground: '#1a2d47', - nodeTextColor: '#c8daf0', - // Sequence diagram - actorBkg: '#1e3a5f', - actorBorder: '#4a7ab5', - actorTextColor: '#c8daf0', - actorLineColor: '#4a7ab5', - signalColor: '#c8daf0', - signalTextColor: '#c8daf0', - labelBoxBkgColor: '#1e3a5f', - labelBoxBorderColor: '#4a7ab5', - labelTextColor: '#c8daf0', - loopTextColor: '#c8daf0', - noteBkgColor: '#2a3550', - noteBorderColor: '#4a7ab5', - noteTextColor: '#c8daf0', - activationBkgColor: '#3a5a80', - // Gantt - sectionBkgColor: '#1a2d47', - altSectionBkgColor: '#1e3350', - sectionBkgColor2: '#1a2d47', - taskBkgColor: '#1e3a5f', - taskBorderColor: '#4a7ab5', - taskTextColor: '#c8daf0', - taskTextOutsideColor: '#8aacca', - taskTextLightColor: '#e0e8f0', - gridColor: '#2a3a55', - activeTaskBkgColor: '#2a5a8a', - activeTaskBorderColor: '#6a9ad0', - doneTaskBkgColor: '#1a3a4f', - doneTaskBorderColor: '#3a7a9a', - critBkgColor: '#5a2a3a', - critBorderColor: '#a04050', - todayLineColor: '#4a7ab5', - // Git graph - git0: '#4a7ab5', - git1: '#3a6a9a', - git2: '#5a8ac0', - git3: '#2a5a8a', - git4: '#6a9ad0', - git5: '#3a7aaa', - git6: '#4a8abf', - git7: '#5a9acf', - gitInv0: '#c8daf0', - gitInv1: '#b0c8e0', - gitInv2: '#d0e0f0', - gitInv3: '#a0b8d0', - gitBranchLabel0: '#c8daf0', - gitBranchLabel1: '#b0c8e0', - gitBranchLabel2: '#d0e0f0', - commitLabelColor: '#c8daf0', - commitLabelBackground: '#1e3a5f', - commitLabelFontSize: '11px', - tagLabelColor: '#a0c0e0', - tagLabelBackground: '#1a2d47', - tagLabelBorder: '#4a7ab5', - // Pie chart - pie1: '#1e3a5f', - pie2: '#2a5a8a', - pie3: '#153050', - pie4: '#3a6a9a', - pie5: '#204070', - pie6: '#4a7ab5', - pie7: '#255080', - pie8: '#5a8ac0', - pieTitleTextColor: '#c8daf0', - pieSectionTextColor: '#c8daf0', - pieLegendTextColor: '#a0c0e0', - pieStrokeColor: '#0f1117', - // Class diagram - classText: '#c8daf0', - // State diagram - labelColor: '#c8daf0', - // ER diagram — dark alternating rows for readability - fillType0: '#111d30', - fillType1: '#152238', - fillType2: '#111d30', - fillType3: '#152238', - fillType4: '#111d30', - fillType5: '#152238', - fillType6: '#111d30', - fillType7: '#152238', - entityBorder: '#4a7ab5', - entityBackground: '#0d1520', - attributeEvenColor: '#ffffff', - attributeOddColor: '#c8daf0', - // Timeline — section colors - cScale0: '#1e3a5f', - cScale1: '#2a5a8a', - cScale2: '#153050', - cScale3: '#3a6a9a', - cScale4: '#204070', - cScale5: '#4a7ab5', - cScaleLabel0: '#c8daf0', - cScaleLabel1: '#c8daf0', - cScaleLabel2: '#c8daf0', - cScaleLabel3: '#c8daf0', - cScaleLabel4: '#c8daf0', - cScaleLabel5: '#c8daf0', - // XY Chart — bar and line colors - xyChartBackgroundColor: '#0f1117', - xyChartTitleColor: '#c8daf0', - xyChartXaxisTitleColor: '#8aacca', - xyChartYaxisTitleColor: '#8aacca', - plotColor1: '#1e3a5f', - plotColor2: '#4a7ab5', - plotColor3: '#2a5a8a', - plotColor4: '#5a8ac0', - plotColor5: '#3a6a9a', - plotColor6: '#6a9ad0', - plotColor7: '#153050', - plotColor8: '#204070', - // General text - textColor: '#c8daf0', - fontSize: '14px', -}; - -// Light theme — clean, minimal -var LIGHT_THEME = { - primaryColor: '#f0f0f5', - primaryTextColor: '#1a1a2e', - primaryBorderColor: '#ccc', - lineColor: '#666', - secondaryColor: '#e8e8f0', - tertiaryColor: '#fafafa', - background: '#ffffff', - mainBkg: '#f5f5fa', - nodeBorder: '#ccc', - clusterBkg: '#f0f0f5', - clusterBorder: '#ddd', - titleColor: '#333', - edgeLabelBackground: '#f5f5fa', - nodeTextColor: '#1a1a2e', - fontSize: '14px', -}; - -// --------------------------------------------------------------------------- -// Templates for all diagram types (#22) -// --------------------------------------------------------------------------- - -export var MERMAID_TEMPLATES = { - flowchart: 'flowchart TD\n A[Start] --> B{Decision?}\n B -->|Yes| C[OK]\n B -->|No| D[Cancel]', - sequenceDiagram: 'sequenceDiagram\n Alice->>Bob: Hello\n Bob-->>Alice: Hi!', - classDiagram: 'classDiagram\n class Animal {\n +name: string\n +age: int\n +makeSound()\n }\n class Dog {\n +bark()\n }\n Animal <|-- Dog', - 'stateDiagram-v2': 'stateDiagram-v2\n [*] --> Idle\n Idle --> Running : start\n Running --> Idle : stop\n Running --> [*] : done', - erDiagram: 'erDiagram\n CUSTOMER ||--o{ ORDER : places\n ORDER ||--|{ LINE-ITEM : contains', - journey: 'journey\n title My day\n section Morning\n Wake up: 5: Me\n Breakfast: 3: Me\n section Work\n Code: 5: Me, Cat', - gantt: 'gantt\n title Project Plan\n dateFormat YYYY-MM-DD\n section Design\n Mockups :a1, 2024-01-01, 7d\n section Dev\n Backend :a2, after a1, 14d', - pie: 'pie title Languages\n "Python" : 45\n "JavaScript" : 30\n "Go" : 15\n "Rust" : 10', - gitGraph: 'gitGraph\n commit\n branch feature\n checkout feature\n commit\n checkout main\n merge feature', - requirementDiagram: 'requirementDiagram\n requirement req1 {\n id: 1\n text: System shall do X\n }\n element Component {\n type: package\n }\n Component - satisfies -> req1', - mindmap: 'mindmap\n root((Project))\n Frontend\n HTML\n CSS\n JavaScript\n Backend\n API\n Database', - timeline: 'timeline\n title History\n 2020 : Started\n 2022 : v1.0\n 2024 : v2.0', - quadrantChart: 'quadrantChart\n title Products\n x-axis Low Reach --> High Reach\n y-axis Low Value --> High Value\n quadrant-1 Stars\n quadrant-2 Question Marks\n Product A: [0.8, 0.6]\n Product B: [0.3, 0.8]', - C4Context: 'C4Context\n title System Context\n Person(user, "User")\n System(app, "My App")\n System_Ext(db, "Database")\n Rel(user, app, "Uses")\n Rel(app, db, "Reads/Writes")', - C4Container: 'C4Container\n title Containers\n Container(web, "Web App", "React")\n Container(api, "API", "FastAPI")\n ContainerDb(db, "DB", "PostgreSQL")\n Rel(web, api, "REST")\n Rel(api, db, "SQL")', - C4Component: 'C4Component\n title API Components\n Container_Boundary(api, "API") {\n Component(auth, "Auth Service")\n Component(search, "Search Engine")\n }', - C4Dynamic: 'C4Dynamic\n title Login Flow\n Person(user, "User")\n Container(web, "Web App")\n Container(api, "API")\n Rel(user, web, "POST /login")\n Rel(web, api, "authenticate")', - C4Deployment: 'C4Deployment\n title Deployment\n Deployment_Node(cloud, "Cloud") {\n Container(web, "Web")\n Container(api, "API")\n }', - 'xychart-beta': 'xychart-beta\n title "Sales"\n x-axis [Jan, Feb, Mar, Apr]\n y-axis "Revenue" 0 --> 100\n bar [45, 60, 75, 90]\n line [30, 45, 55, 70]', - 'block-beta': 'block-beta\n columns 3\n A B C\n D E F', - 'sankey-beta': 'sankey-beta\n A, B, 50\n A, C, 30\n B, D, 20\n C, D, 30', -}; - -// --------------------------------------------------------------------------- -// Rendering engine (#21) -// --------------------------------------------------------------------------- - -var _renderCounter = 0; - -export async function renderMermaidBlocks(container) { - if (!_mermaidReady || typeof mermaid === 'undefined') return; - - var blocks = container.querySelectorAll('pre code.language-mermaid, .mermaid-code'); - if (blocks.length === 0) return; - - for (var i = 0; i < blocks.length; i++) { - var codeBlock = blocks[i]; - var originalCode = codeBlock.textContent || codeBlock.innerText || ''; - if (!originalCode.trim()) continue; - - var wrapper = codeBlock.closest('pre') || codeBlock.parentElement; - if (!wrapper) continue; - - // Check if already rendered - if (wrapper.querySelector('.mermaid-rendered')) continue; - - try { - // Preprocess Obsidian syntax before Mermaid parsing (#24) - var code = preprocessObsidian(originalCode); - await mermaid.parse(code); - var id = 'mermaid-' + (++_renderCounter) + '-' + Date.now(); - var result = await mermaid.render(id, code); - - // Extract diagram type from first non-comment, non-empty line - var diagramType = extractDiagramType(code); - - // Build container with header + body - var containerDiv = document.createElement('div'); - containerDiv.className = 'mermaid-container'; - containerDiv.setAttribute('data-mermaid-code', originalCode); - - // Header bar - var header = document.createElement('div'); - header.className = 'mermaid-header'; - header.innerHTML = - '' + escapeHtml(diagramType) + '' + - '
    ' + - '' + - '' + - '' + - '' + - '' + - '' + - '
    ' + - '' + - '' + - '
    ' + - '
    '; - - // Body - var body = document.createElement('div'); - body.className = 'mermaid-body'; - body.innerHTML = - '
    ' + result.svg + '
    ' + - ''; - - containerDiv.appendChild(header); - containerDiv.appendChild(body); - - wrapper.parentNode.replaceChild(containerDiv, wrapper); - - // Wire up header buttons - wireHeaderButtons(containerDiv, originalCode); - setupZoomPan(containerDiv); - setupCodePreviewToggle(containerDiv); - // Patch beta diagram colors for dark mode - if (_currentTheme === 'dark') patchBetaColors(containerDiv, diagramType); - safeCreateIcons(); - } catch (err) { - var errorDiv = document.createElement('div'); - errorDiv.className = 'mermaid-error'; - errorDiv.innerHTML = 'Erreur Mermaid
    ' + escapeHtml(err.message || String(err)); - wrapper.parentNode.replaceChild(errorDiv, wrapper); - } - } -} - -// --------------------------------------------------------------------------- -// Header button wiring -// --------------------------------------------------------------------------- - -function wireHeaderButtons(container, originalCode) { - // Copy SVG - var copySvgBtn = container.querySelector('.mermaid-copy-svg'); - if (copySvgBtn) { - copySvgBtn.addEventListener('click', function() { - copySvgToClipboard(container); - }); - } - - // Copy code - var copyCodeBtn = container.querySelector('.mermaid-copy-code'); - if (copyCodeBtn) { - copyCodeBtn.addEventListener('click', function() { - copyToClipboard(originalCode); - }); - } - - // Download PNG - var downloadBtn = container.querySelector('.mermaid-download'); - if (downloadBtn) { - downloadBtn.addEventListener('click', function() { - exportMermaidPNG(container); - }); - } -} - -// --------------------------------------------------------------------------- -// Code / Preview toggle -// --------------------------------------------------------------------------- - -function setupCodePreviewToggle(container) { - var toggleBtns = container.querySelectorAll('.mermaid-toggle-btn'); - var rendered = container.querySelector('.mermaid-rendered'); - var source = container.querySelector('.mermaid-source'); - var zoomBtns = container.querySelectorAll('.mermaid-zoom-in, .mermaid-zoom-out'); - var fullscreenBtn = container.querySelector('.mermaid-fullscreen'); - - for (var i = 0; i < toggleBtns.length; i++) { - toggleBtns[i].addEventListener('click', function() { - var mode = this.getAttribute('data-mode'); - - // Update active state - for (var j = 0; j < toggleBtns.length; j++) { - toggleBtns[j].classList.remove('active'); - } - this.classList.add('active'); - - if (mode === 'preview') { - rendered.style.display = ''; - source.style.display = 'none'; - // Show zoom/fullscreen buttons in preview mode - for (var k = 0; k < zoomBtns.length; k++) zoomBtns[k].style.display = ''; - if (fullscreenBtn) fullscreenBtn.style.display = ''; - } else { - rendered.style.display = 'none'; - source.style.display = ''; - // Hide zoom/fullscreen in code mode - for (var k = 0; k < zoomBtns.length; k++) zoomBtns[k].style.display = 'none'; - if (fullscreenBtn) fullscreenBtn.style.display = 'none'; - } - }); - } -} - -// --------------------------------------------------------------------------- -// Diagram type extraction -// --------------------------------------------------------------------------- - -function extractDiagramType(code) { - var lines = code.trim().split('\n'); - for (var i = 0; i < lines.length; i++) { - var line = lines[i].trim(); - // Skip comments and empty lines - if (!line || line.indexOf('%%') === 0) continue; - // Return the first meaningful word(s) - var words = line.split(/\s+/); - if (words.length >= 2) { - return words[0] + ' ' + words[1]; - } - return words[0] || 'mermaid'; - } - return 'mermaid'; -} - -// --------------------------------------------------------------------------- -// Re-render a container after theme change -// --------------------------------------------------------------------------- - -async function reRenderContainer(container) { - var code = container.getAttribute('data-mermaid-code'); - if (!code) return; - - var rendered = container.querySelector('.mermaid-rendered'); - if (!rendered) return; - - try { - var id = 'mermaid-' + (++_renderCounter) + '-' + Date.now(); - var result = await mermaid.render(id, preprocessObsidian(code)); - rendered.innerHTML = result.svg; - - // Reset zoom/pan state on the SVG - var svg = rendered.querySelector('svg'); - if (svg) { - svg.style.transform = ''; - svg.style.cursor = 'grab'; - } - // Patch beta diagram colors for dark mode - if (_currentTheme === 'dark') { - var diagramType = extractDiagramType(code); - patchBetaColors(container, diagramType); - } - } catch (err) { - // Keep old rendering on error - console.warn('[Mermaid] Re-render failed:', err.message); - } -} - -// --------------------------------------------------------------------------- -// Patch beta diagram colors for dark mode (inline SVG attributes beat CSS) -// --------------------------------------------------------------------------- - -function patchBetaColors(container, diagramType) { - var svg = container.querySelector('.mermaid-rendered svg'); - if (!svg) return; - - // packet-beta — override white block backgrounds - if (diagramType.indexOf('packet') !== -1) { - var rects = svg.querySelectorAll('rect'); - for (var i = 0; i < rects.length; i++) { - var r = rects[i]; - var fill = r.getAttribute('fill'); - // Only override if the fill is light/white (preserve dark fills) - if (!fill || fill === '#f4f4f4' || fill === '#fff' || fill === '#ffffff' || fill === 'white' || fill === '#e8e8e8') { - r.setAttribute('fill', '#1e3a5f'); - r.setAttribute('stroke', '#4a7ab5'); - } - } - // Text color - var texts = svg.querySelectorAll('text'); - for (var j = 0; j < texts.length; j++) { - var t = texts[j]; - var tfill = t.getAttribute('fill'); - if (!tfill || tfill === '#000' || tfill === '#333' || tfill === 'black') { - t.setAttribute('fill', '#c8daf0'); - } - } - } - - // xychart-beta — override cream bars and orange line - if (diagramType.indexOf('xychart') !== -1) { - var allRects = svg.querySelectorAll('rect'); - for (var k = 0; k < allRects.length; k++) { - var rr = allRects[k]; - var f = rr.getAttribute('fill'); - if (!f || f === '#f4f4f4' || f === '#fff' || f === '#ffffff' || f === 'white' || f.indexOf('cream') !== -1 || f === '#ececec') { - rr.setAttribute('fill', '#1e3a5f'); - rr.setAttribute('stroke', '#4a7ab5'); - } - } - // Line color - var paths = svg.querySelectorAll('path'); - for (var m = 0; m < paths.length; m++) { - var p = paths[m]; - var ps = p.getAttribute('stroke'); - if (!ps || ps === '#ffa500' || ps === 'orange' || ps === '#ff8c00') { - p.setAttribute('stroke', '#6a9ad0'); - } - } - } -} - -// --------------------------------------------------------------------------- -// Zoom & Pan (#27) -// --------------------------------------------------------------------------- - -function setupZoomPan(container) { - var svgWrapper = container.querySelector('.mermaid-rendered'); - if (!svgWrapper) return; - var svg = svgWrapper.querySelector('svg'); - if (!svg) return; - - var scale = 1; - var panX = 0, panY = 0; - var dragging = false, startX, startY; - - svg.style.transformOrigin = '0 0'; - svg.style.cursor = 'grab'; - - function update() { - svg.style.transform = 'translate(' + panX + 'px, ' + panY + 'px) scale(' + scale + ')'; - } - - svg.addEventListener('mousedown', function(e) { - dragging = true; - startX = e.clientX - panX; - startY = e.clientY - panY; - svg.style.cursor = 'grabbing'; - e.preventDefault(); - }); - - document.addEventListener('mousemove', function(e) { - if (!dragging) return; - panX = e.clientX - startX; - panY = e.clientY - startY; - update(); - }); - - document.addEventListener('mouseup', function() { - dragging = false; - if (svg) svg.style.cursor = 'grab'; - }); - - svg.addEventListener('wheel', function(e) { - e.preventDefault(); - var delta = e.deltaY > 0 ? 0.9 : 1.1; - scale = Math.max(0.2, Math.min(5, scale * delta)); - update(); - }, { passive: false }); - - var zoomIn = container.querySelector('.mermaid-zoom-in'); - var zoomOut = container.querySelector('.mermaid-zoom-out'); - if (zoomIn) zoomIn.addEventListener('click', function() { scale = Math.min(5, scale * 1.3); update(); }); - if (zoomOut) zoomOut.addEventListener('click', function() { scale = Math.max(0.2, scale * 0.7); update(); }); - - // Fullscreen (#28) - var fsBtn = container.querySelector('.mermaid-fullscreen'); - if (fsBtn) { - fsBtn.addEventListener('click', function() { - openFullscreen(container); - }); - } -} - -// --------------------------------------------------------------------------- -// Fullscreen mode (#28) — with header bar + full-size diagram -// --------------------------------------------------------------------------- - -function openFullscreen(container) { - var svgWrapper = container.querySelector('.mermaid-rendered'); - var diagramType = container.querySelector('.mermaid-diagram-type'); - var typeLabel = diagramType ? diagramType.textContent : 'mermaid'; - - var overlay = document.createElement('div'); - overlay.className = 'mermaid-fullscreen-overlay'; - - // Fullscreen header bar - overlay.innerHTML = - '
    ' + - '' + escapeHtml(typeLabel) + '' + - '
    ' + - '' + - '' + - '' + - '' + - '' + - '' + - '
    ' + - '
    ' + - '
    '; - - var content = overlay.querySelector('.mermaid-fullscreen-content'); - content.innerHTML = svgWrapper.innerHTML; - var svg = content.querySelector('svg'); - if (svg) { - svg.style.cursor = 'default'; - } - - document.body.appendChild(overlay); - - // Fullscreen zoom - var fsScale = 1, fsPanX = 0, fsPanY = 0, fsDragging = false, fsStartX, fsStartY; - if (svg) { - svg.style.transformOrigin = '0 0'; - function fsUpdate() { - svg.style.transform = 'translate(' + fsPanX + 'px, ' + fsPanY + 'px) scale(' + fsScale + ')'; - } - - svg.addEventListener('mousedown', function(e) { - fsDragging = true; - fsStartX = e.clientX - fsPanX; - fsStartY = e.clientY - fsPanY; - svg.style.cursor = 'grabbing'; - e.preventDefault(); - }); - - document.addEventListener('mousemove', function(e) { - if (!fsDragging) return; - fsPanX = e.clientX - fsStartX; - fsPanY = e.clientY - fsStartY; - fsUpdate(); - }); - - document.addEventListener('mouseup', function() { - fsDragging = false; - if (svg) svg.style.cursor = 'grab'; - }); - - svg.addEventListener('wheel', function(e) { - e.preventDefault(); - var delta = e.deltaY > 0 ? 0.9 : 1.1; - fsScale = Math.max(0.2, Math.min(5, fsScale * delta)); - fsUpdate(); - }, { passive: false }); - - var fsZoomIn = overlay.querySelector('.mermaid-fs-zoom-in'); - var fsZoomOut = overlay.querySelector('.mermaid-fs-zoom-out'); - if (fsZoomIn) fsZoomIn.addEventListener('click', function() { fsScale = Math.min(5, fsScale * 1.3); fsUpdate(); }); - if (fsZoomOut) fsZoomOut.addEventListener('click', function() { fsScale = Math.max(0.2, fsScale * 0.7); fsUpdate(); }); - } - - // Copy SVG in fullscreen - var fsCopySvg = overlay.querySelector('.mermaid-fs-copy-svg'); - if (fsCopySvg) { - fsCopySvg.addEventListener('click', function() { - copySvgFromElement(content); - }); - } - - // Copy code in fullscreen - var fsCopyCode = overlay.querySelector('.mermaid-fs-copy-code'); - if (fsCopyCode) { - fsCopyCode.addEventListener('click', function() { - var code = container.getAttribute('data-mermaid-code') || ''; - copyToClipboard(code); - }); - } - - // Download PNG in fullscreen - var fsDownload = overlay.querySelector('.mermaid-fs-download'); - if (fsDownload) { - fsDownload.addEventListener('click', function() { - exportMermaidPNGFromElement(svg); - }); - } - - safeCreateIcons(); - - function close() { - overlay.remove(); - document.removeEventListener('keydown', escHandler); - } - - var escHandler = function(e) { - if (e.key === 'Escape') close(); - }; - document.addEventListener('keydown', escHandler); - - overlay.addEventListener('click', function(e) { - if (e.target === overlay) close(); - }); - overlay.querySelector('.mermaid-fs-close').addEventListener('click', close); -} - -// --------------------------------------------------------------------------- -// Copy SVG to clipboard -// --------------------------------------------------------------------------- - -function copySvgToClipboard(container) { - copySvgFromElement(container.querySelector('.mermaid-rendered')); -} - -function copySvgFromElement(el) { - if (!el) return; - var svg = el.querySelector('svg'); - if (!svg) return; - var data = new XMLSerializer().serializeToString(svg); - copyToClipboard(data); -} - -function fallbackCopy(text) { - var textarea = document.createElement('textarea'); - textarea.value = text; - textarea.style.position = 'fixed'; - textarea.style.opacity = '0'; - document.body.appendChild(textarea); - textarea.select(); - try { document.execCommand('copy'); } catch (e) {} - document.body.removeChild(textarea); -} - -// --------------------------------------------------------------------------- -// Export SVG/PNG (#24) -// --------------------------------------------------------------------------- - -export function exportMermaidSVG(container) { - var svg = container.querySelector('.mermaid-rendered svg'); - if (!svg) return; - var data = new XMLSerializer().serializeToString(svg); - var blob = new Blob([data], { type: 'image/svg+xml' }); - downloadBlob(blob, 'diagram.svg'); -} - -export function exportMermaidPNG(container) { - var svg = container.querySelector('.mermaid-rendered svg'); - exportMermaidPNGFromElement(svg); -} - -function exportMermaidPNGFromElement(svg) { - if (!svg) return; - var data = new XMLSerializer().serializeToString(svg); - var canvas = document.createElement('canvas'); - var ctx = canvas.getContext('2d'); - var img = new Image(); - var blob = new Blob([data], { type: 'image/svg+xml' }); - var url = URL.createObjectURL(blob); - - img.onload = function() { - canvas.width = img.width * 2; - canvas.height = img.height * 2; - ctx.scale(2, 2); - ctx.drawImage(img, 0, 0); - URL.revokeObjectURL(url); - canvas.toBlob(function(pngBlob) { - downloadBlob(pngBlob, 'diagram.png'); - }, 'image/png'); - }; - img.src = url; -} - -function downloadBlob(blob, filename) { - var a = document.createElement('a'); - a.href = URL.createObjectURL(blob); - a.download = filename; - a.click(); - URL.revokeObjectURL(a.href); -} - -// --------------------------------------------------------------------------- -// Copy text to clipboard -// --------------------------------------------------------------------------- - -function copyToClipboard(text) { - if (navigator.clipboard && navigator.clipboard.writeText) { - navigator.clipboard.writeText(text).catch(function() { - fallbackCopy(text); - }); - } else { - fallbackCopy(text); - } -} - -// --------------------------------------------------------------------------- -// Focus mode (#29) — click diagram to enlarge in a side panel -// --------------------------------------------------------------------------- - -var _focusPanel = null; - -export function setupFocusMode() { - document.addEventListener('click', function(e) { - var container = e.target.closest('.mermaid-container'); - if (!container) return; - // Don't trigger focus if clicking header or controls - if (e.target.closest('.mermaid-header') || e.target.closest('button')) return; - - var svgWrapper = container.querySelector('.mermaid-rendered'); - if (!svgWrapper) return; - - if (_focusPanel && _focusPanel.style.display !== 'none') { - updateFocusPanel(svgWrapper); - } else { - showFocusPanel(svgWrapper); - } - }); -} - -function showFocusPanel(svgWrapper) { - if (!_focusPanel) { - _focusPanel = document.createElement('div'); - _focusPanel.className = 'mermaid-focus-panel'; - _focusPanel.innerHTML = - '
    ' + - 'Diagramme' + - '' + - '
    ' + - '
    '; - document.body.appendChild(_focusPanel); - - _focusPanel.querySelector('.mermaid-focus-close').addEventListener('click', function() { - _focusPanel.style.display = 'none'; - }); - } - - _focusPanel.style.display = 'block'; - updateFocusPanel(svgWrapper); - safeCreateIcons(); -} - -function updateFocusPanel(svgWrapper) { - if (!_focusPanel) return; - var content = _focusPanel.querySelector('.mermaid-focus-content'); - content.innerHTML = svgWrapper.innerHTML; - var svg = content.querySelector('svg'); - if (svg) { - svg.style.width = '100%'; - svg.style.height = 'auto'; - svg.style.maxHeight = '80vh'; - } -} - -// --------------------------------------------------------------------------- -// Obsidian compatibility pre-processor (#24) -// --------------------------------------------------------------------------- - -export function preprocessObsidian(code) { - return code - .replace(/!\[\[([^\]]+?)\]\]/g, function(_, m) { - var parts = m.split('|'); - var src = parts[0].trim(); - var width = parts[1] ? parts[1].trim() : null; - if (width && /^\d+$/.test(width)) { - return ''; - } - return ''; - }) - .replace(/\[\[([^\]]+?)\]\]/g, '$1') - .replace(/==([^=]+)==/g, '$1'); -} - -// --------------------------------------------------------------------------- -// Utility -// --------------------------------------------------------------------------- - -function escapeHtml(str) { - var div = document.createElement('div'); - div.textContent = str; - return div.innerHTML; -} diff --git a/desktop/frontend-static/js/mobile-toolbar.js b/desktop/frontend-static/js/mobile-toolbar.js deleted file mode 100644 index b1adc19..0000000 --- a/desktop/frontend-static/js/mobile-toolbar.js +++ /dev/null @@ -1,149 +0,0 @@ -/* ObsiGate — Mobile Bottom Toolbar (Obsidian-style) - Phases 1-5: fixed bar, vault home, file palette, commands, tab switcher */ -import { state } from './state.js'; -import { TabManager } from './ui.js'; - -// ── Open file palette (search files) ── -function openFilePalette() { - import('./palette.js').then(m => { m.open(''); }); -} - -// ── Open command palette ── -function openCommandPalette() { - import('./palette.js').then(m => { m.open('> '); }); -} - -// ── Tab switcher ── -function openTabSwitcher() { - const sheet = document.getElementById('mt-tab-switcher'); - const overlay = document.getElementById('mt-overlay'); - if (!sheet || !overlay) return; - - renderTabList(); - sheet.classList.add('open'); - overlay.classList.add('visible'); -} - -function closeTabSwitcher() { - const sheet = document.getElementById('mt-tab-switcher'); - const overlay = document.getElementById('mt-overlay'); - if (sheet) sheet.classList.remove('open'); - if (overlay) overlay.classList.remove('visible'); -} - -function renderTabList() { - const list = document.getElementById('mt-tab-list'); - if (!list) return; - - const tabs = TabManager._tabs || []; - const activeId = TabManager._activeTabId; - - if (tabs.length === 0) { - list.innerHTML = '
    Aucun fichier ouvert
    '; - return; - } - - list.innerHTML = tabs.map(t => { - const isActive = t.id === activeId; - const icon = t.path.endsWith('.md') ? '📄' : '📝'; - return `
    - ${icon} - ${t.title || t.path.split('/').pop()} - -
    `; - }).join(''); - - list.querySelectorAll('.mt-tab-item').forEach(el => { - el.addEventListener('click', (e) => { - if (e.target.closest('.mt-tab-item-close')) return; - const tabId = el.dataset.tabId; - if (tabId) { - TabManager.activate(tabId); - closeTabSwitcher(); - } - }); - }); - - list.querySelectorAll('.mt-tab-item-close').forEach(btn => { - btn.addEventListener('click', (e) => { - e.stopPropagation(); - const tabId = btn.dataset.close; - if (tabId) { - TabManager.close(tabId); - setTimeout(() => renderTabList(), 100); - } - }); - }); -} - -function updateTabCount() { - const badge = document.getElementById('mt-tab-count'); - if (!badge) return; - const count = (TabManager._tabs || []).length; - if (count > 0) { - badge.style.display = 'flex'; - badge.textContent = count; - } else { - badge.style.display = 'none'; - } -} - -// ── Vault home / sidebar toggle ── -function toggleExplorer() { - const sidebar = document.getElementById('sidebar'); - if (sidebar) { - if (sidebar.classList.contains('mobile-open')) { - sidebar.classList.remove('mobile-open'); - } else { - sidebar.classList.add('mobile-open'); - } - } - if (!state.currentVault && state.allVaults && state.allVaults.length > 0) { - import('./sidebar.js').then(m => { - if (m.setSelectedVaultContext) m.setSelectedVaultContext(state.allVaults[0].name); - }); - } -} - -// ── Init ── -export function initMobileToolbar() { - const explorerBtn = document.getElementById('mt-explorer'); - const searchBtn = document.getElementById('mt-search'); - const paletteBtn = document.getElementById('mt-palette'); - const tabsBtn = document.getElementById('mt-tabs'); - const sheetClose = document.getElementById('mt-sheet-close'); - const closeAll = document.getElementById('mt-close-all'); - const overlay = document.getElementById('mt-overlay'); - - if (explorerBtn) explorerBtn.addEventListener('click', toggleExplorer); - if (searchBtn) searchBtn.addEventListener('click', openFilePalette); - if (paletteBtn) paletteBtn.addEventListener('click', openCommandPalette); - if (tabsBtn) tabsBtn.addEventListener('click', openTabSwitcher); - if (sheetClose) sheetClose.addEventListener('click', closeTabSwitcher); - if (closeAll) closeAll.addEventListener('click', () => { - const tabs = [...(TabManager._tabs || [])]; - tabs.forEach(t => TabManager.close(t.id)); - updateTabCount(); - renderTabList(); - }); - if (overlay) overlay.addEventListener('click', closeTabSwitcher); - - setInterval(updateTabCount, 2000); - updateTabCount(); - - // ── Vault context indicator ── - function updateVaultPill() { - const pill = document.getElementById('vault-context-pill'); - if (!pill) return; - const vaultName = state.selectedContextVault || 'all'; - if (vaultName === 'all') { - pill.textContent = t("mobile.all_vaults"); - } else { - pill.textContent = '📂 ' + vaultName; - } - } - updateVaultPill(); - setInterval(updateVaultPill, 1500); - - window._mtUpdateTabs = updateTabCount; -} diff --git a/desktop/frontend-static/js/offline-db.js b/desktop/frontend-static/js/offline-db.js deleted file mode 100644 index 94edb14..0000000 --- a/desktop/frontend-static/js/offline-db.js +++ /dev/null @@ -1,377 +0,0 @@ -/* ObsiGate — Offline IndexedDB Storage - * Stores: file index, file contents, pending changes queue - * Schema v1: - * files store: { path, vault, title, tags[], snippet, modified, tokens[], weight } - * content store: { key: "vault::path", content: string, modified } - * pending store: { id, vault, path, content, action, timestamp } - */ - -const DB_NAME = 'obsigate-offline'; -const DB_VERSION = 1; - -let _db = null; -let _dbPromise = null; - -export const OfflineDB = { - - async open() { - if (_db) return _db; - if (_dbPromise) return _dbPromise; - - _dbPromise = new Promise((resolve, reject) => { - const req = indexedDB.open(DB_NAME, DB_VERSION); - req.onupgradeneeded = (e) => { - const db = e.target.result; - console.log('[OfflineDB] Upgrading to v' + DB_VERSION); - - // File index store — keyed by composite "vault::path" - if (!db.objectStoreNames.contains('files')) { - const store = db.createObjectStore('files', { keyPath: 'key' }); - store.createIndex('vault', 'vault', { unique: false }); - store.createIndex('modified', 'modified', { unique: false }); - store.createIndex('title', 'title', { unique: false }); - } - - // File contents store — keyed by "vault::path" - if (!db.objectStoreNames.contains('content')) { - db.createObjectStore('content', { keyPath: 'key' }); - } - - // Pending changes queue — auto-increment key - if (!db.objectStoreNames.contains('pending')) { - const store = db.createObjectStore('pending', { keyPath: 'id', autoIncrement: true }); - store.createIndex('timestamp', 'timestamp', { unique: false }); - } - }; - - req.onsuccess = (e) => { - _db = e.target.result; - console.log('[OfflineDB] Database opened'); - resolve(_db); - }; - - req.onerror = () => { - _dbPromise = null; - reject(req.error); - }; - }); - - return _dbPromise; - }, - - /* ── File Index ── */ - - async putFileIndex(file) { - const db = await this.open(); - return new Promise((resolve, reject) => { - const tx = db.transaction('files', 'readwrite'); - const store = tx.objectStore('files'); - const key = file.vault + '::' + file.path; - const doc = { key: key, vault: file.vault, path: file.path, - title: file.title, tags: file.tags || [], snippet: file.snippet || '', - modified: file.modified || '', tokens: file.tokens || [], weight: file.score || 0 }; - store.put(doc); - tx.oncomplete = () => resolve(); - tx.onerror = () => reject(tx.error); - }); - }, - - async putFileIndexBatch(files) { - const db = await this.open(); - return new Promise((resolve, reject) => { - const tx = db.transaction('files', 'readwrite'); - const store = tx.objectStore('files'); - for (const file of files) { - const key = file.vault + '::' + file.path; - store.put({ - key: key, vault: file.vault, path: file.path, - title: file.title, tags: file.tags || [], snippet: file.snippet || '', - modified: file.modified || '', tokens: file.tokens || [], score: file.score || 0 - }); - } - tx.oncomplete = () => resolve(); - tx.onerror = () => reject(tx.error); - }); - }, - - async getFileIndex(vault, path) { - const db = await this.open(); - const key = vault + '::' + path; - return new Promise((resolve) => { - const tx = db.transaction('files', 'readonly'); - const store = tx.objectStore('files'); - const req = store.get(key); - req.onsuccess = () => resolve(req.result || null); - req.onerror = () => resolve(null); - }); - }, - - /* Search in file index — title matching and prefix */ - async searchFileIndex(query, vaultFilter) { - const db = await this.open(); - const lowerQ = query.toLowerCase(); - const words = lowerQ.split(/\s+/).filter(Boolean); - - return new Promise((resolve) => { - const tx = db.transaction('files', 'readonly'); - const store = tx.objectStore('files'); - const results = []; - - store.openCursor().onsuccess = (e) => { - const cursor = e.target.result; - if (!cursor) { - // Sort by relevance: title match > path match > snippet match - results.sort((a, b) => b._score - a._score); - resolve(results.slice(0, 50)); - return; - } - - const doc = cursor.value; - - // Vault filter - if (vaultFilter && vaultFilter !== 'all' && doc.vault !== vaultFilter) { - cursor.continue(); - return; - } - - // Score based on match quality - let score = 0; - const titleLower = doc.title.toLowerCase(); - const pathLower = doc.path.toLowerCase(); - const snippetLower = (doc.snippet || '').toLowerCase(); - - for (const word of words) { - if (titleLower.includes(word)) score += 10; - else if (pathLower.includes(word)) score += 5; - else if (snippetLower.includes(word)) score += 2; - } - - // Full query match bonus - if (titleLower.includes(lowerQ)) score += 5; - if (pathLower === lowerQ) score += 8; - - if (score > 0) { - results.push({ - vault: doc.vault, - path: doc.path, - title: doc.title, - tags: doc.tags, - snippet: doc.snippet, - score: score, - modified: doc.modified, - _score: score - }); - } - - cursor.continue(); - }; - }); - }, - - async getAllFileIndex(vaultFilter) { - const db = await this.open(); - return new Promise((resolve) => { - const tx = db.transaction('files', 'readonly'); - const store = tx.objectStore('files'); - const results = []; - store.openCursor().onsuccess = (e) => { - const cursor = e.target.result; - if (!cursor) { resolve(results); return; } - if (!vaultFilter || vaultFilter === 'all' || cursor.value.vault === vaultFilter) { - results.push(cursor.value); - } - cursor.continue(); - }; - }); - }, - - async clearFileIndex(vaultFilter) { - const db = await this.open(); - return new Promise((resolve) => { - const tx = db.transaction('files', 'readwrite'); - const store = tx.objectStore('files'); - if (!vaultFilter || vaultFilter === 'all') { - store.clear().onsuccess = () => resolve(); - } else { - store.openCursor().onsuccess = (e) => { - const cursor = e.target.result; - if (!cursor) { resolve(); return; } - if (cursor.value.vault === vaultFilter) cursor.delete(); - cursor.continue(); - }; - } - }); - }, - - /* ── File Contents ── */ - - async putFileContent(vault, path, content, modified) { - const db = await this.open(); - return new Promise((resolve, reject) => { - const tx = db.transaction('content', 'readwrite'); - const store = tx.objectStore('content'); - const key = vault + '::' + path; - store.put({ key: key, content: content, modified: modified || '' }); - tx.oncomplete = () => resolve(); - tx.onerror = () => reject(tx.error); - }); - }, - - async getFileContent(vault, path) { - const db = await this.open(); - const key = vault + '::' + path; - return new Promise((resolve) => { - const tx = db.transaction('content', 'readonly'); - const store = tx.objectStore('content'); - const req = store.get(key); - req.onsuccess = () => resolve(req.result || null); - req.onerror = () => resolve(null); - }); - }, - - async removeFileContent(vault, path) { - const db = await this.open(); - return new Promise((resolve) => { - const tx = db.transaction('content', 'readwrite'); - const store = tx.objectStore('content'); - const key = vault + '::' + path; - store.delete(key); - tx.oncomplete = () => resolve(); - }); - }, - - /* ── Pending Changes Queue ── */ - - async addPending(entry) { - const db = await this.open(); - return new Promise((resolve, reject) => { - const tx = db.transaction('pending', 'readwrite'); - const store = tx.objectStore('pending'); - const doc = { - vault: entry.vault, - path: entry.path, - content: entry.content || '', - action: entry.action || 'save', - timestamp: Date.now() - }; - const req = store.add(doc); - req.onsuccess = () => resolve(req.result); - tx.onerror = () => reject(tx.error); - }); - }, - - async getPendingCount() { - const db = await this.open(); - return new Promise((resolve) => { - const tx = db.transaction('pending', 'readonly'); - const store = tx.objectStore('pending'); - store.count().onsuccess = (e) => resolve(e.target.result); - }); - }, - - async getAllPending() { - const db = await this.open(); - return new Promise((resolve) => { - const tx = db.transaction('pending', 'readonly'); - const store = tx.objectStore('pending'); - const results = []; - const index = store.index('timestamp'); - index.openCursor().onsuccess = (e) => { - const cursor = e.target.result; - if (!cursor) { resolve(results); return; } - results.push(cursor.value); - cursor.continue(); - }; - }); - }, - - async clearPending() { - const db = await this.open(); - return new Promise((resolve) => { - const tx = db.transaction('pending', 'readwrite'); - tx.objectStore('pending').clear().onsuccess = () => resolve(); - }); - }, - - async removePendingById(id) { - const db = await this.open(); - return new Promise((resolve) => { - const tx = db.transaction('pending', 'readwrite'); - tx.objectStore('pending').delete(id); - tx.oncomplete = () => resolve(); - }); - }, - - /* ── Stats ── */ - - async getStats() { - const db = await this.open(); - const fileCount = await new Promise(r => { - db.transaction('files','readonly').objectStore('files').count().onsuccess = e => r(e.target.result); - }); - const contentCount = await new Promise(r => { - db.transaction('content','readonly').objectStore('content').count().onsuccess = e => r(e.target.result); - }); - const pendingCount = await this.getPendingCount(); - return { fileCount, contentCount, pendingCount }; - }, - - /* ── Full Sync ── */ - - async syncFileIndex(serverFiles) { - // serverFiles: array of {vault,path,title,tags,snippet,modified,tokens} - await this.clearFileIndex(null); - await this.putFileIndexBatch(serverFiles); - console.log('[OfflineDB] File index synced:', serverFiles.length, 'files'); - }, - - async pruneContentCache(maxEntries) { - maxEntries = maxEntries || 50; - const db = await this.open(); - return new Promise((resolve) => { - const tx = db.transaction('content', 'readwrite'); - const store = tx.objectStore('content'); - const keys = []; - store.openCursor().onsuccess = (e) => { - const cursor = e.target.result; - if (!cursor) { - // Delete oldest if over maxEntries - if (keys.length > maxEntries) { - const toDelete = keys.slice(0, keys.length - maxEntries); - for (const k of toDelete) store.delete(k); - } - resolve(); - return; - } - keys.push(cursor.value.key); - cursor.continue(); - }; - }); - } -}; - -/* ── Network Status ── */ -let _online = navigator.onLine; -let _listeners = []; - -export const NetworkStatus = { - get isOnline() { return _online; }, - - init() { - window.addEventListener('online', () => { - _online = true; - _listeners.forEach(fn => fn(true)); - console.log('[Network] Online'); - }); - window.addEventListener('offline', () => { - _online = false; - _listeners.forEach(fn => fn(false)); - console.log('[Network] Offline'); - }); - }, - - onChange(fn) { - _listeners.push(fn); - return () => { _listeners = _listeners.filter(f => f !== fn); }; - } -}; diff --git a/desktop/frontend-static/js/offline.js b/desktop/frontend-static/js/offline.js deleted file mode 100644 index dddfac5..0000000 --- a/desktop/frontend-static/js/offline.js +++ /dev/null @@ -1,209 +0,0 @@ -/* ObsiGate — Offline Integration Module - * Ties together: IndexedDB, offline search, sync queue, UI indicator - */ -import { OfflineDB, NetworkStatus } from './offline-db.js'; -import { state } from './state.js'; -import { showToast } from './ui.js'; - -/* ── Init ── */ -export async function initOffline() { - NetworkStatus.init(); - - // Open DB early - try { - await OfflineDB.open(); - console.log('[Offline] IndexedDB ready'); - } catch (e) { - console.warn('[Offline] IndexedDB not available:', e); - } - - NetworkStatus.onChange((online) => { - updateOfflineIndicator(); - if (online) { - syncPendingChanges(); - showToast(t('offline.reconnected'), 'info'); - } else { - showToast(t('offline.mode_offline'), 'warning'); - } - }); - - updateOfflineIndicator(); -} - -/* ── UI Indicator ── */ -function updateOfflineIndicator() { - const badge = document.getElementById('offline-badge'); - if (!badge) return; - - if (!NetworkStatus.isOnline) { - // Build or show indicator - badge.innerHTML = replaceLucideIcon(badge, 'wifi-off', - ''); - badge.title = 'Mode hors-ligne'; - badge.style.display = 'flex'; - badge.className = 'header-icon offline-indicator offline'; - - // Add pending count if any - OfflineDB.getPendingCount().then(count => { - if (count > 0) { - const span = badge.querySelector('.offline-pending') || document.createElement('span'); - span.className = 'offline-pending'; - span.textContent = String(count); - if (!badge.contains(span)) badge.appendChild(span); - } - }); - } else { - badge.style.display = 'none'; - badge.className = 'header-icon offline-indicator'; - } -} - -function replaceLucideIcon(container, iconName, html) { - const existing = container.querySelector('i[data-lucide]'); - if (existing && existing.getAttribute('data-lucide') === iconName) return container.innerHTML; - return html; -} - -/* ── Sync File Index from Server ── */ -export async function syncFileIndexFromServer() { - if (!NetworkStatus.isOnline) { - console.log('[Offline] Skipping index sync — offline'); - return; - } - try { - // Use a wildcard query to get recent files and populate offline index - const resp = await fetch('/api/search/advanced?q=**&vault=all&limit=200'); - if (!resp.ok) { - console.warn('[Offline] Index sync failed — API returned', resp.status); - return; - } - const data = await resp.json(); - const files = (data.results || []).map(r => ({ - vault: r.vault, - path: r.path, - title: r.title, - tags: r.tags || [], - snippet: r.snippet || '', - modified: r.modified || '', - tokens: [] - })); - if (files.length > 0) { - await OfflineDB.syncFileIndex(files); - console.log('[Offline] Index synced:', files.length, 'files'); - } - } catch (e) { - console.warn('[Offline] Index sync failed:', e.message); - } -} - -/* ── Cache File When Viewed ── */ -export async function cacheViewedFile(vault, path, content, modified) { - if (!vault || !path) return; - try { - await OfflineDB.putFileContent(vault, path, content, modified); - await OfflineDB.pruneContentCache(50); - } catch (e) { - console.warn('[Offline] Cache file failed:', e); - } -} - -/* ── Offline Search ── */ -export async function searchOffline(query, vaultFilter) { - try { - return await OfflineDB.searchFileIndex(query, vaultFilter || state.currentVault); - } catch (e) { - console.error('[Offline] Search failed:', e); - return []; - } -} - -/* ── Get Cached File ── */ -export async function getCachedFile(vault, path) { - try { - return await OfflineDB.getFileContent(vault, path); - } catch (e) { - return null; - } -} - -/* ── Pending Changes Queue ── */ -let _syncing = false; - -export async function queueOfflineSave(vault, path, content) { - try { - const id = await OfflineDB.addPending({ vault, path, content, action: 'save' }); - updateOfflineIndicator(); - console.log('[Offline] Queued save:', vault, path, 'id=', id); - return id; - } catch (e) { - console.error('[Offline] Queue save failed:', e); - return null; - } -} - -export async function syncPendingChanges() { - if (!NetworkStatus.isOnline || _syncing) return; - _syncing = true; - - try { - const pending = await OfflineDB.getAllPending(); - if (pending.length === 0) { - _syncing = false; - return; - } - - console.log('[Offline] Syncing', pending.length, 'pending changes...'); - - for (const entry of pending) { - try { - const resp = await fetch('/api/file/' + encodeURIComponent(entry.vault) + '/write', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ path: entry.path, content: entry.content }) - }); - - if (resp.ok) { - await OfflineDB.removePendingById(entry.id); - console.log('[Offline] Synced:', entry.vault, entry.path); - } else if (resp.status === 409) { - // Conflict — keep in queue for manual resolution - console.warn('[Offline] Conflict on:', entry.vault, entry.path); - } else { - console.error('[Offline] Sync failed for:', entry.vault, entry.path, resp.status); - } - } catch (e) { - console.error('[Offline] Sync error for:', entry.vault, entry.path, e); - break; // Stop on network error - } - } - - const remaining = await OfflineDB.getPendingCount(); - console.log('[Offline] Sync complete. Remaining:', remaining); - updateOfflineIndicator(); - - if (remaining === 0) { - showToast(t('offline.all_synced'), 'success'); - } else { - showToast(remaining + ' modification(s) en attente de resolution', 'warning'); - } - } finally { - _syncing = false; - } -} - -/* ── Conflict Detection ── */ -export async function checkConflict(vault, path, localModified) { - if (!NetworkStatus.isOnline) return null; - - try { - const resp = await fetch('/api/file/' + encodeURIComponent(vault) + '/info?path=' + encodeURIComponent(path)); - if (!resp.ok) return null; - const data = await resp.json(); - if (data.modified && data.modified !== localModified) { - return { serverModified: data.modified, localModified }; - } - return null; - } catch { - return null; - } -} diff --git a/desktop/frontend-static/js/package.json b/desktop/frontend-static/js/package.json deleted file mode 100644 index 6990891..0000000 --- a/desktop/frontend-static/js/package.json +++ /dev/null @@ -1 +0,0 @@ -{"type": "module"} diff --git a/desktop/frontend-static/js/palette.js b/desktop/frontend-static/js/palette.js deleted file mode 100644 index 177e3e3..0000000 --- a/desktop/frontend-static/js/palette.js +++ /dev/null @@ -1,590 +0,0 @@ -/* ObsiGate — Command Palette (Ctrl+Shift+Espace / Ctrl+Alt+Espace) */ -import { api } from './auth.js'; -import { showToast, toggleTheme, TabManager } from './ui.js'; -import { openEditor } from './utils.js'; -import { state } from './state.js'; -import { t } from './i18n.js'; - -function triggerGoHome() { const e = document.getElementById('header-logo'); if (e) e.click(); } - -function getCurrentFile() { - const id = TabManager._activeTabId; - if (id) { const t = TabManager._tabs.find(x => x.id === id); if (t) return { vault: t.vault, path: t.path }; } - if (state.currentVault && state.currentPath) return { vault: state.currentVault, path: state.currentPath }; - return null; -} - -// ── Query parser: +word = required, -word = exclude, word = required ── -function parseQuery(raw) { - const positive = []; - const negative = []; - const parts = (raw || '').split(/\s+/).filter(Boolean); - for (const p of parts) { - if (p.startsWith('-') && p.length > 1) negative.push(p.slice(1).toLowerCase()); - else if (p.startsWith('+')) positive.push(p.slice(1).toLowerCase()); - else positive.push(p.toLowerCase()); - } - return { positive, negative }; -} - -// ── DOM / state ── -let _overlay = null, _input = null, _results = null, _mode = 'files', _sel = 0, _to = null, _items = []; -let _browse = { action: null, vault: null, path: '' }; -let _browseFilterEl = null, _browseFilter = '', _allItems = []; -let _browseFilterTimer = null; // debounce for global search - -// ── Commands ── (lazy: built on first access so i18n is ready) -let _cmdsCache = null; -function getCMDS() { - if (_cmdsCache) return _cmdsCache; - _cmdsCache = [ - { id:'home', label:t('palette.cmd_back_home'), desc:t('palette.cmd_back_home_desc'), cat:'Navigation', act:()=>{close();triggerGoHome();} }, - { id:'edit-current', label:'✏️ '+t('editor.edit'), desc:t('editor.edit_current_desc'), cat:'Fichiers', act:()=>{close();const f=getCurrentFile();if(f)openEditor(f.vault,f.path);else showToast(t('toast.no_open_file'),'error');} }, - { id:'popout', label:'🪟 Pop-out', desc:t('palette.popout_desc'), cat:'Fichiers', act:()=>{close();const f=getCurrentFile();if(f)window.open(`/popout/${encodeURIComponent(f.vault)}/${encodeURIComponent(f.path)}?theme=${document.documentElement.getAttribute('data-theme')||'dark'}`,'popout','width=1000,height=700');else showToast(t('toast.no_open_file'),'error');} }, - { id:'create-file', label:t('palette.cmd_create_file'), desc:t('palette.cmd_create_file_desc'), cat:'Fichiers', act:()=>startBrowse('create-file') }, - { id:'delete-file', label:'🗑️ '+t('file.delete'), desc:t('palette.delete_file_desc'), cat:'Fichiers', act:()=>startBrowse('delete-file') }, - { id:'delete-cur', label:'🗑️ '+t('palette.delete_current'), desc:t('palette.delete_current_desc'), cat:'Fichiers', act:async()=>{close();await delCurFile();} }, - { id:'close-cur', label:'✕ '+t('palette.close_current'), desc:t('palette.close_current_desc'), cat:'Fichiers', act:()=>{close();const f=getCurrentFile();if(f){const tab=TabManager._tabs.find(t=>t.vault===f.vault&&t.path===f.path);if(tab)TabManager.close(tab.id);else triggerGoHome();}else{showToast(t('toast.no_open_file'),'error');}} }, - { id:'create-dir', label:t('palette.cmd_create_dir'), desc:t('palette.cmd_create_dir_desc'), cat:'Répertoires', act:()=>startBrowse('create-dir') }, - { id:'delete-dir', label:t('palette.cmd_delete_dir'), desc:t('palette.cmd_delete_dir_desc'), cat:'Répertoires', act:()=>startBrowse('delete-dir') }, - { id:'theme', label:t('palette.cmd_theme'), desc:t('palette.cmd_theme_desc'), cat:'Actions', act:()=>{close();toggleTheme();} }, - { id:'reindex', label:'🔄 '+t('vault.reindex'), desc:t('palette.reindex_desc'), cat:'Actions', act:async()=>{close();try{await api('/api/index/reload');showToast(t('sync.index_reloaded'),'success');}catch{showToast(t('common.error'),'error');}} }, - { id:'help', label:'❓ '+t('help.help_title'), desc:t('palette.help_desc'), cat:'Système', act:()=>{close();const b=document.getElementById('help-open-btn');if(b)b.click();} }, - { id:'config', label:t('palette.cmd_config'), desc:t('palette.cmd_config_desc'), cat:'Système', act:()=>{close();const b=document.getElementById('config-open-btn');if(b)b.click();} }, - ]; - return _cmdsCache; -} - -// ── Browse: vault picker ── -function startBrowse(action) { - _browse = { action, vault: null, path: '' }; - _browseFilter = ''; _allItems = []; - switchMode('browse-vault'); - renderVaultPicker(); -} - -async function renderVaultPicker() { - try { - const data = await api('/api/vaults'); - const vaults = Array.isArray(data) ? data : []; - _items = vaults.map(v => ({ type:'_vault', vault: v.name, label: (v.type==='DIR'?'📂':'🗂️')+' '+v.name, sublabel: t('palette.vault_count', {count: v.file_count}) })); - if (_items.length === 0) { - _items = [{ type:'_empty', label: t('palette.no_vaults'), sublabel: '' }]; - } - _allItems = _items; - render(); - } catch { _items = [{ type:'_error', label: t('palette.error_loading'), sublabel: '' }]; _allItems = _items; render(); } -} - -// ── Browse: directory navigation ── -async function renderBrowse() { - const { vault, path } = _browse; - _items = []; - const bc = document.getElementById('cp-breadcrumb'); - if (bc) { - bc.style.display = 'flex'; - const segs = path ? path.split('/') : []; - let html = `${esc(vault)}`; - let acc = ''; - for (const s of segs) { acc = acc ? acc+'/'+s : s; html += `/${esc(s)}`; } - bc.innerHTML = html; - bc.querySelectorAll('.cp-bc-item[data-path]').forEach(el => el.addEventListener('click', ()=>{ _browse.path=el.dataset.path; _browseFilter=''; if(_browseFilterEl)_browseFilterEl.value=''; renderBrowse(); })); - bc.querySelector('.cp-bc-root').addEventListener('click', ()=>{ _browse.path=''; _browseFilter=''; if(_browseFilterEl)_browseFilterEl.value=''; renderBrowse(); }); - } - - try { - const data = await api(`/api/browse/${encodeURIComponent(vault)}?path=${encodeURIComponent(path)}`); - const items = data.items || []; - const dirs = items.filter(i => i.type === 'directory' || i.is_dir); - const files = items.filter(i => i.type === 'file' && !i.is_dir); - - // Action row - const actLabel = { - 'create-file': t('palette.cmd_create_file'), - 'create-dir': t('palette.cmd_create_dir'), - 'delete-dir': t('palette.cmd_delete_dir'), - 'delete-file': t('palette.delete_file_desc'), - 'open-file': t('palette.browse_open_file') - }; - const isDeleteDir = _browse.action === 'delete-dir' && path; - const isDeleteFile = _browse.action === 'delete-file'; - const isOpenFile = _browse.action === 'open-file'; - const needsName = _browse.action === 'create-file' || _browse.action === 'create-dir'; - - if (isDeleteDir) { - _items.push({ type:'_action', label: '🗑️ '+t('file.delete')+' '+(path.split('/').pop()||path), sublabel: t('palette.dir_delete_confirm'), act:()=>execDelDir(path) }); - } else if (needsName) { - _items.push({ type:'_action', label: actLabel[_browse.action]||'', sublabel: t('palette.browse_in', {path: path||t('palette.browse_root')}), act:()=>askName() }); - } - - // Parent - if (path) { - _items.push({ type:'_nav', label: '📂 .. (parent)', go: path.split('/').slice(0,-1).join('/') }); - } - - // Subdirs - for (const d of dirs) { - const fp = path ? path+'/'+d.name : d.name; - _items.push({ type:'_nav', label: '📁 '+d.name, go: fp }); - } - - // Files - for (const f of files) { - const fp = path ? path+'/'+f.name : f.name; - if (isDeleteFile) { - _items.push({ type:'_file', label: '📄 '+f.name, sublabel: f.vault+'/'+fp, act:()=>execDelFile(fp) }); - } else if (isOpenFile) { - _items.push({ type:'_file', label: '📄 '+f.name, sublabel: f.vault+'/'+fp, act:()=>{ close(); TabManager.openPersistent(vault, fp); } }); - } else { - _items.push({ type:'_info', label: '📄 '+f.name, sublabel: fp }); - } - } - - if (_items.length === 0) _items.push({ type:'_empty', label: t('palette.empty_dir'), sublabel: '' }); - } catch { _items = [{ type:'_error', label: t('common.error'), sublabel: '' }]; } - - _allItems = _items; - applyBrowseFilter(); -} - -// ── Browse filter: local when empty, global suggest when text ── -function applyBrowseFilter() { - const q = _browseFilter.trim(); - if (!q) { - // Empty filter: show local directory items - _items = _allItems; - render(); - return; - } - // Has filter text: debounce and search globally - if (_browseFilterTimer) clearTimeout(_browseFilterTimer); - _browseFilterTimer = setTimeout(() => searchBrowseGlobal(q), 200); -} - -async function searchBrowseGlobal(rawQ) { - const { positive, negative } = parseQuery(rawQ); - const action = _browse.action; - const isDeleteFile = action === 'delete-file'; - const isOpenFile = action === 'open-file'; - const isDeleteDir = action === 'delete-dir'; - const needsName = action === 'create-file' || action === 'create-dir'; - - try { - const q = positive.join(' '); - const vault = _browse.vault || 'all'; - const d = await api(`/api/suggest?q=${encodeURIComponent(q)}&vault=${encodeURIComponent(vault)}`); - const sug = (d.suggestions || []).filter(s => { - const fullPath = (s.vault+'/'+s.path).toLowerCase(); - // Client-side negative filter - for (const n of negative) { - if (fullPath.includes(n)) return false; - } - return true; - }); - - if (sug.length === 0) { - _items = [{ type:'_empty', label: t('palette.no_results', {query: rawQ}), sublabel: '' }]; - render(); - return; - } - - _items = []; - - // Extract unique directories from result paths - const dirSet = new Set(); - for (const s of sug) { - const parts = s.path.split('/'); - // Build parent directories - for (let i = 0; i < parts.length - 1; i++) { - dirSet.add(s.vault + '|' + parts.slice(0, i + 1).join('/')); - } - } - - // Show directories as navigable - const dirs = [...dirSet].map(d => { - const [v, p] = d.split('|'); - const name = p.split('/').pop(); - return { type:'_nav', label:'📁 '+name, sublabel:v+'/'+p, go:p, vault:v }; - }).sort((a,b) => a.sublabel.localeCompare(b.sublabel)); - - for (const d of dirs) _items.push(d); - - // Show files - for (const s of sug) { - const fp = s.path; - const name = fp.split('/').pop(); - if (isDeleteFile) { - _items.push({ type:'_file', label:'📄 '+name, sublabel:s.vault+'/'+fp, act:()=>execDelFileBrowsed(s.vault, fp) }); - } else if (isOpenFile) { - _items.push({ type:'_file', label:'📄 '+name, sublabel:s.vault+'/'+fp, act:()=>{ close(); TabManager.openPersistent(s.vault, fp); } }); - } else if (isDeleteDir) { - _items.push({ type:'_file', label:'📁 '+name, sublabel:s.vault+'/'+fp, act:()=>execDelDirBrowsed(s.vault, fp) }); - } else { - _items.push({ type:'_file', label:'📄 '+name, sublabel:s.vault+'/'+fp, act:()=>{ close(); TabManager.openPersistent(s.vault, fp); } }); - } - } - - render(); - } catch { _items = [{ type:'_error', label: t('palette.search_error'), sublabel: '' }]; render(); } -} - -// Navigate to a directory from global search -function execNavGlobal(vault, goPath) { - _browse.vault = vault; - _browse.path = goPath; - _browseFilter = ''; - if (_browseFilterEl) _browseFilterEl.value = ''; - renderBrowse(); -} - -async function execDelFileBrowsed(vault, path) { - if (!confirm(t("confirm.delete_file_named", {path: vault + "/" + path}))) return; - try { - const d = await api(`/api/file/${encodeURIComponent(vault)}?path=${encodeURIComponent(path)}`, { method:'DELETE' }); - if (d?.status==='ok' || d?.success) { showToast(`🗑️ ${path} supprimé`,'success'); close(); refreshSidebar(); } - else showToast(t('common.error'),'error'); - } catch(e) { showToast('Erreur : '+(e.message||e),'error'); } -} - -async function execDelDirBrowsed(vault, path) { - if (!confirm(t("confirm.delete_dir_named", {path: path}))) return; - try { - const d = await api(`/api/directory/${encodeURIComponent(vault)}?path=${encodeURIComponent(path)}`, { method:'DELETE' }); - if (d?.status==='ok' || d?.success) { showToast(`🗑️ ${path} supprimé`,'success'); close(); refreshSidebar(); } - else showToast(t('common.error'),'error'); - } catch(e) { showToast('Erreur : '+(e.message||e),'error'); } -} - -function onBrowseFilterInput() { - _browseFilter = _browseFilterEl ? _browseFilterEl.value : ''; - applyBrowseFilter(); -} - -function onBrowseFilterKey(e) { - if (e.key === 'Escape') { - e.preventDefault(); - if (_browseFilter) { - _browseFilter = ''; - if (_browseFilterEl) _browseFilterEl.value = ''; - applyBrowseFilter(); - } else { - close(); - } - } else if (e.key === 'ArrowDown') { - e.preventDefault(); - _sel = 0; - updSel(_results.querySelectorAll('.cp-item')); - _overlay.focus(); - } else if (e.key === 'ArrowUp') { - e.preventDefault(); - const items = _results.querySelectorAll('.cp-item'); - _sel = Math.max(items.length - 1, 0); - updSel(items); - _overlay.focus(); - } else if (e.key === 'Enter') { - e.preventDefault(); - if (_items.length > 0) exec(_sel); - } else if (e.key === 'Backspace' && !_browseFilter && (!_browseFilterEl || !_browseFilterEl.value)) { - e.preventDefault(); - const segs = _browse.path ? _browse.path.split('/') : []; - if (segs.length > 0) { _browse.path = segs.slice(0, -1).join('/'); renderBrowse(); } - else if (_browse.vault) { switchMode('browse-vault'); renderVaultPicker(); } - } -} - -// ── Name input modal ── -function askName() { - const label = _browse.action === 'create-file' ? 'Nom du fichier' : 'Nom du dossier'; - const ext = _browse.action === 'create-file' ? '(.md ajouté si besoin)' : ''; - const existingInput = document.getElementById('cp-name-input'); - if (existingInput) { existingInput.focus(); return; } - - _input.style.display = 'none'; - const bc = document.getElementById('cp-breadcrumb'); - if (bc) bc.style.display = 'none'; - - const nameDiv = document.createElement('div'); - nameDiv.id = 'cp-name-input'; - nameDiv.className = 'cp-name-input'; - nameDiv.innerHTML = ` - Enter confirmer · Esc annuler`; - _results.before(nameDiv); - - const field = document.getElementById('cp-name-field'); - field.focus(); - field.addEventListener('keydown', (e) => { - if (e.key === 'Enter') { - e.preventDefault(); - const name = field.value.trim(); - if (!name) return; - cleanupNameInput(); - if (_browse.action === 'create-file') execCreateFile(name); - else execCreateDir(name); - } else if (e.key === 'Escape') { - e.preventDefault(); - cleanupNameInput(); - _overlay.focus(); - renderBrowse(); - } - }); -} - -function cleanupNameInput() { - const el = document.getElementById('cp-name-input'); - if (el) el.remove(); - const bc = document.getElementById('cp-breadcrumb'); - if (bc) bc.style.display = 'flex'; -} - -// ── Execute actions ── -async function execCreateFile(name) { - let fp = _browse.path ? _browse.path+'/'+name : name; - if (!fp.includes('.')) fp += '.md'; - try { - const d = await api(`/api/file/${encodeURIComponent(_browse.vault)}`, { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({path:fp, content:`# ${name.replace('.md','')}\n\n`}) }); - if (d?.status==='ok' || d?.success) { showToast(`✅ ${fp} créé`,'success'); close(); openEditor(_browse.vault, fp); } - else showToast(t('toast.create_error'),'error'); - } catch(e) { showToast('Erreur : '+(e.message||e),'error'); } -} - -async function execCreateDir(name) { - const dp = _browse.path ? _browse.path+'/'+name : name; - try { - const d = await api(`/api/directory/${encodeURIComponent(_browse.vault)}`, { method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({path:dp}) }); - if (d?.status==='ok' || d?.success) { showToast(`📁 ${dp} créé`,'success'); close(); refreshSidebar(); } - else showToast(t('common.error'),'error'); - } catch(e) { showToast('Erreur : '+(e.message||e),'error'); } -} - -async function execDelDir(path) { - if (!confirm(t("confirm.delete_dir_named", {path: path}))) return; - try { - const d = await api(`/api/directory/${encodeURIComponent(_browse.vault)}?path=${encodeURIComponent(path)}`, { method:'DELETE' }); - if (d?.status==='ok' || d?.success) { showToast(`🗑️ ${path} supprimé`,'success'); close(); refreshSidebar(); } - else showToast(t('common.error'),'error'); - } catch(e) { showToast('Erreur : '+(e.message||e),'error'); } -} - -async function execDelFile(path) { - if (!confirm(t("confirm.delete_file_named", {path: path}))) return; - try { - const d = await api(`/api/file/${encodeURIComponent(_browse.vault)}?path=${encodeURIComponent(path)}`, { method:'DELETE' }); - if (d?.status==='ok' || d?.success) { showToast(`🗑️ ${path} supprimé`,'success'); close(); refreshSidebar(); } - else showToast(t('common.error'),'error'); - } catch(e) { showToast('Erreur : '+(e.message||e),'error'); } -} - -async function delCurFile() { - const f = getCurrentFile(); - if (!f) { showToast(t('toast.no_open_file'),'error'); return; } - if (!confirm(t("confirm.delete_file_named", {path: f.path}))) return; - try { - const d = await api(`/api/file/${encodeURIComponent(f.vault)}?path=${encodeURIComponent(f.path)}`, { method:'DELETE' }); - if (d?.status==='ok' || d?.success) { showToast(`🗑️ ${f.path} supprimé`,'success'); - const tab = TabManager._tabs.find(t=>t.vault===f.vault&&t.path===f.path); if(tab) TabManager.close(tab.id); triggerGoHome(); refreshSidebar(); } - else showToast(t('common.error'),'error'); - } catch(e) { showToast('Erreur : '+(e.message||e),'error'); } -} - -function refreshSidebar() { - import('./sidebar.js').then(m => { if (m.loadVaults) m.loadVaults(); }).catch(() => {}); -} - -// ── DOM ── -function createDOM() { - if (_overlay) return; - _overlay = document.createElement('div'); - _overlay.className = 'command-palette-overlay'; - _overlay.tabIndex = -1; - _overlay.innerHTML = `
    -
    Ctrl+Shift+Espace
    - -
    -
    `; - _input = _overlay.querySelector('.cp-input'); - _browseFilterEl = _overlay.querySelector('#cp-browse-filter'); - _results = _overlay.querySelector('.cp-results'); - _overlay.addEventListener('click', (e) => { if (e.target === _overlay) close(); }); - _input.addEventListener('keydown', onKeyDown); - _input.addEventListener('input', onInput); - if (_browseFilterEl) { - _browseFilterEl.addEventListener('input', onBrowseFilterInput); - _browseFilterEl.addEventListener('keydown', onBrowseFilterKey); - } - _overlay.addEventListener('keydown', onOverlayKeyDown); - document.body.appendChild(_overlay); -} - -export function open(q = '') { - createDOM(); - _overlay.classList.add('active'); - _input.value = q; - _mode = q.startsWith('>') ? 'commands' : 'files'; - _input.disabled = false; _input.style.display = ''; - _sel = 0; _items = []; _results.innerHTML = ''; - _input.focus(); - onInput(); -} - -export function close() { - if (!_overlay) return; - _overlay.classList.remove('active'); - if (_to) clearTimeout(_to); _to = null; - if (_browseFilterTimer) clearTimeout(_browseFilterTimer); - _mode = 'files'; - _browseFilter = ''; - _allItems = []; - cleanupNameInput(); - if (_browseFilterEl) { _browseFilterEl.style.display = 'none'; _browseFilterEl.value = ''; } - const bc = document.getElementById('cp-breadcrumb'); if (bc) bc.style.display = 'none'; - const si = document.querySelector('.search-input'); if (si) si.focus(); -} - -function isOpen() { return _overlay && _overlay.classList.contains('active'); } - -function switchMode(m) { - _mode = m; - if (m === 'browse' || m === 'browse-vault') { - _input.style.display = 'none'; _input.disabled = true; - _overlay.focus(); - if (m === 'browse' && _browseFilterEl) { - _browseFilterEl.style.display = ''; - _browseFilterEl.value = _browseFilter; - _browseFilterEl.focus(); - } else if (_browseFilterEl) { - _browseFilterEl.style.display = 'none'; - } - } else { - _input.style.display = ''; _input.disabled = false; - _input.focus(); - if (_browseFilterEl) _browseFilterEl.style.display = 'none'; - const bc = document.getElementById('cp-breadcrumb'); if (bc) bc.style.display = 'none'; - } -} - -function onInput() { - if (_mode === 'browse' || _mode === 'browse-vault') return; - const v = _input.value; - const nm = v.startsWith('>') ? 'commands' : 'files'; - if (nm !== _mode) { _mode = nm; _input.placeholder = _mode==='commands'?'Tapez une commande...':'Rechercher un fichier... (+inclure -exclure)'; } - if (_to) clearTimeout(_to); - _to = setTimeout(() => { _to = null; if (_mode==='commands') searchCmd(v.slice(1).trim()); else searchFiles(v.trim()); }, 150); -} - -async function searchFiles(rawQ) { - if (!rawQ) { - _items = [{ type:'_browse', label:'📂 Parcourir les répertoires...', sublabel:'Naviguer dans les vaults pour trouver un fichier', act:()=>startBrowse('open-file') }]; - render(); - return; - } - - const { positive, negative } = parseQuery(rawQ); - - try { - const q = positive.join(' '); - const d = await api(`/api/suggest?q=${encodeURIComponent(q)}&vault=all`); - let sug = d.suggestions || []; - - // Client-side negative filter - if (negative.length > 0) { - sug = sug.filter(s => { - const fullPath = (s.vault+'/'+s.path).toLowerCase(); - for (const n of negative) { - if (fullPath.includes(n)) return false; - } - return true; - }); - } - - if (sug.length === 0) { - _items = [{ type:'_browse', label:'📂 Parcourir les répertoires...', sublabel:'Aucun résultat — naviguer manuellement', act:()=>startBrowse('open-file') }]; - } else { - _items = sug.map(s => ({ type:'file', vault:s.vault, path:s.path, label:s.title||s.path.split('/').pop(), sublabel:`${s.vault}/${s.path}` })); - } - render(); - } catch { _results.innerHTML = '
    Erreur
    '; } -} - -function searchCmd(q) { - if (!q) { _items = getCMDS().map(c => ({ type:'cmd', ...c })); render(); return; } - const lq = q.toLowerCase(); - _items = getCMDS().filter(c => c.label.toLowerCase().includes(lq)||c.desc.toLowerCase().includes(lq)||(c.cat&&c.cat.toLowerCase().includes(lq))).map(c => ({ type:'cmd', ...c })); - render(); -} - -function render() { - _sel = 0; - if (!_items.length) { _results.innerHTML = '
    Aucun résultat
    '; return; } - _results.innerHTML = _items.map((it, i) => `
    ${esc(it.label)}
    ${esc(it.sublabel||'')}
    `).join(''); - _results.querySelectorAll('.cp-item').forEach(el => { - el.addEventListener('click', () => exec(parseInt(el.dataset.idx))); - el.addEventListener('mouseenter', () => { document.querySelectorAll('.cp-item').forEach(e=>e.classList.remove('cp-selected')); el.classList.add('cp-selected'); _sel = parseInt(el.dataset.idx); }); - }); - scroll(); -} - -function onKeyDown(e) { - const items = _results.querySelectorAll('.cp-item'); - if (_mode === 'browse' || _mode === 'browse-vault') { - if (e.key === 'Escape') { e.preventDefault(); close(); } - else if (e.key === 'Backspace') { - e.preventDefault(); - if (_mode === 'browse-vault') { _mode='commands'; _input.style.display=''; _input.disabled=false; _input.focus(); searchCmd(''); return; } - const segs = _browse.path ? _browse.path.split('/') : []; - if (segs.length > 0) { _browse.path = segs.slice(0,-1).join('/'); renderBrowse(); } - else if (_browse.vault) { switchMode('browse-vault'); renderVaultPicker(); } - } - else if (e.key === 'Enter') { e.preventDefault(); exec(_sel); } - else if (e.key === 'ArrowDown') { e.preventDefault(); _sel = Math.min(_sel+1, _items.length-1); updSel(items); } - else if (e.key === 'ArrowUp') { e.preventDefault(); _sel = Math.max(_sel-1, 0); updSel(items); } - return; - } - if (e.key === 'Escape') { e.preventDefault(); close(); } - else if (e.key === 'Enter') { e.preventDefault(); exec(_sel); } - else if (e.key === 'ArrowDown') { e.preventDefault(); _sel = Math.min(_sel+1, _items.length-1); updSel(items); } - else if (e.key === 'ArrowUp') { e.preventDefault(); _sel = Math.max(_sel-1, 0); updSel(items); } - else if (e.key === 'Tab') { e.preventDefault(); if (_mode==='files') { _input.value='> '; setTimeout(()=>_input.setSelectionRange(2,2),0); } else _input.value=''; onInput(); } -} - -function updSel(items) { items.forEach((el,i)=>el.classList.toggle('cp-selected',i===_sel)); scroll(); } -function scroll() { const s = _results.querySelector('.cp-selected'); if (s) s.scrollIntoView({block:'nearest'}); } - -// ── Overlay keydown handler (for browse modes where input is hidden) ── -function onOverlayKeyDown(e) { - if (_mode !== 'browse' && _mode !== 'browse-vault') return; - if (document.getElementById('cp-name-input')) return; - if (document.activeElement === _browseFilterEl) return; - onKeyDown(e); -} - -function exec(idx) { - const it = _items[idx]; if (!it) return; - if (it.type === 'file') { - close(); - if (window.innerWidth <= 768) { - TabManager.openPersistent(it.vault, it.path); - } else { - TabManager.openPreview(it.vault, it.path); - } - } - else if (it.type === 'cmd' || it.type === '_browse') { it.act(); } - else if (it.type === '_vault') { _browse.vault = it.vault; switchMode('browse'); renderBrowse(); } - else if (it.type === '_nav') { - // Check if this is a global search result with vault info - if (it.vault && it.vault !== _browse.vault) { _browse.vault = it.vault; } - _browse.path = it.go; - _browseFilter=''; - if(_browseFilterEl) _browseFilterEl.value=''; - renderBrowse(); - } - else if (it.type === '_action' || it.type === '_file') { it.act(); } -} - -function esc(s) { if (!s) return ''; return String(s).replace(/&/g,'&').replace(//g,'>').replace(/\"/g,'"'); } - -export function initCommandPalette() { - document.addEventListener('keydown', (e) => { - if ((e.ctrlKey||e.metaKey) && e.shiftKey && !e.altKey && (e.key===' '||e.code==='Space')) { e.preventDefault(); if (isOpen()) close(); else open(''); } - if ((e.ctrlKey||e.metaKey) && e.altKey && !e.shiftKey && (e.key===' '||e.code==='Space')) { e.preventDefault(); if (isOpen()) close(); else open('> '); } - }); -} diff --git a/desktop/frontend-static/js/pane-manager.js b/desktop/frontend-static/js/pane-manager.js deleted file mode 100644 index 2e9324d..0000000 --- a/desktop/frontend-static/js/pane-manager.js +++ /dev/null @@ -1,263 +0,0 @@ -/** - * PaneManager — Multi-pane split view for ObsiGate (v2.0.0-dev) - * Supports 1–4 panes in CSS grid, split right/down, resize, drag tabs between panes. - * Integrates with existing TabManager singleton. - */ - -const PANE_MAX = 4; - -const PaneManager = { - panes: [], - activePaneId: 0, - _paneCounter: 1, - layout: 'horizontal', - - init() { - const saved = localStorage.getItem('obsigate-panes'); - if (saved) { - try { - const data = JSON.parse(saved); - if (data.panes && data.panes.length >= 2) { - this.layout = data.layout || 'horizontal'; - this._paneCounter = data.panes.length; - this._buildGrid(data.panes.length); - data.panes.forEach((p, i) => { - this.panes[i].activeTab = p.activeTab; - this.panes[i].width = p.width; - }); - this.activePaneId = data.panes[0].id; - this._applyResize(); - return; - } - } catch (e) { /* ignore */ } - } - }, - - _buildGrid(n) { - const wrapper = document.querySelector('.content-wrapper'); - const origTabBar = document.getElementById('tab-bar'); - const origContent = document.getElementById('content-area'); - if (!wrapper || !origContent || n < 2) return; - - // Create grid container - const grid = document.createElement('div'); - grid.className = 'pane-grid'; - if (n === 2) grid.style.gridTemplateColumns = this.layout === 'horizontal' ? '1fr 4px 1fr' : '1fr'; - if (n >= 3) grid.style.gridTemplateColumns = '1fr 4px 1fr'; - if (n === 4) grid.style.gridTemplateRows = '1fr 4px 1fr'; - - wrapper.innerHTML = ''; - wrapper.appendChild(grid); - - for (let i = 0; i < Math.min(n, PANE_MAX); i++) { - const pane = this._createPane(i, grid, i === 0 ? origTabBar : null, i === 0 ? origContent : null); - this.panes.push(pane); - if (i < n - 1) { - const handle = document.createElement('div'); - handle.className = 'pane-resize-handle'; - if (this.layout === 'horizontal') handle.style.cursor = 'col-resize'; - else handle.style.cursor = 'row-resize'; - handle.addEventListener('mousedown', (e) => this._onResizeStart(e, i, i + 1)); - handle.addEventListener('dblclick', () => this._resetResize(i, i + 1)); - grid.appendChild(handle); - } - } - this.activePaneId = 0; - this._highlightActive(); - }, - - _createPane(idx, grid, reuseTabBar, reuseContent) { - const container = document.createElement('div'); - container.className = 'pane-container'; - container.dataset.pane = idx; - - if (reuseTabBar && reuseContent) { - // Pane 0 reuses existing DOM - container.appendChild(reuseTabBar); - container.appendChild(reuseContent); - reuseContent.id = 'content-area-0'; - } else { - const tabBar = document.createElement('div'); - tabBar.className = 'tab-bar pane-tab-bar'; - tabBar.id = 'tab-bar-' + idx; - tabBar.innerHTML = '
    '; - const content = document.createElement('main'); - content.className = 'content-area pane-content'; - content.id = 'content-area-' + idx; - container.appendChild(tabBar); - container.appendChild(content); - } - - container.addEventListener('click', () => { - this.activePaneId = idx; - this._highlightActive(); - }); - - grid.appendChild(container); - return { id: idx, element: container, width: 100 / this.panes.length + '%' }; - }, - - _highlightActive() { - this.panes.forEach((p, i) => { - p.element.classList.toggle('pane-active', i === this.activePaneId); - }); - }, - - splitRight() { - if (this.panes.length >= PANE_MAX) return; - if (this.panes.length === 0) { - // First split: promote single pane to grid - this._buildGrid(2); - } else { - this._addPane(); - } - this._persist(); - }, - - splitDown() { - if (this.panes.length >= PANE_MAX) return; - this.layout = 'vertical'; - if (this.panes.length === 0) { - this._buildGrid(2); - } else { - this._addPane(); - } - this._persist(); - }, - - _addPane() { - const grid = document.querySelector('.pane-grid'); - if (!grid) return; - const n = this.panes.length + 1; - const handle = document.createElement('div'); - handle.className = 'pane-resize-handle'; - handle.addEventListener('mousedown', (e) => this._onResizeStart(e, n - 2, n - 1)); - grid.appendChild(handle); - const pane = this._createPane(n - 1, grid, null, null); - this.panes.push(pane); - this.activePaneId = n - 1; - this._highlightActive(); - if (n <= 2) grid.style.gridTemplateColumns = '1fr 4px 1fr'; - else if (n === 4) grid.style.gridTemplateRows = '1fr 4px 1fr'; - }, - - closePane(paneId) { - if (this.panes.length <= 1) return; - const idx = this.panes.findIndex(p => p.id === paneId); - if (idx < 0) return; - // Remove pane and its resize handles - this.panes[idx].element.remove(); - const handles = document.querySelectorAll('.pane-resize-handle'); - if (handles[idx]) handles[idx].remove(); - else if (handles[idx - 1]) handles[idx - 1].remove(); - this.panes.splice(idx, 1); - if (this.panes.length <= 1) { - this._collapseToSingle(); - } else { - this.activePaneId = Math.min(this.activePaneId, this.panes.length - 1); - this._highlightActive(); - } - this._persist(); - }, - - _collapseToSingle() { - const grid = document.querySelector('.pane-grid'); - if (!grid) return; - const wrapper = grid.parentElement; - const pane0 = this.panes[0]; - wrapper.innerHTML = ''; - const tabBar = pane0.element.querySelector('.tab-bar') || document.getElementById('tab-bar-0'); - const content = pane0.element.querySelector('.content-area') || document.getElementById('content-area-0'); - if (tabBar) wrapper.appendChild(tabBar); - if (content) wrapper.appendChild(content); - this.panes = []; - this.activePaneId = 0; - }, - - _onResizeStart(e, leftIdx, rightIdx) { - e.preventDefault(); - const grid = document.querySelector('.pane-grid'); - const startX = e.clientX; - const startY = e.clientY; - const totalSize = this.layout === 'horizontal' ? grid.offsetWidth : grid.offsetHeight; - - const onMove = (ev) => { - const delta = this.layout === 'horizontal' ? ev.clientX - startX : ev.clientY - startY; - const pct = (delta / totalSize) * 100; - const leftEl = this.panes[leftIdx].element; - const rightEl = this.panes[rightIdx].element; - const curLeft = parseFloat(leftEl.style.flexBasis || leftEl.style.width || '50'); - const curRight = parseFloat(rightEl.style.flexBasis || rightEl.style.width || '50'); - const newLeft = Math.max(20, Math.min(80, curLeft + pct)); - const newRight = 100 - newLeft; - leftEl.style.flexBasis = newLeft + '%'; - rightEl.style.flexBasis = newRight + '%'; - this.panes[leftIdx].width = newLeft + '%'; - this.panes[rightIdx].width = newRight + '%'; - }; - - const onUp = () => { - document.removeEventListener('mousemove', onMove); - document.removeEventListener('mouseup', onUp); - this._persist(); - }; - - document.addEventListener('mousemove', onMove); - document.addEventListener('mouseup', onUp); - }, - - _resetResize(leftIdx, rightIdx) { - this.panes[leftIdx].element.style.flexBasis = '50%'; - this.panes[rightIdx].element.style.flexBasis = '50%'; - this._persist(); - }, - - _applyResize() { - this.panes.forEach(p => { - if (p.width) p.element.style.flexBasis = p.width; - }); - }, - - _persist() { - if (this.panes.length <= 1) { - localStorage.removeItem('obsigate-panes'); - return; - } - const data = { - layout: this.layout, - panes: this.panes.map(p => ({ id: p.id, activeTab: p.activeTab, width: p.width })), - }; - localStorage.setItem('obsigate-panes', JSON.stringify(data)); - }, - - getActiveContentArea() { - if (this.panes.length < 2) return document.getElementById('content-area'); - return document.getElementById('content-area-' + this.activePaneId) || document.getElementById('content-area-0'); - }, - - isSplit() { - return this.panes.length >= 2; - }, -}; - -// Export and auto-init -if (typeof window !== 'undefined') { - window.PaneManager = PaneManager; - document.addEventListener('DOMContentLoaded', () => { - // Register keyboard shortcuts - document.addEventListener('keydown', (e) => { - if (e.ctrlKey && e.altKey && !e.shiftKey && e.key === '\\') { - e.preventDefault(); - PaneManager.splitRight(); - } - if (e.ctrlKey && e.altKey && e.shiftKey && e.key === '\\') { - e.preventDefault(); - PaneManager.splitDown(); - } - }); - // Initialize if saved state exists - setTimeout(() => PaneManager.init(), 500); - }); -} - -export default PaneManager; diff --git a/desktop/frontend-static/js/search.js b/desktop/frontend-static/js/search.js deleted file mode 100644 index 69cbc74..0000000 --- a/desktop/frontend-static/js/search.js +++ /dev/null @@ -1,1154 +0,0 @@ -/* ObsiGate — Search module */ -import { api } from './auth.js'; -import { state } from './state.js'; -import { safeCreateIcons } from './utils.js'; -import { showLoading, el, hideProgressBar, showWelcome, highlightSearchText, loadSavedSearches } from './viewer.js'; -import { searchOffline } from './offline.js'; -import { _getEffective } from './config.js'; -import { TabManager, showToast } from './ui.js'; -import { addTagFilter, buildSearchResultsHeader, shouldDisplayPath, removeTagFilter, TagFilterService } from './sidebar.js'; -import { t } from './i18n.js'; -// --------------------------------------------------------------------------- -// Search History Service (localStorage, LIFO, max 50, dedup) -// --------------------------------------------------------------------------- -export const SearchHistory = { - _load() { - try { - const raw = localStorage.getItem(state.SEARCH_HISTORY_KEY); - return raw ? JSON.parse(raw) : []; - } catch { - return []; - } - }, - _save(entries) { - try { - localStorage.setItem(state.SEARCH_HISTORY_KEY, JSON.stringify(entries)); - } catch {} - }, - getAll() { - return this._load(); - }, - add(query) { - if (!query || !query.trim()) return; - const q = query.trim(); - let entries = this._load().filter((e) => e !== q); - entries.unshift(q); - if (entries.length > state.MAX_HISTORY_ENTRIES) entries = entries.slice(0, state.MAX_HISTORY_ENTRIES); - this._save(entries); - }, - remove(query) { - const entries = this._load().filter((e) => e !== query); - this._save(entries); - }, - clear() { - this._save([]); - }, - filter(prefix) { - if (!prefix) return this.getAll().slice(0, 8); - const lp = prefix.toLowerCase(); - return this._load() - .filter((e) => e.toLowerCase().includes(lp)) - .slice(0, 8); - }, -}; - - -// --------------------------------------------------------------------------- -// Query Parser — extracts operators (tag:, #, vault:, title:, path:, ext:) -// --------------------------------------------------------------------------- -export const QueryParser = { - parse(raw) { - const result = { tags: [], vault: null, title: null, path: null, ext: null, - created: null, modified: null, size: null, freeText: "" }; - if (!raw) return result; - const tokens = this._tokenize(raw); - const freeTokens = []; - for (const tok of tokens) { - const lower = tok.toLowerCase(); - if (lower.startsWith("tag:")) { - const v = tok.slice(4).replace(/"/g, "").trim().replace(/^#/, ""); - if (v) result.tags.push(v); - } else if (lower.startsWith("#") && tok.length > 1) { - result.tags.push(tok.slice(1)); - } else if (lower.startsWith("vault:")) { - result.vault = tok.slice(6).replace(/"/g, "").trim(); - } else if (lower.startsWith("title:")) { - result.title = tok.slice(6).replace(/"/g, "").trim(); - } else if (lower.startsWith("path:")) { - result.path = tok.slice(5).replace(/"/g, "").trim(); - } else if (lower.startsWith("ext:")) { - result.ext = tok.slice(4).replace(/"/g, "").trim().replace(/^\./, "").toLowerCase(); - } else if (lower.startsWith("created:")) { - result.created = tok.slice(8).replace(/"/g, "").trim(); - } else if (lower.startsWith("modified:")) { - result.modified = tok.slice(9).replace(/"/g, "").trim(); - } else if (lower.startsWith("size:")) { - result.size = tok.slice(5).replace(/"/g, "").trim(); - } else { - freeTokens.push(tok); - } - } - result.freeText = freeTokens.join(" "); - return result; - }, - _tokenize(raw) { - const tokens = []; - let i = 0; - const n = raw.length; - while (i < n) { - while (i < n && raw[i] === " ") i++; - if (i >= n) break; - if (raw[i] !== '"') { - let j = i; - while (j < n && raw[j] !== " ") { - if (raw[j] === '"') { - j++; - while (j < n && raw[j] !== '"') j++; - if (j < n) j++; - } else j++; - } - tokens.push(raw.slice(i, j).replace(/"/g, "")); - i = j; - } else { - i++; - let j = i; - while (j < n && raw[j] !== '"') j++; - tokens.push(raw.slice(i, j)); - i = j + 1; - } - } - return tokens; - }, - /** Detect the current operator context at cursor for autocomplete */ - getContext(raw, cursorPos) { - const before = raw.slice(0, cursorPos); - // Check if we're typing a tag: or # value - const tagMatch = before.match(/(?:tag:|#)([\w-]*)$/i); - if (tagMatch) return { type: "tag", prefix: tagMatch[1] }; - // Check if typing title: - const titleMatch = before.match(/title:([\w-]*)$/i); - if (titleMatch) return { type: "title", prefix: titleMatch[1] }; - // Default: free text - const words = before.trim().split(/\s+/); - const lastWord = words[words.length - 1] || ""; - return { type: "text", prefix: lastWord }; - }, -}; - - -// --------------------------------------------------------------------------- -// Autocomplete Dropdown Controller -// --------------------------------------------------------------------------- -export const AutocompleteDropdown = { - _dropdown: null, - _historySection: null, - _titlesSection: null, - _tagsSection: null, - _historyList: null, - _titlesList: null, - _tagsList: null, - _emptyEl: null, - _suggestTimer: null, - - init() { - this._dropdown = document.getElementById("search-dropdown"); - this._historySection = document.getElementById("search-dropdown-history"); - this._titlesSection = document.getElementById("search-dropdown-titles"); - this._tagsSection = document.getElementById("search-dropdown-tags"); - this._historyList = document.getElementById("search-dropdown-history-list"); - this._titlesList = document.getElementById("search-dropdown-titles-list"); - this._tagsList = document.getElementById("search-dropdown-tags-list"); - this._emptyEl = document.getElementById("search-dropdown-empty"); - - // Clear history button - const clearBtn = document.getElementById("search-dropdown-clear-history"); - if (clearBtn) { - clearBtn.addEventListener("click", (e) => { - e.stopPropagation(); - SearchHistory.clear(); - this.hide(); - }); - } - - // Close dropdown on outside click - document.addEventListener("click", (e) => { - if (this._dropdown && !this._dropdown.contains(e.target) && e.target.id !== "search-input") { - this.hide(); - } - }); - }, - - show() { - if (this._dropdown) this._dropdown.hidden = false; - }, - - hide() { - if (this._dropdown) this._dropdown.hidden = true; - state.dropdownActiveIndex = -1; - state.dropdownItems = []; - }, - - isVisible() { - return this._dropdown && !this._dropdown.hidden; - }, - - /** Populate and show the dropdown with history, title suggestions, and tag suggestions */ - async populate(inputValue, cursorPos) { - if (this._suppressNext) { this._suppressNext = false; return; } - // Cancel previous suggestion request - if (state.suggestAbortController) { - state.suggestAbortController.abort(); - state.suggestAbortController = null; - } - - const ctx = QueryParser.getContext(inputValue, cursorPos); - const vault = document.getElementById("vault-filter").value; - - // History — always show filtered history - const historyItems = SearchHistory.filter(inputValue).slice(0, 5); - this._renderHistory(historyItems, inputValue); - - // Title and tag suggestions from API (debounced) — always fetch both - clearTimeout(this._suggestTimer); - const prefix = ctx.prefix; - if (prefix && prefix.length >= 2) { - // Only show placeholder if lists are empty (avoid flashing on fast typing) - const hasTitles = this._titlesList.children.length > 0 && !this._titlesList.querySelector(".search-dropdown__item--loading"); - const hasTags = this._tagsList.children.length > 0 && !this._tagsList.querySelector(".search-dropdown__item--loading"); - if (!hasTitles) { - this._titlesList.innerHTML = '
  • Recherche...
  • '; - } - if (!hasTags) { - this._tagsList.innerHTML = '
  • Recherche...
  • '; - } - this._titlesSection.hidden = false; - this._tagsSection.hidden = false; - this.show(); - this._suggestTimer = setTimeout(() => this._fetchSuggestions(prefix, vault), 150); - } else { - this._renderTitles([], ""); - this._renderTags([], ""); - this._titlesSection.hidden = true; - this._tagsSection.hidden = true; - } - - // Show/hide sections - this._historySection.hidden = historyItems.length === 0; - const hasContent = historyItems.length > 0; - if (hasContent || (prefix && prefix.length >= 2)) { - this.show(); - } else { - this.hide(); - } - - this._collectItems(); - }, - - async _fetchSuggestions(prefix, vault) { - state.suggestAbortController = new AbortController(); - // Fetch titles - try { - const titlesRes = await api(`/api/suggest?q=${encodeURIComponent(prefix)}&vault=${encodeURIComponent(vault)}&limit=5`, { signal: state.suggestAbortController.signal }); - this._renderTitles(titlesRes.suggestions || [], prefix); - this._titlesSection.hidden = !(titlesRes.suggestions || []).length; - if (titlesRes.suggestions?.length) this.show(); - } catch (err) { - if (err.name === "AbortError") return; - this._titlesSection.hidden = true; - } - // Fetch tags — keep section always visible to confirm it works - try { - const tagsRes = await api(`/api/tags/suggest?q=${encodeURIComponent(prefix)}&vault=${encodeURIComponent(vault)}&limit=5`, { signal: state.suggestAbortController.signal }); - const items = tagsRes.suggestions || []; - if (items.length > 0) { - this._renderTags(items, prefix); - } else { - this._tagsList.innerHTML = '
  • Aucun tag
  • '; - } - this._tagsSection.hidden = false; - this.show(); - } catch (err) { - if (err.name === "AbortError") return; - this._tagsList.innerHTML = '
  • Erreur chargement
  • '; - this._tagsSection.hidden = false; - } - this._collectItems(); - }, - - _renderHistory(items, query) { - this._historyList.innerHTML = ""; - items.forEach((entry) => { - const li = el("li", { class: "search-dropdown__item search-dropdown__item--history", role: "option" }); - const iconEl = el("span", { class: "search-dropdown__icon" }); - iconEl.innerHTML = ''; - const textEl = el("span", { class: "search-dropdown__text" }); - textEl.textContent = entry; - li.appendChild(iconEl); - li.appendChild(textEl); - li.addEventListener("click", () => { - const input = document.getElementById("search-input"); - input.value = entry; - this._suppressNext = true; - input.dispatchEvent(new Event("input", { bubbles: true })); - this.hide(); - _triggerAdvancedSearch(entry); - }); - this._historyList.appendChild(li); - }); - }, - - _renderTitles(items, prefix) { - this._titlesList.innerHTML = ""; - items.forEach((item) => { - const li = el("li", { class: "search-dropdown__item search-dropdown__item--title", role: "option" }); - const iconEl = el("span", { class: "search-dropdown__icon" }); - iconEl.innerHTML = ''; - const textEl = el("span", { class: "search-dropdown__text" }); - if (prefix) { - this._highlightText(textEl, item.title, prefix); - } else { - textEl.textContent = item.title; - } - const metaEl = el("span", { class: "search-dropdown__meta" }); - metaEl.textContent = item.vault; - li.appendChild(iconEl); - li.appendChild(textEl); - li.appendChild(metaEl); - li.addEventListener("click", () => { - this.hide(); - TabManager.openPreview(item.vault, item.path); - }); - this._titlesList.appendChild(li); - }); - }, - - _renderTags(items, prefix) { - this._tagsList.innerHTML = ""; - items.forEach((item) => { - const li = el("li", { class: "search-dropdown__item search-dropdown__item--tag", role: "option" }); - const iconEl = el("span", { class: "search-dropdown__icon" }); - iconEl.innerHTML = ''; - const textEl = el("span", { class: "search-dropdown__text" }); - if (prefix) { - this._highlightText(textEl, item.tag, prefix); - } else { - textEl.textContent = item.tag; - } - const badge = el("span", { class: "search-dropdown__badge" }); - badge.textContent = item.count; - li.appendChild(iconEl); - li.appendChild(textEl); - li.appendChild(badge); - li.addEventListener("click", () => { - const input = document.getElementById("search-input"); - const current = input.value; - const cursorPos = input.selectionStart; - const ctx = QueryParser.getContext(current, cursorPos); - if (ctx.type === "tag") { - // Replace the partial tag prefix - const before = current.slice(0, cursorPos - ctx.prefix.length); - input.value = before + item.tag + " "; - } else { - // Replace the last word with tag: operator - const words = current.trim().split(/\s+/); - if (words.length > 0 && ctx.prefix && ctx.prefix.length > 0) { - words[words.length - 1] = ""; // remove last partial word - } - const base = words.filter(w => w).join(" "); - input.value = (base ? base + " " : "") + "tag:" + item.tag + " "; - } - this._suppressNext = true; - input.dispatchEvent(new Event("input", { bubbles: true })); - this.hide(); - input.focus(); - _triggerAdvancedSearch(input.value); - }); - this._tagsList.appendChild(li); - }); - }, - - _highlightText(container, text, query) { - const lower = text.toLowerCase(); - const needle = query.toLowerCase(); - const pos = lower.indexOf(needle); - if (pos === -1) { - container.textContent = text; - return; - } - container.appendChild(document.createTextNode(text.slice(0, pos))); - const markEl = el("mark", {}, [document.createTextNode(text.slice(pos, pos + query.length))]); - container.appendChild(markEl); - container.appendChild(document.createTextNode(text.slice(pos + query.length))); - }, - - _collectItems() { - state.dropdownItems = Array.from(this._dropdown.querySelectorAll(".search-dropdown__item")); - state.dropdownActiveIndex = -1; - state.dropdownItems.forEach((item) => item.classList.remove("active")); - }, - - navigateDown() { - if (!this.isVisible() || state.dropdownItems.length === 0) return; - if (state.dropdownActiveIndex >= 0) state.dropdownItems[state.dropdownActiveIndex].classList.remove("active"); - state.dropdownActiveIndex = (state.dropdownActiveIndex + 1) % state.dropdownItems.length; - state.dropdownItems[state.dropdownActiveIndex].classList.add("active"); - state.dropdownItems[state.dropdownActiveIndex].scrollIntoView({ block: "nearest" }); - }, - - navigateUp() { - if (!this.isVisible() || state.dropdownItems.length === 0) return; - if (state.dropdownActiveIndex >= 0) state.dropdownItems[state.dropdownActiveIndex].classList.remove("active"); - state.dropdownActiveIndex = state.dropdownActiveIndex <= 0 ? state.dropdownItems.length - 1 : state.dropdownActiveIndex - 1; - state.dropdownItems[state.dropdownActiveIndex].classList.add("active"); - state.dropdownItems[state.dropdownActiveIndex].scrollIntoView({ block: "nearest" }); - }, - - selectActive() { - if (state.dropdownActiveIndex >= 0 && state.dropdownActiveIndex < state.dropdownItems.length) { - state.dropdownItems[state.dropdownActiveIndex].click(); - return true; - } - return false; - }, -}; - - -// --------------------------------------------------------------------------- -// Search Chips Controller — renders active filter chips from parsed query -// --------------------------------------------------------------------------- -export const SearchChips = { - _container: null, - init() { - this._container = document.getElementById("search-chips"); - }, - update(parsed) { - if (!this._container) return; - this._container.innerHTML = ""; - let hasChips = false; - parsed.tags.forEach((tag) => { - this._addChip("tag", `tag:${tag}`, tag); - hasChips = true; - }); - if (parsed.vault) { - this._addChip("vault", `vault:${parsed.vault}`, parsed.vault); - hasChips = true; - } - if (parsed.title) { - this._addChip("title", `title:${parsed.title}`, parsed.title); - hasChips = true; - } - if (parsed.path) { - this._addChip("path", `path:${parsed.path}`, parsed.path); - hasChips = true; - } - if (parsed.ext) { - this._addChip("ext", `ext:${parsed.ext}`, parsed.ext); - hasChips = true; - } - if (parsed.created) { - this._addChip("date", `created:${parsed.created}`, `créé ${parsed.created}`); - hasChips = true; - } - if (parsed.modified) { - this._addChip("date", `modified:${parsed.modified}`, `modifié ${parsed.modified}`); - hasChips = true; - } - if (parsed.size) { - this._addChip("size", `size:${parsed.size}`, `taille ${parsed.size}`); - hasChips = true; - } - this._container.hidden = !hasChips; - }, - clear() { - if (!this._container) return; - this._container.innerHTML = ""; - this._container.hidden = true; - }, - _addChip(type, fullOperator, displayText) { - const chip = el("span", { class: `search-chip search-chip--${type}` }); - const label = el("span", { class: "search-chip__label" }); - label.textContent = fullOperator; - const removeBtn = el("button", { class: "search-chip__remove", title: "Retirer ce filtre", type: "button" }); - removeBtn.innerHTML = ''; - removeBtn.addEventListener("click", () => { - // Remove this operator from the input - const input = document.getElementById("search-input"); - const raw = input.value; - // Remove the operator text from the query - const escaped = fullOperator.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - input.value = raw.replace(new RegExp("\\s*" + escaped + "\\s*", "i"), " ").trim(); - _triggerAdvancedSearch(input.value); - }); - chip.appendChild(label); - chip.appendChild(removeBtn); - this._container.appendChild(chip); - safeCreateIcons(); - }, -}; - - -// --------------------------------------------------------------------------- -// Helper: trigger advanced search from input value -// --------------------------------------------------------------------------- -function _triggerAdvancedSearch(rawQuery) { - const q = (rawQuery || "").trim(); - const vault = document.getElementById("vault-filter").value; - const tagFilter = state.selectedTags.length > 0 ? state.selectedTags.join(",") : null; - state.advancedSearchOffset = 0; - if (q.length > 0 || tagFilter) { - SearchHistory.add(q); - performAdvancedSearch(q, vault, tagFilter); - } else { - SearchChips.clear(); - showWelcome(); - } -} - - -// --------------------------------------------------------------------------- -// Search (enhanced with autocomplete, keyboard nav, global shortcuts) -// --------------------------------------------------------------------------- -// ── Search toggle state ── - -export function initSearch() { - const input = document.getElementById("search-input"); - if (!input) return; - const caseBtn = document.getElementById("rb-case"); - const wordBtn = document.getElementById("rb-word"); - const regexBtn = document.getElementById("rb-regex"); - const filterBtn = document.getElementById("search-filter-btn"); - const clearBtn = document.getElementById("search-clear-btn"); - const filterRow = document.getElementById("search-filter-row"); - const prevBtn = document.getElementById("rb-prev"); - const nextBtn = document.getElementById("rb-next"); - const countEl = document.getElementById("rb-count"); - const resultsBar = document.getElementById("results-bar"); - - function _showResultsBar() { if (resultsBar) resultsBar.style.display = 'flex'; } - function _hideResultsBar() { if (resultsBar) resultsBar.style.display = 'none'; } - - function _updateToggleUI() { - caseBtn.classList.toggle("active", state.searchCaseSensitive); - wordBtn.classList.toggle("active", state.searchWholeWord); - regexBtn.classList.toggle("active", state.searchRegex); - filterBtn.classList.toggle("active", state.searchFilterVisible); - } - - // Toggle buttons - caseBtn.addEventListener("click", () => { state.searchCaseSensitive = !state.searchCaseSensitive; _updateToggleUI(); _research(); }); - if (wordBtn) wordBtn.addEventListener("click", () => { state.searchWholeWord = !state.searchWholeWord; _updateToggleUI(); _research(); }); - if (regexBtn) regexBtn.addEventListener("click", () => { state.searchRegex = !state.searchRegex; _updateToggleUI(); _research(); }); - if (filterBtn) filterBtn.addEventListener("click", () => { state.searchFilterVisible = !state.searchFilterVisible; if (filterRow) filterRow.style.display = state.searchFilterVisible ? "flex" : "none"; _updateToggleUI(); }); - - // ── Result navigation (up/down arrows + Enter) ── - let _searchResultIdx = -1; - let _searchResultItems = []; - - function _updateResultHighlight() { - _searchResultItems.forEach((el, i) => { - el.classList.toggle("search-result-active", i === _searchResultIdx); - }); - if (_searchResultIdx >= 0 && _searchResultIdx < _searchResultItems.length) { - _searchResultItems[_searchResultIdx].scrollIntoView({ block: "nearest", behavior: "smooth" }); - } - const countEl = document.getElementById("rb-count"); - if (countEl) countEl.textContent = _searchResultIdx >= 0 ? `${_searchResultIdx + 1}/${_searchResultItems.length}` : `0/${_searchResultItems.length}`; - } - - function _refreshResultItems() { - _searchResultItems = Array.from(document.querySelectorAll(".search-result-item")); - _searchResultIdx = _searchResultItems.length > 0 ? 0 : -1; - _updateResultHighlight(); - if (_searchResultItems.length > 0) _showResultsBar(); else _hideResultsBar(); - } - - window.navigateSearchResults = function(delta) { - _searchResultItems = Array.from(document.querySelectorAll(".search-result-item")); - if (_searchResultItems.length === 0) return; - _searchResultIdx = Math.max(0, Math.min(_searchResultItems.length - 1, _searchResultIdx + delta)); - _updateResultHighlight(); - }; - - if (prevBtn) prevBtn.addEventListener("click", () => navigateSearchResults(-1)); - if (nextBtn) nextBtn.addEventListener("click", () => navigateSearchResults(1)); - - function _research() { - const q = input.value.trim(); - if (q.length >= _getEffective("min_query_length", 2)) { - clearTimeout(state.searchTimeout); - state.searchTimeout = setTimeout(() => { - const vault = document.getElementById("vault-filter").value; - const tagFilter = state.selectedTags.length > 0 ? state.selectedTags.join(",") : null; - state.advancedSearchOffset = 0; - performAdvancedSearch(q, vault, tagFilter); - }, _getEffective("debounce_ms", 300)); - } - } - - // Keyboard shortcuts - document.addEventListener("keydown", (e) => { - if (e.altKey && !e.ctrlKey && !e.metaKey) { - if (e.key === "c" || e.key === "C") { e.preventDefault(); caseBtn.click(); } - else if (e.key === "w" || e.key === "W") { e.preventDefault(); if (wordBtn) wordBtn.click(); } - else if (e.key === "r" || e.key === "R") { e.preventDefault(); if (regexBtn) regexBtn.click(); } - else if (e.key === "f" || e.key === "F") { e.preventDefault(); if (filterBtn) filterBtn.click(); input.focus(); } - } - }); - - // Initialize sub-controllers - AutocompleteDropdown.init(); - SearchChips.init(); - - // Initially hide clear button - if (clearBtn) clearBtn.style.display = "none"; - - // --- Input handler: autocomplete dropdown only (search triggered on Enter or selection) --- - input.addEventListener("input", () => { - const hasText = input.value.length > 0; - clearBtn.style.display = hasText ? "flex" : "none"; - - // Show autocomplete dropdown while typing - AutocompleteDropdown.populate(input.value, input.selectionStart); - - // Clear results when input becomes empty - if (!hasText) { - SearchChips.clear(); - showWelcome(); - } - }); - - // --- Focus handler: show history dropdown --- - input.addEventListener("focus", () => { - if (input.value.length === 0) { - const historyItems = SearchHistory.filter("").slice(0, 5); - if (historyItems.length > 0) { - AutocompleteDropdown.populate("", 0); - } - } - }); - - // --- Keyboard navigation in dropdown --- - input.addEventListener("keydown", (e) => { - if (AutocompleteDropdown.isVisible()) { - if (e.key === "ArrowDown") { - e.preventDefault(); - AutocompleteDropdown.navigateDown(); - } else if (e.key === "ArrowUp") { - e.preventDefault(); - AutocompleteDropdown.navigateUp(); - } else if (e.key === "Enter") { - // First: check dropdown suggestions (higher priority than search results) - if (AutocompleteDropdown.selectActive()) { - e.preventDefault(); - return; - } - // Second: navigate search results if visible - const results = document.querySelectorAll(".search-result-item"); - if (results.length > 0 && _searchResultIdx >= 0) { - const el = results[_searchResultIdx]; - if (el) { - const vault = el.dataset.vault; - const path = el.dataset.path; - if (vault && path) { TabManager.openPreview(vault, path); e.preventDefault(); return; } - } - } - // Third: execute search - AutocompleteDropdown.hide(); - const q = input.value.trim(); - if (q) { - SearchHistory.add(q); - clearTimeout(state.searchTimeout); - state.advancedSearchOffset = 0; - const vault = document.getElementById("vault-filter").value; - const tagFilter = state.selectedTags.length > 0 ? state.selectedTags.join(",") : null; - performAdvancedSearch(q, vault, tagFilter); - } - e.preventDefault(); - } else if (e.key === "Escape") { - AutocompleteDropdown.hide(); - e.stopPropagation(); - } - } else { - // Dropdown not visible: navigate search results or execute search - if (e.key === "ArrowDown") { - if (window.navigateSearchResults) { window.navigateSearchResults(1); e.preventDefault(); } - } else if (e.key === "ArrowUp") { - if (window.navigateSearchResults) { window.navigateSearchResults(-1); e.preventDefault(); } - } else if (e.key === "Enter") { - const q = input.value.trim(); - if (q) { - SearchHistory.add(q); - clearTimeout(state.searchTimeout); - state.advancedSearchOffset = 0; - const vault = document.getElementById("vault-filter").value; - const tagFilter = state.selectedTags.length > 0 ? state.selectedTags.join(",") : null; - performAdvancedSearch(q, vault, tagFilter); - } - e.preventDefault(); - } - } - }); - - clearBtn.addEventListener("click", () => { - input.value = ""; - if (clearBtn) clearBtn.style.display = "none"; - state.searchCaseSensitive = false; - state.searchWholeWord = false; - state.searchRegex = false; - _updateToggleUI(); - _hideResultsBar(); - SearchChips.clear(); - AutocompleteDropdown.hide(); - showWelcome(); - }); - - // --- Global keyboard shortcuts --- - document.addEventListener("keydown", (e) => { - // Ctrl+K or Cmd+K: focus search - if ((e.ctrlKey || e.metaKey) && e.key === "k") { - e.preventDefault(); - input.focus(); - input.select(); - } - // "/" key: focus search (when not in an input/textarea) - if (e.key === "/" && !_isInputFocused()) { - e.preventDefault(); - input.focus(); - } - // Escape: blur search input and close dropdown - if (e.key === "Escape" && document.activeElement === input) { - AutocompleteDropdown.hide(); - input.blur(); - } - }); -} - -/** Check if user is focused on an input/textarea/contenteditable */ -function _isInputFocused() { - const tag = document.activeElement?.tagName; - if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true; - return document.activeElement?.isContentEditable === true; -} - -// --- Backward-compatible search (existing /api/search endpoint) --- -export async function performSearch(query, vaultFilter, tagFilter) { - if (state.searchAbortController) state.searchAbortController.abort(); - state.searchAbortController = new AbortController(); - const searchId = ++state.currentSearchId; - showLoading(); - let url = `/api/search?q=${encodeURIComponent(query)}&vault=${encodeURIComponent(vaultFilter)}`; - if (tagFilter) url += `&tag=${encodeURIComponent(tagFilter)}`; - try { - const data = await api(url, { signal: state.searchAbortController.signal }); - if (searchId !== state.currentSearchId) return; - renderSearchResults(data, query, tagFilter); - } catch (err) { - if (err.name === "AbortError") return; - if (searchId !== state.currentSearchId) return; - showWelcome(); - } finally { - hideProgressBar(); - if (searchId === state.currentSearchId) state.searchAbortController = null; - } -} - -// --- Advanced search with TF-IDF, facets, pagination --- -export async function performAdvancedSearch(query, vaultFilter, tagFilter, offset, sort) { - if (state.searchAbortController) state.searchAbortController.abort(); - state.searchAbortController = new AbortController(); - const searchId = ++state.currentSearchId; - showLoading(); - - const ofs = offset !== undefined ? offset : state.advancedSearchOffset; - const sortBy = sort || state.advancedSearchSort; - state.advancedSearchLastQuery = query; - - // Update chips from parsed query - const parsed = QueryParser.parse(query); - SearchChips.update(parsed); - - const effectiveLimit = _getEffective("results_per_page", state.ADVANCED_SEARCH_LIMIT); - let url = `/api/search/advanced?q=${encodeURIComponent(query)}&vault=${encodeURIComponent(vaultFilter)}&limit=${effectiveLimit}&offset=${ofs}&sort=${sortBy}`; - if (tagFilter) url += `&tag=${encodeURIComponent(tagFilter)}`; - if (state.searchCaseSensitive) url += "&case_sensitive=true"; - if (state.searchWholeWord) url += "&whole_word=true"; - if (state.searchRegex) url += "®ex=true"; - const includeEl = document.getElementById("search-include-input"); - const excludeEl = document.getElementById("search-exclude-input"); - if (includeEl?.value.trim()) url += `&include_paths=${encodeURIComponent(includeEl.value.trim())}`; - if (excludeEl?.value.trim()) url += `&exclude_paths=${encodeURIComponent(excludeEl.value.trim())}`; - if (parsed.created) url += `&created=${encodeURIComponent(parsed.created)}`; - if (parsed.modified) url += `&modified=${encodeURIComponent(parsed.modified)}`; - if (parsed.size) url += `&size=${encodeURIComponent(parsed.size)}`; - - // Search timeout — abort if server takes too long - const timeoutId = setTimeout( - () => { - if (state.searchAbortController) state.searchAbortController.abort(); - }, - _getEffective("search_timeout_ms", state.SEARCH_TIMEOUT_MS), - ); - - try { - const data = await api(url, { signal: state.searchAbortController.signal }); - clearTimeout(timeoutId); - if (searchId !== state.currentSearchId) return; - state.advancedSearchTotal = data.total; - state.advancedSearchOffset = ofs; - renderAdvancedSearchResults(data, query, tagFilter); - } catch (err) { - clearTimeout(timeoutId); - if (err.name === "AbortError") return; - if (searchId !== state.currentSearchId) return; - - // Try offline search fallback - console.log('[Search] Network failed, trying offline search'); - const offlineResults = await searchOffline(query, vaultFilter); - if (offlineResults && offlineResults.length > 0) { - const data = { - query: query, - vault_filter: vaultFilter, - count: offlineResults.length, - total: offlineResults.length, - offset: 0, - limit: effectiveLimit, - results: offlineResults, - offline: true - }; - state.advancedSearchTotal = offlineResults.length; - state.advancedSearchOffset = 0; - renderAdvancedSearchResults(data, query, tagFilter); - return; - } - - showWelcome(); - } finally { - hideProgressBar(); - if (searchId === state.currentSearchId) state.searchAbortController = null; - } -} - -// --- Legacy search results renderer (kept for backward compat) --- -export function renderSearchResults(data, query, tagFilter) { - const area = document.getElementById("content-area"); - area.innerHTML = ""; - const header = buildSearchResultsHeader(data, query, tagFilter); - area.appendChild(header); - if (data.results.length === 0) { - area.appendChild(el("p", { style: "color:var(--text-muted);margin-top:20px" }, [document.createTextNode(t("search.no_results"))])); - return; - } - const container = el("div", { class: "search-results" }); - data.results.forEach((r) => { - // Apply client-side filtering for hidden files - if (!shouldDisplayPath(r.path, r.vault)) { - return; // Skip this result - } - - const titleDiv = el("div", { class: "search-result-title" }); - if (query && query.trim()) { - highlightSearchText(titleDiv, r.title, query, state.searchCaseSensitive); - } else { - titleDiv.textContent = r.title; - } - const snippetDiv = el("div", { class: "search-result-snippet" }); - if (r.snippet && r.snippet.includes("")) { - snippetDiv.innerHTML = r.snippet; - } else if (query && query.trim() && r.snippet) { - highlightSearchText(snippetDiv, r.snippet, query, state.searchCaseSensitive); - } else { - snippetDiv.textContent = r.snippet || ""; - } - const item = el("div", { class: "search-result-item", "data-vault": r.vault, "data-path": r.path }, [ - el("span", { class: "search-result-ext" }, [document.createTextNode(r.extension || (r.path || "").split(".").pop() || "")]), - titleDiv, - el("div", { class: "search-result-vault" }, [document.createTextNode(r.vault + " / " + r.path)]), - snippetDiv - ]); - if (r.tags && r.tags.length > 0) { - const tagsDiv = el("div", { class: "search-result-tags" }); - r.tags.forEach((tag) => { - if (!TagFilterService.isTagFiltered(tag)) { - const tagEl = el("span", { class: "file-tag" }, [document.createTextNode(`#${tag}`)]); - tagEl.addEventListener("click", (e) => { - e.stopPropagation(); - addTagFilter(tag); - }); - tagsDiv.appendChild(tagEl); - } - }); - if (tagsDiv.children.length > 0) item.appendChild(tagsDiv); - } - item.addEventListener("click", () => TabManager.openPreview(r.vault, r.path)); - item.addEventListener("dblclick", (e) => { e.preventDefault(); TabManager.openPersistent(r.vault, r.path); }); - container.appendChild(item); - }); - area.appendChild(container); -} - -// --- Advanced search results renderer (facets, highlighted snippets, pagination, sort) --- -export function renderAdvancedSearchResults(data, query, tagFilter) { - const area = document.getElementById("content-area"); - area.innerHTML = ""; - - // Update match counter + show floating results bar - var rb = document.getElementById("results-bar"); - var countEl = document.getElementById("rb-count"); - if (countEl) countEl.textContent = `${data.total > 0 ? "1" : "0"}/${data.total}`; - if (rb) rb.style.display = 'flex'; - - // Header with result count and sort controls - const header = el("div", { class: "search-results-header" }); - const summaryText = el("span", { class: "search-results-summary-text" }); - const parsed = QueryParser.parse(query); - const freeText = parsed.freeText; - - if (freeText && tagFilter) { - summaryText.textContent = t('search.results_filtered', {count: data.total, query: freeText}); - } else if (freeText) { - summaryText.textContent = t('search.results_for', {count: data.total, query: freeText}); - } else if (parsed.tags.length > 0 || tagFilter) { - summaryText.textContent = t('search.files_filtered', {count: data.total}); - } else { - summaryText.textContent = t('search.results_count', {count: data.total}); - } - if (data.query_time_ms !== undefined && data.query_time_ms > 0) { - const timeBadge = el("span", { class: "search-time-badge" }); - timeBadge.textContent = t('search.query_time', {time: data.query_time_ms}); - summaryText.appendChild(timeBadge); - } - header.appendChild(summaryText); - - // Active filter badges - const filtersRow = el("div", { class: "search-filters-row" }); - if (state.searchCaseSensitive) filtersRow.appendChild(el("span", { class: "search-filter-badge" }, [document.createTextNode("Aa")])); - if (state.searchWholeWord) filtersRow.appendChild(el("span", { class: "search-filter-badge" }, [document.createTextNode("wd")])); - if (state.searchRegex) filtersRow.appendChild(el("span", { class: "search-filter-badge" }, [document.createTextNode(".*")])); - const inclEl = document.getElementById("search-include-input"); - const exclEl = document.getElementById("search-exclude-input"); - if (inclEl?.value.trim()) filtersRow.appendChild(el("span", { class: "search-filter-badge path" }, [document.createTextNode("incl: " + inclEl.value.trim())])); - if (exclEl?.value.trim()) filtersRow.appendChild(el("span", { class: "search-filter-badge path" }, [document.createTextNode("excl: " + exclEl.value.trim())])); - if (filtersRow.children.length > 0) header.appendChild(filtersRow); - - // Sort controls - const sortDiv = el("div", { class: "search-sort" }); - const btnRelevance = el("button", { class: "search-sort__btn" + (state.advancedSearchSort === "relevance" ? " active" : ""), type: "button" }); - btnRelevance.textContent = "Pertinence"; - btnRelevance.addEventListener("click", () => { - state.advancedSearchSort = "relevance"; - state.advancedSearchOffset = 0; - const vault = document.getElementById("vault-filter").value; - performAdvancedSearch(query, vault, tagFilter, 0, "relevance"); - }); - const btnDate = el("button", { class: "search-sort__btn" + (state.advancedSearchSort === "modified" ? " active" : ""), type: "button" }); - btnDate.textContent = "Date"; - btnDate.addEventListener("click", () => { - state.advancedSearchSort = "modified"; - state.advancedSearchOffset = 0; - const vault = document.getElementById("vault-filter").value; - performAdvancedSearch(query, vault, tagFilter, 0, "modified"); - }); - sortDiv.appendChild(btnRelevance); - sortDiv.appendChild(btnDate); - header.appendChild(sortDiv); - - // Save search button - const saveBtn = el("button", { class: "search-save-btn", type: "button", title: t("search.save_search") }); - saveBtn.innerHTML = ' Sauver'; - saveBtn.addEventListener("click", async () => { - const inclEl = document.getElementById("search-include-input"); - const exclEl = document.getElementById("search-exclude-input"); - try { - await api("/api/saved-searches", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - query: query, - vault: document.getElementById("vault-filter")?.value || "all", - case_sensitive: state.searchCaseSensitive, - whole_word: state.searchWholeWord, - regex: state.searchRegex, - include_paths: inclEl?.value || "", - exclude_paths: exclEl?.value || "", - }), - }); - showToast(t("search.saved"), "success"); - loadSavedSearches(); - } catch (err) { showToast("Erreur: " + err.message, "error"); } - }); - header.appendChild(saveBtn); - area.appendChild(header); - - // Active sidebar tag chips - if (state.selectedTags.length > 0) { - const activeTags = el("div", { class: "search-results-active-tags" }); - state.selectedTags.forEach((tag) => { - const removeBtn = el( - "button", - { - class: "search-results-active-tag-remove", - title: `Retirer ${tag} du filtre`, - }, - [document.createTextNode("×")], - ); - removeBtn.addEventListener("click", (e) => { - e.stopPropagation(); - removeTagFilter(tag); - }); - const chip = el("span", { class: "search-results-active-tag" }, [document.createTextNode(`#${tag}`), removeBtn]); - activeTags.appendChild(chip); - }); - area.appendChild(activeTags); - } - - // Facets panel - if (data.facets && (Object.keys(data.facets.tags || {}).length > 0 || Object.keys(data.facets.vaults || {}).length > 0)) { - const facetsDiv = el("div", { class: "search-facets" }); - - // Vault facets - const vaultFacets = data.facets.vaults || {}; - if (Object.keys(vaultFacets).length > 1) { - const group = el("div", { class: "search-facets__group" }); - const label = el("span", { class: "search-facets__label" }); - label.textContent = "Vaults"; - group.appendChild(label); - for (const [vaultName, count] of Object.entries(vaultFacets)) { - const item = el("span", { class: "search-facets__item" }); - item.innerHTML = `${vaultName} ${count}`; - item.addEventListener("click", () => { - const input = document.getElementById("search-input"); - // Add vault: operator - const current = input.value.replace(/vault:\S+\s*/gi, "").trim(); - input.value = current + " vault:" + vaultName; - _triggerAdvancedSearch(input.value); - }); - group.appendChild(item); - } - facetsDiv.appendChild(group); - } - - // Tag facets - const tagFacets = data.facets.tags || {}; - if (Object.keys(tagFacets).length > 0) { - const group = el("div", { class: "search-facets__group" }); - const label = el("span", { class: "search-facets__label" }); - label.textContent = "Tags"; - group.appendChild(label); - const entries = Object.entries(tagFacets).slice(0, 12); - for (const [tagName, count] of entries) { - const item = el("span", { class: "search-facets__item" }); - item.innerHTML = `#${tagName} ${count}`; - item.addEventListener("click", () => { - addTagFilter(tagName); - }); - group.appendChild(item); - } - facetsDiv.appendChild(group); - } - - area.appendChild(facetsDiv); - } - - // Empty state - if (data.results.length === 0) { - area.appendChild(el("p", { style: "color:var(--text-muted);margin-top:20px" }, [document.createTextNode(t("search.no_results"))])); - return; - } - - // Results list - const container = el("div", { class: "search-results" }); - data.results.forEach((r) => { - // Apply client-side filtering for hidden files - if (!shouldDisplayPath(r.path, r.vault)) { - return; // Skip this result - } - - const titleDiv = el("div", { class: "search-result-title" }); - if (freeText) { - highlightSearchText(titleDiv, r.title, freeText, state.searchCaseSensitive); - } else { - titleDiv.textContent = r.title; - } - - // Snippet — use HTML from backend (already has tags) - const snippetDiv = el("div", { class: "search-result-snippet search-result__snippet" }); - if (r.snippet && r.snippet.includes("")) { - snippetDiv.innerHTML = r.snippet; - } else if (freeText && r.snippet) { - highlightSearchText(snippetDiv, r.snippet, freeText, state.searchCaseSensitive); - } else { - snippetDiv.textContent = r.snippet || ""; - } - - // Score badge - const scoreEl = el("span", { class: "search-result-score", style: "font-size:0.7rem;color:var(--text-muted);margin-left:8px" }); - scoreEl.textContent = `score: ${r.score}`; - - const vaultPath = el("div", { class: "search-result-vault" }, [document.createTextNode(r.vault + " / " + r.path), scoreEl]); - - const item = el("div", { class: "search-result-item", "data-vault": r.vault, "data-path": r.path }, [ - el("span", { class: "search-result-ext" }, [document.createTextNode(r.extension || (r.path || "").split(".").pop() || "")]), - titleDiv, vaultPath, snippetDiv - ]); - - if (r.tags && r.tags.length > 0) { - const tagsDiv = el("div", { class: "search-result-tags" }); - r.tags.forEach((tag) => { - if (!TagFilterService.isTagFiltered(tag)) { - const tagEl = el("span", { class: "file-tag" }, [document.createTextNode(`#${tag}`)]); - tagEl.addEventListener("click", (e) => { - e.stopPropagation(); - addTagFilter(tag); - }); - tagsDiv.appendChild(tagEl); - } - }); - if (tagsDiv.children.length > 0) item.appendChild(tagsDiv); - } - - item.addEventListener("click", () => TabManager.openPreview(r.vault, r.path)); - item.addEventListener("dblclick", (e) => { e.preventDefault(); TabManager.openPersistent(r.vault, r.path); }); - container.appendChild(item); - }); - area.appendChild(container); - - // Pagination - if (data.total > state.ADVANCED_SEARCH_LIMIT) { - const paginationDiv = el("div", { class: "search-pagination" }); - const prevBtn = el("button", { class: "search-pagination__btn", type: "button" }); - prevBtn.textContent = t('search.previous'); - prevBtn.disabled = state.advancedSearchOffset === 0; - prevBtn.addEventListener("click", () => { - state.advancedSearchOffset = Math.max(0, state.advancedSearchOffset - state.ADVANCED_SEARCH_LIMIT); - const vault = document.getElementById("vault-filter").value; - performAdvancedSearch(query, vault, tagFilter, state.advancedSearchOffset); - document.getElementById("content-area").scrollTop = 0; - }); - - const info = el("span", { class: "search-pagination__info" }); - const from = state.advancedSearchOffset + 1; - const to = Math.min(state.advancedSearchOffset + state.ADVANCED_SEARCH_LIMIT, data.total); - info.textContent = `${from}–${to} sur ${data.total}`; - - const nextBtn = el("button", { class: "search-pagination__btn", type: "button" }); - nextBtn.textContent = "Suivant →"; - nextBtn.disabled = state.advancedSearchOffset + state.ADVANCED_SEARCH_LIMIT >= data.total; - nextBtn.addEventListener("click", () => { - state.advancedSearchOffset += state.ADVANCED_SEARCH_LIMIT; - const vault = document.getElementById("vault-filter").value; - performAdvancedSearch(query, vault, tagFilter, state.advancedSearchOffset); - document.getElementById("content-area").scrollTop = 0; - }); - - paginationDiv.appendChild(prevBtn); - paginationDiv.appendChild(info); - paginationDiv.appendChild(nextBtn); - area.appendChild(paginationDiv); - } - - safeCreateIcons(); - // Initialize result navigation (select first result) - setTimeout(() => { if (window.navigateSearchResults) window.navigateSearchResults(0); }, 50); -} - - diff --git a/desktop/frontend-static/js/sidebar.js b/desktop/frontend-static/js/sidebar.js deleted file mode 100644 index b4146e0..0000000 --- a/desktop/frontend-static/js/sidebar.js +++ /dev/null @@ -1,1124 +0,0 @@ -import { state } from './state.js'; -import { safeCreateIcons, getFileIcon, flushIcons } from './utils.js'; -import { api } from './auth.js'; -import { populateCustomDropdown, TabManager, closeMobileSidebar, ContextMenuManager } from './ui.js'; -import { _populateRecentVaultFilter, switchSidebarTab } from './config.js'; -import { el, icon, getVaultIcon, smallBadge, attachTreeItemActionButton, attachTreeItemLongPress, showWelcome, appendHighlightedText } from './viewer.js'; -import { performAdvancedSearch } from './search.js'; -import { t } from './i18n.js'; - -// --------------------------------------------------------------------------- -// Vault context switching -// --------------------------------------------------------------------------- -function initVaultContext() { - const filter = document.getElementById("vault-filter"); - const quickSelect = document.getElementById("vault-quick-select"); - if (!filter || !quickSelect) return; - - filter.addEventListener("change", async () => { - await setSelectedVaultContext(filter.value, { focusVault: filter.value !== "all" }); - }); - - quickSelect.addEventListener("change", async () => { - await setSelectedVaultContext(quickSelect.value, { focusVault: quickSelect.value !== "all" }); - }); -} - -async function setSelectedVaultContext(vaultName, options) { - state.selectedContextVault = vaultName; - state.showingSource = false; - state.cachedRawSource = null; - syncVaultSelectors(); - await refreshSidebarForContext(); - await refreshTagsForContext(); - - // Synchroniser le dashboard et les fichiers récents - if (typeof DashboardRecentWidget !== "undefined" && DashboardRecentWidget.load) { - DashboardRecentWidget.load(vaultName); - } - if (typeof DashboardBookmarkWidget !== "undefined" && DashboardBookmarkWidget.load) { - DashboardBookmarkWidget.load(vaultName); - } - if (state.activeSidebarTab === "recent") { - loadRecentFiles(vaultName === "all" ? null : vaultName); - } - - showWelcome(); - // If a specific vault is selected, switch to vault home page - if (vaultName !== "all") { - import('./vaulthome.js').then(m => m.showVaultHome(vaultName, '')); - } - if (options && options.focusVault && vaultName !== "all") { - await focusVaultInSidebar(vaultName); - } -} - -function syncVaultSelectors() { - const filter = document.getElementById("vault-filter"); - const quickSelect = document.getElementById("vault-quick-select"); - const recentFilter = document.getElementById("recent-vault-filter"); - const dashboardFilter = document.getElementById("dashboard-vault-filter"); - const contextText = document.getElementById("vault-context-text"); - - if (filter) filter.value = state.selectedContextVault; - if (quickSelect) quickSelect.value = state.selectedContextVault; - if (recentFilter) recentFilter.value = state.selectedContextVault === "all" ? "" : state.selectedContextVault; - if (dashboardFilter) dashboardFilter.value = state.selectedContextVault; - - // Mise à jour visuelle des dropdowns personnalisés - updateCustomDropdownVisual("vault-filter-dropdown", state.selectedContextVault); - updateCustomDropdownVisual("vault-quick-select-dropdown", state.selectedContextVault); - - // Update vault context indicator - if (contextText) { - contextText.textContent = state.selectedContextVault === "all" ? "All" : state.selectedContextVault; - } - // Apply color class to the indicator - const indicator = document.getElementById("vault-context-indicator"); - if (indicator) { - indicator.classList.remove("vault-ctx-all", "vault-ctx-vault", "vault-ctx-dir"); - if (state.selectedContextVault === "all") { - indicator.classList.add("vault-ctx-all"); - } else { - indicator.classList.add("vault-ctx-vault"); - } - } -} - -/** - * Updates the visual state of a custom dropdown based on its current value. - */ -function updateCustomDropdownVisual(dropdownId, value) { - const dropdown = document.getElementById(dropdownId); - if (!dropdown) return; - - const selectedText = dropdown.querySelector(".custom-dropdown-selected"); - const options = dropdown.querySelectorAll(".custom-dropdown-option"); - - options.forEach((opt) => { - const optValue = opt.getAttribute("data-value"); - if (optValue === value) { - opt.classList.add("selected"); - if (selectedText) selectedText.textContent = opt.textContent; - } else { - opt.classList.remove("selected"); - } - }); -} - -function scrollTreeItemIntoView(element, alignToTop) { - if (!element) return; - const scrollContainer = document.getElementById("sidebar-panel-vaults"); - if (!scrollContainer) return; - - const containerRect = scrollContainer.getBoundingClientRect(); - const elementRect = element.getBoundingClientRect(); - const isAbove = elementRect.top < containerRect.top; - const isBelow = elementRect.bottom > containerRect.bottom; - - if (!isAbove && !isBelow && !alignToTop) return; - - const currentTop = scrollContainer.scrollTop; - const offsetTop = element.offsetTop; - const shouldCenter = alignToTop === "center"; - const centeredTop = Math.max(0, currentTop + (elementRect.top - containerRect.top) - (containerRect.height / 2) + (elementRect.height / 2)); - const targetTop = shouldCenter - ? centeredTop - : alignToTop - ? Math.max(0, offsetTop - 60) - : Math.max(0, currentTop + (elementRect.top - containerRect.top) - containerRect.height * 0.35); - - scrollContainer.scrollTo({ - top: targetTop, - behavior: "smooth", - }); -} - -async function refreshSidebarForContext() { - const container = document.getElementById("vault-tree"); - container.innerHTML = ""; - - const vaultsToShow = state.selectedContextVault === "all" ? state.allVaults : state.allVaults.filter((v) => v.name === state.selectedContextVault); - - vaultsToShow.forEach((v) => { - const vaultItem = el("div", { class: "tree-item vault-item", "data-vault": v.name }, [icon("chevron-right", 14), getVaultIcon(v.name, 16), el("span", { class: "tree-item-text" }, [document.createTextNode(v.name)]), smallBadge(v.file_count)]); - vaultItem.addEventListener("click", () => toggleVault(vaultItem, v.name)); - - vaultItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - const isReadonly = false; - ContextMenuManager.show(e.clientX, e.clientY, v.name, '', 'vault', isReadonly); - }); - attachTreeItemActionButton(vaultItem, v.name, "", "vault", false); - attachTreeItemLongPress(vaultItem, () => ({ vault: v.name, path: "", type: "vault", isReadonly: false })); - - container.appendChild(vaultItem); - - const childContainer = el("div", { class: "tree-children collapsed", id: `vault-children-${v.name}` }); - container.appendChild(childContainer); - }); - - safeCreateIcons(); -} - -async function focusVaultInSidebar(vaultName) { - switchSidebarTab("vaults"); - const vaultItem = document.querySelector(`.vault-item[data-vault="${CSS.escape(vaultName)}"]`); - if (!vaultItem) return; - document.querySelectorAll(".vault-item.focused").forEach((el) => el.classList.remove("focused")); - vaultItem.classList.add("focused"); - const childContainer = document.getElementById(`vault-children-${vaultName}`); - if (childContainer && childContainer.classList.contains("collapsed")) { - await toggleVault(vaultItem, vaultName, true); - } - scrollTreeItemIntoView(vaultItem, false); -} - -async function refreshTagsForContext() { - const vaultParam = state.selectedContextVault === "all" ? "" : `?vault=${encodeURIComponent(state.selectedContextVault)}`; - const data = await api(`/api/tags${vaultParam}`); - const filteredTags = TagFilterService.filterTags(data.tags); - renderTagCloud(filteredTags); -} - -// --------------------------------------------------------------------------- -// Helper: Check if path should be displayed based on hideHiddenFiles setting -// --------------------------------------------------------------------------- -function shouldDisplayPath(path, vaultName) { - // Get hideHiddenFiles setting for this vault (default: false = show all) - const settings = state.vaultSettings[vaultName] || { hideHiddenFiles: false }; - - if (!settings.hideHiddenFiles) { - // Show all files - return true; - } - - // Check if any segment of the path starts with a dot (hidden) - const segments = path.split("/").filter(Boolean); - for (const segment of segments) { - if (segment.startsWith(".")) { - return false; // Hide this path - } - } - - return true; // Show this path -} - -async function loadVaultSettings() { - try { - const settings = await api("/api/vaults/settings/all"); - state.vaultSettings = settings; - } catch (err) { - console.error("Failed to load vault settings:", err); - state.vaultSettings = {}; - } -} - -// --------------------------------------------------------------------------- -// Sidebar — Vault tree -// --------------------------------------------------------------------------- -async function loadVaults() { - const vaults = await api("/api/vaults"); - state.allVaults = vaults; - const container = document.getElementById("vault-tree"); - container.innerHTML = ""; - - // Prepare dropdown options - const dropdownOptions = [{ value: "all", text: t('help.all_vaults') }, ...vaults.map((v) => ({ value: v.name, text: v.name }))]; - - // Populate custom dropdowns - populateCustomDropdown("vault-filter-dropdown", dropdownOptions, "all"); - populateCustomDropdown("vault-quick-select-dropdown", dropdownOptions, "all"); - - // Populate standard selects - _populateRecentVaultFilter(); - if (typeof DashboardRecentWidget !== "undefined" && DashboardRecentWidget.populateVaultFilter) { - DashboardRecentWidget.populateVaultFilter(); - } - - vaults.forEach((v) => { - // Sidebar tree entry - const vaultItem = el("div", { class: "tree-item vault-item", "data-vault": v.name }, [icon("chevron-right", 14), getVaultIcon(v.name, 16), el("span", { class: "tree-item-text" }, [document.createTextNode(v.name)]), smallBadge(v.file_count)]); - vaultItem.addEventListener("click", () => toggleVault(vaultItem, v.name)); - - vaultItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - const isReadonly = false; - ContextMenuManager.show(e.clientX, e.clientY, v.name, '', 'vault', isReadonly); - }); - attachTreeItemActionButton(vaultItem, v.name, "", "vault", false); - attachTreeItemLongPress(vaultItem, () => ({ vault: v.name, path: "", type: "vault", isReadonly: false })); - - container.appendChild(vaultItem); - - const childContainer = el("div", { class: "tree-children collapsed", id: `vault-children-${v.name}` }); - container.appendChild(childContainer); - }); - - syncVaultSelectors(); - safeCreateIcons(); -} - -/** - * Refreshes the sidebar tree while preserving the expanded state of vaults and folders. - * Optimized to avoid a full sidebar wipe and minimize visible loading states. - */ -/** - * Incrementally update a directory container without wiping existing DOM. - * Only adds new items, removes deleted ones, and updates changed ones. - */ -async function incrementalLoadDirectory(vaultName, dirPath, container) { - let data; - try { - const url = `/api/browse/${encodeURIComponent(vaultName)}?path=${encodeURIComponent(dirPath)}`; - data = await api(url); - } catch (err) { - // Server unavailable — keep existing content - return; - } - - // Build a map of existing DOM elements by path - const existingItems = {}; - const existingChildren = {}; // path -> child container (for directories) - for (let i = 0; i < container.children.length; i++) { - const child = container.children[i]; - if (child.classList.contains("tree-item") && child.dataset.path) { - existingItems[child.dataset.path] = child; - // The next sibling should be the tree-children container for this directory - if (i + 1 < container.children.length) { - const next = container.children[i + 1]; - if (next.classList.contains("tree-children")) { - existingChildren[child.dataset.path] = next; - } - } - } - } - - const fragment = document.createDocumentFragment(); - - data.items.forEach((item) => { - if (!shouldDisplayPath(item.path, vaultName)) return; - - const existing = existingItems[item.path]; - - if (existing) { - // Item already exists — reuse it, but update text/badge if needed - const textEl = existing.querySelector(".tree-item-text"); - const displayName = item.type === "file" && item.name.match(/\.md$/i) - ? item.name.replace(/\.md$/i, "") - : item.name; - if (textEl && textEl.textContent !== displayName) { - textEl.textContent = displayName; - } - // Update badge for directories - if (item.type === "directory") { - const badge = existing.querySelector(".badge-small"); - const newBadge = `(${item.children_count})`; - if (badge && badge.textContent !== newBadge) { - badge.textContent = newBadge; - } else if (!badge) { - existing.appendChild(smallBadge(item.children_count)); - } - } - fragment.appendChild(existing); - // Also re-add the child container for directories - if (item.type === "directory" && existingChildren[item.path]) { - fragment.appendChild(existingChildren[item.path]); - } else if (item.type === "directory") { - // Directory existed but no child container — create one - const subContainer = el("div", { class: "tree-children collapsed", id: `dir-${vaultName}-${item.path}` }); - fragment.appendChild(subContainer); - } - } else { - // New item — create it - if (item.type === "directory") { - const dirItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path }, [icon("chevron-right", 14), icon("folder", 16), el("span", { class: "tree-item-text" }, [document.createTextNode(item.name)]), smallBadge(item.children_count)]); - attachTreeItemActionButton(dirItem, vaultName, item.path, "directory", false); - attachTreeItemLongPress(dirItem, () => ({ vault: vaultName, path: item.path, type: "directory", isReadonly: false })); - fragment.appendChild(dirItem); - - const subContainer = el("div", { class: "tree-children collapsed", id: `dir-${vaultName}-${item.path}` }); - fragment.appendChild(subContainer); - - dirItem.addEventListener("click", async () => { - scrollTreeItemIntoView(dirItem, false); - if (subContainer.classList.contains("collapsed")) { - if (subContainer.children.length === 0) { - await loadDirectory(vaultName, item.path, subContainer); - } - subContainer.classList.remove("collapsed"); - const chev = dirItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-down"); - safeCreateIcons(); - } else { - subContainer.classList.add("collapsed"); - const chev = dirItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-right"); - safeCreateIcons(); - } - }); - - dirItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, "directory", false); - }); - } else { - const fileIconName = getFileIcon(item.name); - const displayName = item.name.match(/\.md$/i) ? item.name.replace(/\.md$/i, "") : item.name; - const fileItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path }, [icon(fileIconName, 16), el("span", { class: "tree-item-text" }, [document.createTextNode(displayName)])]); - attachTreeItemActionButton(fileItem, vaultName, item.path, "file", false); - attachTreeItemLongPress(fileItem, () => ({ vault: vaultName, path: item.path, type: "file", isReadonly: false })); - fileItem.addEventListener("click", () => { - scrollTreeItemIntoView(fileItem, false); - if (window.innerWidth <= 768) { - TabManager.openPersistent(vaultName, item.path); - } else { - TabManager.openPreview(vaultName, item.path); - } - closeMobileSidebar(); - }); - - fileItem.addEventListener("dblclick", (e) => { - e.preventDefault(); - TabManager.openPersistent(vaultName, item.path); - }); - - fileItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, "file", false); - }); - - fragment.appendChild(fileItem); - } - } - }); - - // Replace container content in a single batch operation to avoid flash - container.textContent = ""; - container.appendChild(fragment); -} - -export async function refreshSidebarTreePreservingState() { - // 1. Capture expanded states - const expandedVaults = Array.from(document.querySelectorAll(".vault-item")) - .filter((v) => { - const children = document.getElementById(`vault-children-${v.dataset.vault}`); - return children && !children.classList.contains("collapsed"); - }) - .map((v) => v.dataset.vault); - - const expandedDirs = Array.from(document.querySelectorAll(".tree-item[data-path]")) - .filter((item) => { - const vault = item.dataset.vault; - const path = item.dataset.path; - const children = document.getElementById(`dir-${vault}-${path}`); - return children && !children.classList.contains("collapsed"); - }) - .map((item) => ({ vault: item.dataset.vault, path: item.dataset.path })); - - const selectedItem = document.querySelector(".tree-item.path-selected"); - const selectedState = selectedItem ? { vault: selectedItem.dataset.vault, path: selectedItem.dataset.path } : null; - - // 2. Soft update: vault names/counts without wiping the tree - try { - const vaults = await api("/api/vaults"); - state.allVaults = vaults; - vaults.forEach((v) => { - const vItem = document.querySelector(`.vault-item[data-vault="${CSS.escape(v.name)}"]`); - if (vItem) { - const badge = vItem.querySelector(".badge-small"); - if (badge) badge.textContent = `(${v.file_count})`; - } - }); - } catch (e) { - console.warn("Soft vault refresh failed, falling back to full reload", e); - await loadVaults(); - return; - } - - // 3. Incrementally update expanded vaults (no DOM wipe) - for (const vName of expandedVaults) { - const container = document.getElementById(`vault-children-${vName}`); - if (container) { - await incrementalLoadDirectory(vName, "", container); - } - } - - // 4. Incrementally update expanded directories (parents first, no DOM wipe) - expandedDirs.sort((a, b) => a.path.split("/").length - b.path.split("/").length); - for (const dir of expandedDirs) { - const container = document.getElementById(`dir-${dir.vault}-${dir.path}`); - if (container) { - try { - await incrementalLoadDirectory(dir.vault, dir.path, container); - container.classList.remove("collapsed"); - const dItem = document.querySelector(`.tree-item[data-vault="${CSS.escape(dir.vault)}"][data-path="${CSS.escape(dir.path)}"]`); - if (dItem) { - const chev = dItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-down"); - } - } catch (e) { - console.error(`Failed to refresh directory ${dir.vault}/${dir.path}`, e); - } - } - } - - // 5. Restore selection - if (selectedState) { - await focusPathInSidebar(selectedState.vault, selectedState.path, { alignToTop: false }); - } - - safeCreateIcons(); -} - -async function toggleVault(itemEl, vaultName, forceExpand) { - const childContainer = document.getElementById(`vault-children-${vaultName}`); - if (!childContainer) return; - - scrollTreeItemIntoView(itemEl, false); - - const shouldExpand = forceExpand || childContainer.classList.contains("collapsed"); - - if (shouldExpand) { - // Expand — load children if empty - if (childContainer.children.length === 0) { - await loadDirectory(vaultName, "", childContainer); - } - childContainer.classList.remove("collapsed"); - // Swap chevron - const chevron = itemEl.querySelector("[data-lucide]"); - if (chevron) chevron.setAttribute("data-lucide", "chevron-down"); - safeCreateIcons(); - } else { - childContainer.classList.add("collapsed"); - const chevron = itemEl.querySelector("[data-lucide]"); - if (chevron) chevron.setAttribute("data-lucide", "chevron-right"); - safeCreateIcons(); - } -} - -async function expandDirectoryInSidebar(vaultName, dirPath, dirItem) { - const subContainer = document.getElementById(`dir-${vaultName}-${dirPath}`); - if (!subContainer) return null; - - if (subContainer.children.length === 0) { - await loadDirectory(vaultName, dirPath, subContainer); - } - - subContainer.classList.remove("collapsed"); - if (dirItem) { - const chevron = dirItem.querySelector("[data-lucide]"); - if (chevron) chevron.setAttribute("data-lucide", "chevron-down"); - } - safeCreateIcons(); - return subContainer; -} - -async function focusPathInSidebar(vaultName, targetPath, options) { - switchSidebarTab("vaults"); - - const vaultItem = document.querySelector(`.vault-item[data-vault="${CSS.escape(vaultName)}"]`); - if (!vaultItem) return; - - document.querySelectorAll(".vault-item.focused").forEach((el) => el.classList.remove("focused")); - vaultItem.classList.add("focused"); - - const vaultContainer = document.getElementById(`vault-children-${vaultName}`); - if (!vaultContainer) return; - - if (vaultContainer.classList.contains("collapsed")) { - await toggleVault(vaultItem, vaultName, true); - } - - if (!targetPath) { - // Clear any previous path selection - document.querySelectorAll(".tree-item.path-selected").forEach((el) => el.classList.remove("path-selected")); - scrollTreeItemIntoView(vaultItem, options && options.alignToTop); - return; - } - - const segments = targetPath.split("/").filter(Boolean); - let currentContainer = vaultContainer; - let cumulativePath = ""; - let lastTargetItem = null; - - for (let index = 0; index < segments.length; index++) { - cumulativePath += (cumulativePath ? "/" : "") + segments[index]; - - let targetItem = null; - try { - targetItem = currentContainer.querySelector(`.tree-item[data-vault="${CSS.escape(vaultName)}"][data-path="${CSS.escape(cumulativePath)}"]`); - } catch (e) { - targetItem = null; - } - - if (!targetItem) { - return; - } - - lastTargetItem = targetItem; - - const isLastSegment = index === segments.length - 1; - if (!isLastSegment) { - const nextContainer = await expandDirectoryInSidebar(vaultName, cumulativePath, targetItem); - if (nextContainer) { - currentContainer = nextContainer; - } - } - } - - if (lastTargetItem && options && options.expandTarget) { - await expandDirectoryInSidebar(vaultName, targetPath, lastTargetItem); - } - - // Clear previous path selections and highlight the final target - document.querySelectorAll(".tree-item.path-selected").forEach((el) => el.classList.remove("path-selected")); - if (lastTargetItem) { - lastTargetItem.classList.add("path-selected"); - } - - scrollTreeItemIntoView(lastTargetItem, options && options.alignToTop); -} - -function getParentDirectoryPath(filePath) { - if (!filePath) return ""; - const segments = filePath.split("/").filter(Boolean); - if (segments.length <= 1) return ""; - segments.pop(); - return segments.join("/"); -} - -function syncActiveFileTreeItem(vaultName, filePath) { - document.querySelectorAll(".tree-item.active").forEach((el) => el.classList.remove("active")); - if (!vaultName || !filePath) return; - const selector = `.tree-item[data-vault="${CSS.escape(vaultName)}"][data-path="${CSS.escape(filePath)}"]`; - try { - const active = document.querySelector(selector); - if (active) active.classList.add("active"); - } catch (e) { - /* selector might fail on special chars */ - } -} - -async function loadDirectory(vaultName, dirPath, container) { - // Only show the loading spinner if the container is currently empty - const isEmpty = container.children.length === 0; - if (isEmpty) { - container.innerHTML = '
    '; - } - - var data; - try { - const url = `/api/browse/${encodeURIComponent(vaultName)}?path=${encodeURIComponent(dirPath)}`; - data = await api(url); - } catch (err) { - container.innerHTML = '
    Erreur de chargement
    '; - return; - } - container.innerHTML = ""; - - const fragment = document.createDocumentFragment(); - - data.items.forEach((item) => { - // Apply client-side filtering for hidden files - if (!shouldDisplayPath(item.path, vaultName)) { - return; // Skip this item - } - - if (item.type === "directory") { - const dirItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path }, [icon("chevron-right", 14), icon("folder", 16), el("span", { class: "tree-item-text" }, [document.createTextNode(item.name)]), smallBadge(item.children_count)]); - attachTreeItemActionButton(dirItem, vaultName, item.path, "directory", false); - attachTreeItemLongPress(dirItem, () => ({ vault: vaultName, path: item.path, type: "directory", isReadonly: false })); - fragment.appendChild(dirItem); - - const subContainer = el("div", { class: "tree-children collapsed", id: `dir-${vaultName}-${item.path}` }); - fragment.appendChild(subContainer); - - dirItem.addEventListener("click", async () => { - scrollTreeItemIntoView(dirItem, false); - if (subContainer.classList.contains("collapsed")) { - if (subContainer.children.length === 0) { - await loadDirectory(vaultName, item.path, subContainer); - } - subContainer.classList.remove("collapsed"); - const chev = dirItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-down"); - safeCreateIcons(); - } else { - subContainer.classList.add("collapsed"); - const chev = dirItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-right"); - safeCreateIcons(); - } - }); - - dirItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - const isReadonly = false; - ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, 'directory', isReadonly); - }); - } else { - const fileIconName = getFileIcon(item.name); - const displayName = item.name.match(/\.md$/i) ? item.name.replace(/\.md$/i, "") : item.name; - const fileItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path }, [icon(fileIconName, 16), el("span", { class: "tree-item-text" }, [document.createTextNode(displayName)])]); - attachTreeItemActionButton(fileItem, vaultName, item.path, "file", false); - attachTreeItemLongPress(fileItem, () => ({ vault: vaultName, path: item.path, type: "file", isReadonly: false })); - fileItem.addEventListener("click", () => { - scrollTreeItemIntoView(fileItem, false); - if (window.innerWidth <= 768) { - TabManager.openPersistent(vaultName, item.path); - } else { - TabManager.openPreview(vaultName, item.path); - } - closeMobileSidebar(); - }); - - fileItem.addEventListener("dblclick", (e) => { - e.preventDefault(); - TabManager.openPersistent(vaultName, item.path); - }); - - fileItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - const isReadonly = false; - ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, 'file', isReadonly); - }); - - fragment.appendChild(fileItem); - } - }); - - container.appendChild(fragment); - safeCreateIcons(); -} - -// --------------------------------------------------------------------------- -// Sidebar filter -// --------------------------------------------------------------------------- -function initSidebarFilter() { - const input = document.getElementById("sidebar-filter-input"); - const caseBtn = document.getElementById("sidebar-filter-case-btn"); - const clearBtn = document.getElementById("sidebar-filter-clear-btn"); - - input.addEventListener("input", () => { - const hasText = input.value.length > 0; - clearBtn.style.display = hasText ? "flex" : "none"; - clearTimeout(state.filterDebounce); - state.filterDebounce = setTimeout(async () => { - const q = state.sidebarFilterCaseSensitive ? input.value.trim() : input.value.trim().toLowerCase(); - if (hasText) { - if (state.activeSidebarTab === "vaults") { - await performTreeSearch(q); - } else { - filterTagCloud(q); - } - } else { - if (state.activeSidebarTab === "vaults") { - await restoreSidebarTree(); - } else { - filterTagCloud(""); - } - } - }, 220); - }); - - caseBtn.addEventListener("click", async () => { - state.sidebarFilterCaseSensitive = !state.sidebarFilterCaseSensitive; - caseBtn.classList.toggle("active"); - const q = state.sidebarFilterCaseSensitive ? input.value.trim() : input.value.trim().toLowerCase(); - if (input.value.trim()) { - if (state.activeSidebarTab === "vaults") { - await performTreeSearch(q); - } else { - filterTagCloud(q); - } - } - }); - - clearBtn.addEventListener("click", async () => { - input.value = ""; - clearBtn.style.display = "none"; - state.sidebarFilterCaseSensitive = false; - caseBtn.classList.remove("active"); - clearTimeout(state.filterDebounce); - if (state.activeSidebarTab === "vaults") { - await restoreSidebarTree(); - } else { - filterTagCloud(""); - } - }); - - clearBtn.style.display = "none"; -} - -async function performTreeSearch(query) { - if (!query) { - await restoreSidebarTree(); - return; - } - - try { - const vaultParam = state.selectedContextVault === "all" ? "all" : state.selectedContextVault; - const url = `/api/tree-search?q=${encodeURIComponent(query)}&vault=${encodeURIComponent(vaultParam)}`; - const data = await api(url); - renderFilteredSidebarResults(query, data.results); - } catch (err) { - console.error("Tree search error:", err); - renderFilteredSidebarResults(query, []); - } -} - -async function restoreSidebarTree() { - await refreshSidebarForContext(); - if (state.currentVault) { - focusPathInSidebar(state.currentVault, state.currentPath || "", { alignToTop: false }).catch(() => {}); - } -} - -function renderFilteredSidebarResults(query, results) { - const container = document.getElementById("vault-tree"); - container.innerHTML = ""; - - const grouped = new Map(); - results.forEach((result) => { - if (!grouped.has(result.vault)) { - grouped.set(result.vault, []); - } - grouped.get(result.vault).push(result); - }); - - if (grouped.size === 0) { - container.appendChild(el("div", { class: "sidebar-filter-empty" }, [document.createTextNode(t("sidebar.no_results"))])); - return; - } - - grouped.forEach((entries, vaultName) => { - entries.sort((a, b) => a.path.localeCompare(b.path, undefined, { sensitivity: "base" })); - - const vaultHeader = el("div", { class: "tree-item vault-item filter-results-header", "data-vault": vaultName }, [getVaultIcon(vaultName, 16), document.createTextNode(` ${vaultName} `), smallBadge(entries.length)]); - container.appendChild(vaultHeader); - - const resultsWrapper = el("div", { class: "filter-results-group" }); - entries.forEach((entry) => { - const resultItem = el( - "div", - { - class: `tree-item filter-result-item filter-result-${entry.type}`, - "data-vault": entry.vault, - "data-path": entry.path, - "data-type": entry.type, - }, - [icon(entry.type === "directory" ? "folder" : getFileIcon(entry.name), 16)], - ); - - const textWrap = el("div", { class: "filter-result-text" }); - const primary = el("div", { class: "filter-result-primary" }); - appendHighlightedText(primary, entry.name, query, state.sidebarFilterCaseSensitive); - const secondary = el("div", { class: "filter-result-secondary" }); - appendHighlightedText(secondary, entry.path, query, state.sidebarFilterCaseSensitive); - textWrap.appendChild(primary); - textWrap.appendChild(secondary); - resultItem.appendChild(textWrap); - - resultItem.addEventListener("click", async () => { - const input = document.getElementById("sidebar-filter-input"); - const clearBtn = document.getElementById("sidebar-filter-clear-btn"); - if (input) input.value = ""; - if (clearBtn) clearBtn.style.display = "none"; - await restoreSidebarTree(); - if (entry.type === "directory") { - await focusPathInSidebar(entry.vault, entry.path, { alignToTop: true, expandTarget: true }); - } else { - if (window.innerWidth <= 768) { - await TabManager.openPersistent(entry.vault, entry.path); - } else { - await TabManager.openPreview(entry.vault, entry.path); - } - await focusPathInSidebar(entry.vault, getParentDirectoryPath(entry.path), { alignToTop: true, expandTarget: true }); - syncActiveFileTreeItem(entry.vault, entry.path); - } - closeMobileSidebar(); - }); - - resultsWrapper.appendChild(resultItem); - }); - - container.appendChild(resultsWrapper); - }); - - flushIcons(); -} - -function filterSidebarTree(query) { - const tree = document.getElementById("vault-tree"); - const items = tree.querySelectorAll(".tree-item"); - const containers = tree.querySelectorAll(".tree-children"); - - if (!query) { - items.forEach((item) => item.classList.remove("filtered-out")); - containers.forEach((c) => { - c.classList.remove("filtered-out"); - // Keep current collapsed state when clearing filter - }); - return; - } - - // First pass: mark all as filtered out - items.forEach((item) => item.classList.add("filtered-out")); - containers.forEach((c) => c.classList.add("filtered-out")); - - // Second pass: find matching items and mark them + ancestors + descendants - const matchingItems = new Set(); - - items.forEach((item) => { - const text = state.sidebarFilterCaseSensitive ? item.textContent : item.textContent.toLowerCase(); - const searchQuery = state.sidebarFilterCaseSensitive ? query : query.toLowerCase(); - if (text.includes(searchQuery)) { - matchingItems.add(item); - item.classList.remove("filtered-out"); - - // Show all ancestor containers - let parent = item.parentElement; - while (parent && parent !== tree) { - parent.classList.remove("filtered-out"); - if (parent.classList.contains("tree-children")) { - parent.classList.remove("collapsed"); - } - parent = parent.parentElement; - } - - // If this is a directory (has a children container after it), show all descendants - const nextEl = item.nextElementSibling; - if (nextEl && nextEl.classList.contains("tree-children")) { - nextEl.classList.remove("filtered-out"); - nextEl.classList.remove("collapsed"); - // Recursively show all children in this container - showAllDescendants(nextEl); - } - } - }); - - // Third pass: show items that are descendants of matching directories - // and ensure their containers are visible - matchingItems.forEach((item) => { - const nextEl = item.nextElementSibling; - if (nextEl && nextEl.classList.contains("tree-children")) { - const children = nextEl.querySelectorAll(".tree-item"); - children.forEach((child) => child.classList.remove("filtered-out")); - } - }); -} - -function showAllDescendants(container) { - const items = container.querySelectorAll(".tree-item"); - items.forEach((item) => { - item.classList.remove("filtered-out"); - // If this item has children, also show them - const nextEl = item.nextElementSibling; - if (nextEl && nextEl.classList.contains("tree-children")) { - nextEl.classList.remove("filtered-out"); - nextEl.classList.remove("collapsed"); - } - }); - // Also ensure all nested containers are visible - const nestedContainers = container.querySelectorAll(".tree-children"); - nestedContainers.forEach((c) => { - c.classList.remove("filtered-out"); - c.classList.remove("collapsed"); - }); -} - -function filterTagCloud(query) { - const tags = document.querySelectorAll("#tag-cloud .tag-item"); - tags.forEach((tag) => { - const text = state.sidebarFilterCaseSensitive ? tag.textContent : tag.textContent.toLowerCase(); - const searchQuery = state.sidebarFilterCaseSensitive ? query : query.toLowerCase(); - if (!query || text.includes(searchQuery)) { - tag.classList.remove("filtered-out"); - } else { - tag.classList.add("filtered-out"); - } - }); -} - -// --------------------------------------------------------------------------- -// Tag Filter Service -// --------------------------------------------------------------------------- -const TagFilterService = { - defaultFilters: [ - { pattern: "#<% ... %>", regex: "#<%.*%>", enabled: true }, - { pattern: "#{{ ... }}", regex: "#\\{\\{.*\\}\\}", enabled: true }, - { pattern: "#{ ... }", regex: "#\\{.*\\}", enabled: true }, - ], - - getConfig() { - const stored = localStorage.getItem("obsigate-tag-filters"); - if (stored) { - try { - return JSON.parse(stored); - } catch (e) { - return { tagFilters: this.defaultFilters }; - } - } - return { tagFilters: this.defaultFilters }; - }, - - saveConfig(config) { - localStorage.setItem("obsigate-tag-filters", JSON.stringify(config)); - }, - - patternToRegex(pattern) { - // 1. Escape ALL special regex characters - // We use a broader set including * and . - let regex = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - - // 2. Convert escaped '*' to '.*' (wildcard) - regex = regex.replace(/\\\*/g, ".*"); - - // 3. Convert escaped '...' (or any sequence of 2+ dots like ..) to '.*' - // We also handle optional whitespace around it to make it more user-friendly - regex = regex.replace(/\s*\\\.{2,}\s*/g, ".*"); - - return regex; - }, - - isTagFiltered(tag) { - const config = this.getConfig(); - const filters = config.tagFilters || this.defaultFilters; - const tagWithHash = `#${tag}`; - - for (const filter of filters) { - if (!filter.enabled) continue; - try { - // Robustly handle regex with or without ^/$ - let patternStr = filter.regex; - if (!patternStr.startsWith("^")) patternStr = "^" + patternStr; - if (!patternStr.endsWith("$")) patternStr = patternStr + "$"; - - const regex = new RegExp(patternStr); - if (regex.test(tagWithHash)) { - return true; - } - } catch (e) { - console.warn("Invalid regex:", filter.regex, e); - } - } - return false; - }, - - filterTags(tags) { - const filtered = {}; - Object.entries(tags).forEach(([tag, count]) => { - if (!this.isTagFiltered(tag)) { - filtered[tag] = count; - } - }); - return filtered; - }, -}; - -// --------------------------------------------------------------------------- -// Tags -// --------------------------------------------------------------------------- -async function loadTags() { - const data = await api("/api/tags"); - const filteredTags = TagFilterService.filterTags(data.tags); - renderTagCloud(filteredTags); -} - -function renderTagCloud(tags) { - const cloud = document.getElementById("tag-cloud"); - cloud.innerHTML = ""; - - const counts = Object.values(tags); - if (counts.length === 0) return; - - const maxCount = Math.max(...counts); - const minSize = 0.7; - const maxSize = 1.25; - - Object.entries(tags).forEach(([tag, count]) => { - const ratio = maxCount > 1 ? (count - 1) / (maxCount - 1) : 0; - const size = minSize + ratio * (maxSize - minSize); - const tagEl = el("span", { class: "tag-item", style: `font-size:${size}rem` }, [document.createTextNode(`#${tag}`)]); - tagEl.addEventListener("click", () => searchByTag(tag)); - cloud.appendChild(tagEl); - }); -} - -function addTagFilter(tag) { - if (!state.selectedTags.includes(tag)) { - state.selectedTags.push(tag); - performTagSearch(); - } -} - -function removeTagFilter(tag) { - state.selectedTags = state.selectedTags.filter((t) => t !== tag); - if (state.selectedTags.length > 0) { - performTagSearch(); - } else { - const input = document.getElementById("search-input"); - if (input.value.trim()) { - performAdvancedSearch(input.value.trim(), document.getElementById("vault-filter").value, null); - } else { - showWelcome(); - } - } -} - -function performTagSearch() { - const input = document.getElementById("search-input"); - const query = input.value.trim(); - const vault = document.getElementById("vault-filter").value; - performAdvancedSearch(query, vault, state.selectedTags.length > 0 ? state.selectedTags.join(",") : null); -} - -function buildSearchResultsHeader(data, query, tagFilter) { - const header = el("div", { class: "search-results-header" }); - const summaryText = el("span", { class: "search-results-summary-text" }); - - if (query && tagFilter) { - summaryText.textContent = `${data.count} résultat(s) pour "${query}" avec les tags`; - } else if (query) { - summaryText.textContent = `${data.count} résultat(s) pour "${query}"`; - } else if (tagFilter) { - summaryText.textContent = `${data.count} fichier(s) avec les tags`; - } else { - summaryText.textContent = `${data.count} résultat(s)`; - } - - header.appendChild(summaryText); - - if (state.selectedTags.length > 0) { - const activeTags = el("div", { class: "search-results-active-tags" }); - state.selectedTags.forEach((tag) => { - const removeBtn = el( - "button", - { - class: "search-results-active-tag-remove", - title: `Retirer ${tag} du filtre`, - "aria-label": `Retirer ${tag} du filtre`, - }, - [document.createTextNode("×")], - ); - removeBtn.addEventListener("click", (e) => { - e.stopPropagation(); - removeTagFilter(tag); - }); - - const chip = el("span", { class: "search-results-active-tag" }, [document.createTextNode(`#${tag}`), removeBtn]); - activeTags.appendChild(chip); - }); - header.appendChild(activeTags); - } - - return header; -} - -function searchByTag(tag) { - addTagFilter(tag); -} - - -export { initVaultContext, setSelectedVaultContext, syncVaultSelectors, shouldDisplayPath, loadVaults, loadVaultSettings, initSidebarFilter, TagFilterService, loadTags, scrollTreeItemIntoView, refreshSidebarForContext, focusVaultInSidebar, focusPathInSidebar, refreshTagsForContext, syncActiveFileTreeItem, searchByTag, addTagFilter, buildSearchResultsHeader, removeTagFilter }; diff --git a/desktop/frontend-static/js/sidebar_raw.js b/desktop/frontend-static/js/sidebar_raw.js deleted file mode 100644 index 2c5a070..0000000 --- a/desktop/frontend-static/js/sidebar_raw.js +++ /dev/null @@ -1,1087 +0,0 @@ -// --------------------------------------------------------------------------- -// Vault context switching -// --------------------------------------------------------------------------- -function initVaultContext() { - const filter = document.getElementById("vault-filter"); - const quickSelect = document.getElementById("vault-quick-select"); - if (!filter || !quickSelect) return; - - filter.addEventListener("change", async () => { - await setSelectedVaultContext(filter.value, { focusVault: filter.value !== "all" }); - }); - - quickSelect.addEventListener("change", async () => { - await setSelectedVaultContext(quickSelect.value, { focusVault: quickSelect.value !== "all" }); - }); -} - -async function setSelectedVaultContext(vaultName, options) { - selectedContextVault = vaultName; - showingSource = false; - cachedRawSource = null; - syncVaultSelectors(); - await refreshSidebarForContext(); - await refreshTagsForContext(); - - // Synchroniser le dashboard et les fichiers récents - if (typeof DashboardRecentWidget !== "undefined" && DashboardRecentWidget.load) { - DashboardRecentWidget.load(vaultName); - } - if (typeof DashboardBookmarkWidget !== "undefined" && DashboardBookmarkWidget.load) { - DashboardBookmarkWidget.load(vaultName); - } - if (activeSidebarTab === "recent") { - loadRecentFiles(vaultName === "all" ? null : vaultName); - } - - showWelcome(); - if (options && options.focusVault && vaultName !== "all") { - await focusVaultInSidebar(vaultName); - } -} - -function syncVaultSelectors() { - const filter = document.getElementById("vault-filter"); - const quickSelect = document.getElementById("vault-quick-select"); - const recentFilter = document.getElementById("recent-vault-filter"); - const dashboardFilter = document.getElementById("dashboard-vault-filter"); - const contextText = document.getElementById("vault-context-text"); - - if (filter) filter.value = selectedContextVault; - if (quickSelect) quickSelect.value = selectedContextVault; - if (recentFilter) recentFilter.value = selectedContextVault === "all" ? "" : selectedContextVault; - if (dashboardFilter) dashboardFilter.value = selectedContextVault; - - // Mise à jour visuelle des dropdowns personnalisés - updateCustomDropdownVisual("vault-filter-dropdown", selectedContextVault); - updateCustomDropdownVisual("vault-quick-select-dropdown", selectedContextVault); - - // Update vault context indicator - if (contextText) { - contextText.textContent = selectedContextVault === "all" ? "All" : selectedContextVault; - } -} - -/** - * Updates the visual state of a custom dropdown based on its current value. - */ -function updateCustomDropdownVisual(dropdownId, value) { - const dropdown = document.getElementById(dropdownId); - if (!dropdown) return; - - const selectedText = dropdown.querySelector(".custom-dropdown-selected"); - const options = dropdown.querySelectorAll(".custom-dropdown-option"); - - options.forEach((opt) => { - const optValue = opt.getAttribute("data-value"); - if (optValue === value) { - opt.classList.add("selected"); - if (selectedText) selectedText.textContent = opt.textContent; - } else { - opt.classList.remove("selected"); - } - }); -} - -function scrollTreeItemIntoView(element, alignToTop) { - if (!element) return; - const scrollContainer = document.getElementById("sidebar-panel-vaults"); - if (!scrollContainer) return; - - const containerRect = scrollContainer.getBoundingClientRect(); - const elementRect = element.getBoundingClientRect(); - const isAbove = elementRect.top < containerRect.top; - const isBelow = elementRect.bottom > containerRect.bottom; - - if (!isAbove && !isBelow && !alignToTop) return; - - const currentTop = scrollContainer.scrollTop; - const offsetTop = element.offsetTop; - const shouldCenter = alignToTop === "center"; - const centeredTop = Math.max(0, currentTop + (elementRect.top - containerRect.top) - (containerRect.height / 2) + (elementRect.height / 2)); - const targetTop = shouldCenter - ? centeredTop - : alignToTop - ? Math.max(0, offsetTop - 60) - : Math.max(0, currentTop + (elementRect.top - containerRect.top) - containerRect.height * 0.35); - - scrollContainer.scrollTo({ - top: targetTop, - behavior: "smooth", - }); -} - -async function refreshSidebarForContext() { - const container = document.getElementById("vault-tree"); - container.innerHTML = ""; - - const vaultsToShow = selectedContextVault === "all" ? allVaults : allVaults.filter((v) => v.name === selectedContextVault); - - vaultsToShow.forEach((v) => { - const vaultItem = el("div", { class: "tree-item vault-item", "data-vault": v.name }, [icon("chevron-right", 14), getVaultIcon(v.name, 16), el("span", { class: "tree-item-text" }, [document.createTextNode(v.name)]), smallBadge(v.file_count)]); - vaultItem.addEventListener("click", () => toggleVault(vaultItem, v.name)); - - vaultItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - const isReadonly = false; - ContextMenuManager.show(e.clientX, e.clientY, v.name, '', 'vault', isReadonly); - }); - attachTreeItemActionButton(vaultItem, v.name, "", "vault", false); - attachTreeItemLongPress(vaultItem, () => ({ vault: v.name, path: "", type: "vault", isReadonly: false })); - - container.appendChild(vaultItem); - - const childContainer = el("div", { class: "tree-children collapsed", id: `vault-children-${v.name}` }); - container.appendChild(childContainer); - }); - - safeCreateIcons(); -} - -async function focusVaultInSidebar(vaultName) { - switchSidebarTab("vaults"); - const vaultItem = document.querySelector(`.vault-item[data-vault="${CSS.escape(vaultName)}"]`); - if (!vaultItem) return; - document.querySelectorAll(".vault-item.focused").forEach((el) => el.classList.remove("focused")); - vaultItem.classList.add("focused"); - const childContainer = document.getElementById(`vault-children-${vaultName}`); - if (childContainer && childContainer.classList.contains("collapsed")) { - await toggleVault(vaultItem, vaultName, true); - } - scrollTreeItemIntoView(vaultItem, false); -} - -async function refreshTagsForContext() { - const vaultParam = selectedContextVault === "all" ? "" : `?vault=${encodeURIComponent(selectedContextVault)}`; - const data = await api(`/api/tags${vaultParam}`); - const filteredTags = TagFilterService.filterTags(data.tags); - renderTagCloud(filteredTags); -} - -// --------------------------------------------------------------------------- -// Helper: Check if path should be displayed based on hideHiddenFiles setting -// --------------------------------------------------------------------------- -function shouldDisplayPath(path, vaultName) { - // Get hideHiddenFiles setting for this vault (default: false = show all) - const settings = vaultSettings[vaultName] || { hideHiddenFiles: false }; - - if (!settings.hideHiddenFiles) { - // Show all files - return true; - } - - // Check if any segment of the path starts with a dot (hidden) - const segments = path.split("/").filter(Boolean); - for (const segment of segments) { - if (segment.startsWith(".")) { - return false; // Hide this path - } - } - - return true; // Show this path -} - -async function loadVaultSettings() { - try { - const settings = await api("/api/vaults/settings/all"); - vaultSettings = settings; - } catch (err) { - console.error("Failed to load vault settings:", err); - vaultSettings = {}; - } -} - -// --------------------------------------------------------------------------- -// Sidebar — Vault tree -// --------------------------------------------------------------------------- -async function loadVaults() { - const vaults = await api("/api/vaults"); - allVaults = vaults; - const container = document.getElementById("vault-tree"); - container.innerHTML = ""; - - // Prepare dropdown options - const dropdownOptions = [{ value: "all", text: t('help.all_vaults') }, ...vaults.map((v) => ({ value: v.name, text: v.name }))]; - - // Populate custom dropdowns - populateCustomDropdown("vault-filter-dropdown", dropdownOptions, "all"); - populateCustomDropdown("vault-quick-select-dropdown", dropdownOptions, "all"); - - // Populate standard selects - _populateRecentVaultFilter(); - if (typeof DashboardRecentWidget !== "undefined" && DashboardRecentWidget.populateVaultFilter) { - DashboardRecentWidget.populateVaultFilter(); - } - - vaults.forEach((v) => { - // Sidebar tree entry - const vaultItem = el("div", { class: "tree-item vault-item", "data-vault": v.name }, [icon("chevron-right", 14), getVaultIcon(v.name, 16), el("span", { class: "tree-item-text" }, [document.createTextNode(v.name)]), smallBadge(v.file_count)]); - vaultItem.addEventListener("click", () => toggleVault(vaultItem, v.name)); - - vaultItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - const isReadonly = false; - ContextMenuManager.show(e.clientX, e.clientY, v.name, '', 'vault', isReadonly); - }); - attachTreeItemActionButton(vaultItem, v.name, "", "vault", false); - attachTreeItemLongPress(vaultItem, () => ({ vault: v.name, path: "", type: "vault", isReadonly: false })); - - container.appendChild(vaultItem); - - const childContainer = el("div", { class: "tree-children collapsed", id: `vault-children-${v.name}` }); - container.appendChild(childContainer); - }); - - syncVaultSelectors(); - safeCreateIcons(); -} - -/** - * Refreshes the sidebar tree while preserving the expanded state of vaults and folders. - * Optimized to avoid a full sidebar wipe and minimize visible loading states. - */ -/** - * Incrementally update a directory container without wiping existing DOM. - * Only adds new items, removes deleted ones, and updates changed ones. - */ -async function incrementalLoadDirectory(vaultName, dirPath, container) { - let data; - try { - const url = `/api/browse/${encodeURIComponent(vaultName)}?path=${encodeURIComponent(dirPath)}`; - data = await api(url); - } catch (err) { - // Server unavailable — keep existing content - return; - } - - // Build a map of existing DOM elements by path - const existingItems = {}; - const existingChildren = {}; // path -> child container (for directories) - for (let i = 0; i < container.children.length; i++) { - const child = container.children[i]; - if (child.classList.contains("tree-item") && child.dataset.path) { - existingItems[child.dataset.path] = child; - // The next sibling should be the tree-children container for this directory - if (i + 1 < container.children.length) { - const next = container.children[i + 1]; - if (next.classList.contains("tree-children")) { - existingChildren[child.dataset.path] = next; - } - } - } - } - - const fragment = document.createDocumentFragment(); - - data.items.forEach((item) => { - if (!shouldDisplayPath(item.path, vaultName)) return; - - const existing = existingItems[item.path]; - - if (existing) { - // Item already exists — reuse it, but update text/badge if needed - const textEl = existing.querySelector(".tree-item-text"); - const displayName = item.type === "file" && item.name.match(/\.md$/i) - ? item.name.replace(/\.md$/i, "") - : item.name; - if (textEl && textEl.textContent !== displayName) { - textEl.textContent = displayName; - } - // Update badge for directories - if (item.type === "directory") { - const badge = existing.querySelector(".badge-small"); - const newBadge = `(${item.children_count})`; - if (badge && badge.textContent !== newBadge) { - badge.textContent = newBadge; - } else if (!badge) { - existing.appendChild(smallBadge(item.children_count)); - } - } - fragment.appendChild(existing); - // Also re-add the child container for directories - if (item.type === "directory" && existingChildren[item.path]) { - fragment.appendChild(existingChildren[item.path]); - } else if (item.type === "directory") { - // Directory existed but no child container — create one - const subContainer = el("div", { class: "tree-children collapsed", id: `dir-${vaultName}-${item.path}` }); - fragment.appendChild(subContainer); - } - } else { - // New item — create it - if (item.type === "directory") { - const dirItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path }, [icon("chevron-right", 14), icon("folder", 16), el("span", { class: "tree-item-text" }, [document.createTextNode(item.name)]), smallBadge(item.children_count)]); - attachTreeItemActionButton(dirItem, vaultName, item.path, "directory", false); - attachTreeItemLongPress(dirItem, () => ({ vault: vaultName, path: item.path, type: "directory", isReadonly: false })); - fragment.appendChild(dirItem); - - const subContainer = el("div", { class: "tree-children collapsed", id: `dir-${vaultName}-${item.path}` }); - fragment.appendChild(subContainer); - - dirItem.addEventListener("click", async () => { - scrollTreeItemIntoView(dirItem, false); - if (subContainer.classList.contains("collapsed")) { - if (subContainer.children.length === 0) { - await loadDirectory(vaultName, item.path, subContainer); - } - subContainer.classList.remove("collapsed"); - const chev = dirItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-down"); - safeCreateIcons(); - } else { - subContainer.classList.add("collapsed"); - const chev = dirItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-right"); - safeCreateIcons(); - } - }); - - dirItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, "directory", false); - }); - } else { - const fileIconName = getFileIcon(item.name); - const displayName = item.name.match(/\.md$/i) ? item.name.replace(/\.md$/i, "") : item.name; - const fileItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path }, [icon(fileIconName, 16), el("span", { class: "tree-item-text" }, [document.createTextNode(displayName)])]); - attachTreeItemActionButton(fileItem, vaultName, item.path, "file", false); - attachTreeItemLongPress(fileItem, () => ({ vault: vaultName, path: item.path, type: "file", isReadonly: false })); - fileItem.addEventListener("click", () => { - scrollTreeItemIntoView(fileItem, false); - TabManager.openPreview(vaultName, item.path); - closeMobileSidebar(); - }); - - fileItem.addEventListener("dblclick", (e) => { - e.preventDefault(); - TabManager.openPersistent(vaultName, item.path); - }); - - fileItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, "file", false); - }); - - fragment.appendChild(fileItem); - } - } - }); - - // Replace container content in a single batch operation to avoid flash - container.textContent = ""; - container.appendChild(fragment); -} - -async function refreshSidebarTreePreservingState() { - // 1. Capture expanded states - const expandedVaults = Array.from(document.querySelectorAll(".vault-item")) - .filter((v) => { - const children = document.getElementById(`vault-children-${v.dataset.vault}`); - return children && !children.classList.contains("collapsed"); - }) - .map((v) => v.dataset.vault); - - const expandedDirs = Array.from(document.querySelectorAll(".tree-item[data-path]")) - .filter((item) => { - const vault = item.dataset.vault; - const path = item.dataset.path; - const children = document.getElementById(`dir-${vault}-${path}`); - return children && !children.classList.contains("collapsed"); - }) - .map((item) => ({ vault: item.dataset.vault, path: item.dataset.path })); - - const selectedItem = document.querySelector(".tree-item.path-selected"); - const selectedState = selectedItem ? { vault: selectedItem.dataset.vault, path: selectedItem.dataset.path } : null; - - // 2. Soft update: vault names/counts without wiping the tree - try { - const vaults = await api("/api/vaults"); - allVaults = vaults; - vaults.forEach((v) => { - const vItem = document.querySelector(`.vault-item[data-vault="${CSS.escape(v.name)}"]`); - if (vItem) { - const badge = vItem.querySelector(".badge-small"); - if (badge) badge.textContent = `(${v.file_count})`; - } - }); - } catch (e) { - console.warn("Soft vault refresh failed, falling back to full reload", e); - await loadVaults(); - return; - } - - // 3. Incrementally update expanded vaults (no DOM wipe) - for (const vName of expandedVaults) { - const container = document.getElementById(`vault-children-${vName}`); - if (container) { - await incrementalLoadDirectory(vName, "", container); - } - } - - // 4. Incrementally update expanded directories (parents first, no DOM wipe) - expandedDirs.sort((a, b) => a.path.split("/").length - b.path.split("/").length); - for (const dir of expandedDirs) { - const container = document.getElementById(`dir-${dir.vault}-${dir.path}`); - if (container) { - try { - await incrementalLoadDirectory(dir.vault, dir.path, container); - container.classList.remove("collapsed"); - const dItem = document.querySelector(`.tree-item[data-vault="${CSS.escape(dir.vault)}"][data-path="${CSS.escape(dir.path)}"]`); - if (dItem) { - const chev = dItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-down"); - } - } catch (e) { - console.error(`Failed to refresh directory ${dir.vault}/${dir.path}`, e); - } - } - } - - // 5. Restore selection - if (selectedState) { - await focusPathInSidebar(selectedState.vault, selectedState.path, { alignToTop: false }); - } - - safeCreateIcons(); -} - -async function toggleVault(itemEl, vaultName, forceExpand) { - const childContainer = document.getElementById(`vault-children-${vaultName}`); - if (!childContainer) return; - - scrollTreeItemIntoView(itemEl, false); - - const shouldExpand = forceExpand || childContainer.classList.contains("collapsed"); - - if (shouldExpand) { - // Expand — load children if empty - if (childContainer.children.length === 0) { - await loadDirectory(vaultName, "", childContainer); - } - childContainer.classList.remove("collapsed"); - // Swap chevron - const chevron = itemEl.querySelector("[data-lucide]"); - if (chevron) chevron.setAttribute("data-lucide", "chevron-down"); - safeCreateIcons(); - } else { - childContainer.classList.add("collapsed"); - const chevron = itemEl.querySelector("[data-lucide]"); - if (chevron) chevron.setAttribute("data-lucide", "chevron-right"); - safeCreateIcons(); - } -} - -async function expandDirectoryInSidebar(vaultName, dirPath, dirItem) { - const subContainer = document.getElementById(`dir-${vaultName}-${dirPath}`); - if (!subContainer) return null; - - if (subContainer.children.length === 0) { - await loadDirectory(vaultName, dirPath, subContainer); - } - - subContainer.classList.remove("collapsed"); - if (dirItem) { - const chevron = dirItem.querySelector("[data-lucide]"); - if (chevron) chevron.setAttribute("data-lucide", "chevron-down"); - } - safeCreateIcons(); - return subContainer; -} - -async function focusPathInSidebar(vaultName, targetPath, options) { - switchSidebarTab("vaults"); - - const vaultItem = document.querySelector(`.vault-item[data-vault="${CSS.escape(vaultName)}"]`); - if (!vaultItem) return; - - document.querySelectorAll(".vault-item.focused").forEach((el) => el.classList.remove("focused")); - vaultItem.classList.add("focused"); - - const vaultContainer = document.getElementById(`vault-children-${vaultName}`); - if (!vaultContainer) return; - - if (vaultContainer.classList.contains("collapsed")) { - await toggleVault(vaultItem, vaultName, true); - } - - if (!targetPath) { - // Clear any previous path selection - document.querySelectorAll(".tree-item.path-selected").forEach((el) => el.classList.remove("path-selected")); - scrollTreeItemIntoView(vaultItem, options && options.alignToTop); - return; - } - - const segments = targetPath.split("/").filter(Boolean); - let currentContainer = vaultContainer; - let cumulativePath = ""; - let lastTargetItem = null; - - for (let index = 0; index < segments.length; index++) { - cumulativePath += (cumulativePath ? "/" : "") + segments[index]; - - let targetItem = null; - try { - targetItem = currentContainer.querySelector(`.tree-item[data-vault="${CSS.escape(vaultName)}"][data-path="${CSS.escape(cumulativePath)}"]`); - } catch (e) { - targetItem = null; - } - - if (!targetItem) { - return; - } - - lastTargetItem = targetItem; - - const isLastSegment = index === segments.length - 1; - if (!isLastSegment) { - const nextContainer = await expandDirectoryInSidebar(vaultName, cumulativePath, targetItem); - if (nextContainer) { - currentContainer = nextContainer; - } - } - } - - if (lastTargetItem && options && options.expandTarget) { - await expandDirectoryInSidebar(vaultName, targetPath, lastTargetItem); - } - - // Clear previous path selections and highlight the final target - document.querySelectorAll(".tree-item.path-selected").forEach((el) => el.classList.remove("path-selected")); - if (lastTargetItem) { - lastTargetItem.classList.add("path-selected"); - } - - scrollTreeItemIntoView(lastTargetItem, options && options.alignToTop); -} - -function getParentDirectoryPath(filePath) { - if (!filePath) return ""; - const segments = filePath.split("/").filter(Boolean); - if (segments.length <= 1) return ""; - segments.pop(); - return segments.join("/"); -} - -function syncActiveFileTreeItem(vaultName, filePath) { - document.querySelectorAll(".tree-item.active").forEach((el) => el.classList.remove("active")); - if (!vaultName || !filePath) return; - const selector = `.tree-item[data-vault="${CSS.escape(vaultName)}"][data-path="${CSS.escape(filePath)}"]`; - try { - const active = document.querySelector(selector); - if (active) active.classList.add("active"); - } catch (e) { - /* selector might fail on special chars */ - } -} - -async function loadDirectory(vaultName, dirPath, container) { - // Only show the loading spinner if the container is currently empty - const isEmpty = container.children.length === 0; - if (isEmpty) { - container.innerHTML = '
    '; - } - - var data; - try { - const url = `/api/browse/${encodeURIComponent(vaultName)}?path=${encodeURIComponent(dirPath)}`; - data = await api(url); - } catch (err) { - container.innerHTML = '
    Erreur de chargement
    '; - return; - } - container.innerHTML = ""; - - const fragment = document.createDocumentFragment(); - - data.items.forEach((item) => { - // Apply client-side filtering for hidden files - if (!shouldDisplayPath(item.path, vaultName)) { - return; // Skip this item - } - - if (item.type === "directory") { - const dirItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path }, [icon("chevron-right", 14), icon("folder", 16), el("span", { class: "tree-item-text" }, [document.createTextNode(item.name)]), smallBadge(item.children_count)]); - attachTreeItemActionButton(dirItem, vaultName, item.path, "directory", false); - attachTreeItemLongPress(dirItem, () => ({ vault: vaultName, path: item.path, type: "directory", isReadonly: false })); - fragment.appendChild(dirItem); - - const subContainer = el("div", { class: "tree-children collapsed", id: `dir-${vaultName}-${item.path}` }); - fragment.appendChild(subContainer); - - dirItem.addEventListener("click", async () => { - scrollTreeItemIntoView(dirItem, false); - if (subContainer.classList.contains("collapsed")) { - if (subContainer.children.length === 0) { - await loadDirectory(vaultName, item.path, subContainer); - } - subContainer.classList.remove("collapsed"); - const chev = dirItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-down"); - safeCreateIcons(); - } else { - subContainer.classList.add("collapsed"); - const chev = dirItem.querySelector("[data-lucide]"); - if (chev) chev.setAttribute("data-lucide", "chevron-right"); - safeCreateIcons(); - } - }); - - dirItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - const isReadonly = false; - ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, 'directory', isReadonly); - }); - } else { - const fileIconName = getFileIcon(item.name); - const displayName = item.name.match(/\.md$/i) ? item.name.replace(/\.md$/i, "") : item.name; - const fileItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path }, [icon(fileIconName, 16), el("span", { class: "tree-item-text" }, [document.createTextNode(displayName)])]); - attachTreeItemActionButton(fileItem, vaultName, item.path, "file", false); - attachTreeItemLongPress(fileItem, () => ({ vault: vaultName, path: item.path, type: "file", isReadonly: false })); - fileItem.addEventListener("click", () => { - scrollTreeItemIntoView(fileItem, false); - TabManager.openPreview(vaultName, item.path); - closeMobileSidebar(); - }); - - fileItem.addEventListener("dblclick", (e) => { - e.preventDefault(); - TabManager.openPersistent(vaultName, item.path); - }); - - fileItem.addEventListener("contextmenu", (e) => { - e.preventDefault(); - const isReadonly = false; - ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, 'file', isReadonly); - }); - - fragment.appendChild(fileItem); - } - }); - - container.appendChild(fragment); - safeCreateIcons(); -} - -// --------------------------------------------------------------------------- -// Sidebar filter -// --------------------------------------------------------------------------- -function initSidebarFilter() { - const input = document.getElementById("sidebar-filter-input"); - const caseBtn = document.getElementById("sidebar-filter-case-btn"); - const clearBtn = document.getElementById("sidebar-filter-clear-btn"); - - input.addEventListener("input", () => { - const hasText = input.value.length > 0; - clearBtn.style.display = hasText ? "flex" : "none"; - clearTimeout(filterDebounce); - filterDebounce = setTimeout(async () => { - const q = sidebarFilterCaseSensitive ? input.value.trim() : input.value.trim().toLowerCase(); - if (hasText) { - if (activeSidebarTab === "vaults") { - await performTreeSearch(q); - } else { - filterTagCloud(q); - } - } else { - if (activeSidebarTab === "vaults") { - await restoreSidebarTree(); - } else { - filterTagCloud(""); - } - } - }, 220); - }); - - caseBtn.addEventListener("click", async () => { - sidebarFilterCaseSensitive = !sidebarFilterCaseSensitive; - caseBtn.classList.toggle("active"); - const q = sidebarFilterCaseSensitive ? input.value.trim() : input.value.trim().toLowerCase(); - if (input.value.trim()) { - if (activeSidebarTab === "vaults") { - await performTreeSearch(q); - } else { - filterTagCloud(q); - } - } - }); - - clearBtn.addEventListener("click", async () => { - input.value = ""; - clearBtn.style.display = "none"; - sidebarFilterCaseSensitive = false; - caseBtn.classList.remove("active"); - clearTimeout(filterDebounce); - if (activeSidebarTab === "vaults") { - await restoreSidebarTree(); - } else { - filterTagCloud(""); - } - }); - - clearBtn.style.display = "none"; -} - -async function performTreeSearch(query) { - if (!query) { - await restoreSidebarTree(); - return; - } - - try { - const vaultParam = selectedContextVault === "all" ? "all" : selectedContextVault; - const url = `/api/tree-search?q=${encodeURIComponent(query)}&vault=${encodeURIComponent(vaultParam)}`; - const data = await api(url); - renderFilteredSidebarResults(query, data.results); - } catch (err) { - console.error("Tree search error:", err); - renderFilteredSidebarResults(query, []); - } -} - -async function restoreSidebarTree() { - await refreshSidebarForContext(); - if (currentVault) { - focusPathInSidebar(currentVault, currentPath || "", { alignToTop: false }).catch(() => {}); - } -} - -function renderFilteredSidebarResults(query, results) { - const container = document.getElementById("vault-tree"); - container.innerHTML = ""; - - const grouped = new Map(); - results.forEach((result) => { - if (!grouped.has(result.vault)) { - grouped.set(result.vault, []); - } - grouped.get(result.vault).push(result); - }); - - if (grouped.size === 0) { - container.appendChild(el("div", { class: "sidebar-filter-empty" }, [document.createTextNode(t("sidebar.no_results"))])); - return; - } - - grouped.forEach((entries, vaultName) => { - entries.sort((a, b) => a.path.localeCompare(b.path, undefined, { sensitivity: "base" })); - - const vaultHeader = el("div", { class: "tree-item vault-item filter-results-header", "data-vault": vaultName }, [getVaultIcon(vaultName, 16), document.createTextNode(` ${vaultName} `), smallBadge(entries.length)]); - container.appendChild(vaultHeader); - - const resultsWrapper = el("div", { class: "filter-results-group" }); - entries.forEach((entry) => { - const resultItem = el( - "div", - { - class: `tree-item filter-result-item filter-result-${entry.type}`, - "data-vault": entry.vault, - "data-path": entry.path, - "data-type": entry.type, - }, - [icon(entry.type === "directory" ? "folder" : getFileIcon(entry.name), 16)], - ); - - const textWrap = el("div", { class: "filter-result-text" }); - const primary = el("div", { class: "filter-result-primary" }); - appendHighlightedText(primary, entry.name, query, sidebarFilterCaseSensitive); - const secondary = el("div", { class: "filter-result-secondary" }); - appendHighlightedText(secondary, entry.path, query, sidebarFilterCaseSensitive); - textWrap.appendChild(primary); - textWrap.appendChild(secondary); - resultItem.appendChild(textWrap); - - resultItem.addEventListener("click", async () => { - const input = document.getElementById("sidebar-filter-input"); - const clearBtn = document.getElementById("sidebar-filter-clear-btn"); - if (input) input.value = ""; - if (clearBtn) clearBtn.style.display = "none"; - await restoreSidebarTree(); - if (entry.type === "directory") { - await focusPathInSidebar(entry.vault, entry.path, { alignToTop: true, expandTarget: true }); - } else { - await TabManager.openPreview(entry.vault, entry.path); - await focusPathInSidebar(entry.vault, getParentDirectoryPath(entry.path), { alignToTop: true, expandTarget: true }); - syncActiveFileTreeItem(entry.vault, entry.path); - } - closeMobileSidebar(); - }); - - resultsWrapper.appendChild(resultItem); - }); - - container.appendChild(resultsWrapper); - }); - - flushIcons(); -} - -function filterSidebarTree(query) { - const tree = document.getElementById("vault-tree"); - const items = tree.querySelectorAll(".tree-item"); - const containers = tree.querySelectorAll(".tree-children"); - - if (!query) { - items.forEach((item) => item.classList.remove("filtered-out")); - containers.forEach((c) => { - c.classList.remove("filtered-out"); - // Keep current collapsed state when clearing filter - }); - return; - } - - // First pass: mark all as filtered out - items.forEach((item) => item.classList.add("filtered-out")); - containers.forEach((c) => c.classList.add("filtered-out")); - - // Second pass: find matching items and mark them + ancestors + descendants - const matchingItems = new Set(); - - items.forEach((item) => { - const text = sidebarFilterCaseSensitive ? item.textContent : item.textContent.toLowerCase(); - const searchQuery = sidebarFilterCaseSensitive ? query : query.toLowerCase(); - if (text.includes(searchQuery)) { - matchingItems.add(item); - item.classList.remove("filtered-out"); - - // Show all ancestor containers - let parent = item.parentElement; - while (parent && parent !== tree) { - parent.classList.remove("filtered-out"); - if (parent.classList.contains("tree-children")) { - parent.classList.remove("collapsed"); - } - parent = parent.parentElement; - } - - // If this is a directory (has a children container after it), show all descendants - const nextEl = item.nextElementSibling; - if (nextEl && nextEl.classList.contains("tree-children")) { - nextEl.classList.remove("filtered-out"); - nextEl.classList.remove("collapsed"); - // Recursively show all children in this container - showAllDescendants(nextEl); - } - } - }); - - // Third pass: show items that are descendants of matching directories - // and ensure their containers are visible - matchingItems.forEach((item) => { - const nextEl = item.nextElementSibling; - if (nextEl && nextEl.classList.contains("tree-children")) { - const children = nextEl.querySelectorAll(".tree-item"); - children.forEach((child) => child.classList.remove("filtered-out")); - } - }); -} - -function showAllDescendants(container) { - const items = container.querySelectorAll(".tree-item"); - items.forEach((item) => { - item.classList.remove("filtered-out"); - // If this item has children, also show them - const nextEl = item.nextElementSibling; - if (nextEl && nextEl.classList.contains("tree-children")) { - nextEl.classList.remove("filtered-out"); - nextEl.classList.remove("collapsed"); - } - }); - // Also ensure all nested containers are visible - const nestedContainers = container.querySelectorAll(".tree-children"); - nestedContainers.forEach((c) => { - c.classList.remove("filtered-out"); - c.classList.remove("collapsed"); - }); -} - -function filterTagCloud(query) { - const tags = document.querySelectorAll("#tag-cloud .tag-item"); - tags.forEach((tag) => { - const text = sidebarFilterCaseSensitive ? tag.textContent : tag.textContent.toLowerCase(); - const searchQuery = sidebarFilterCaseSensitive ? query : query.toLowerCase(); - if (!query || text.includes(searchQuery)) { - tag.classList.remove("filtered-out"); - } else { - tag.classList.add("filtered-out"); - } - }); -} - -// --------------------------------------------------------------------------- -// Tag Filter Service -// --------------------------------------------------------------------------- -const TagFilterService = { - defaultFilters: [ - { pattern: "#<% ... %>", regex: "#<%.*%>", enabled: true }, - { pattern: "#{{ ... }}", regex: "#\\{\\{.*\\}\\}", enabled: true }, - { pattern: "#{ ... }", regex: "#\\{.*\\}", enabled: true }, - ], - - getConfig() { - const stored = localStorage.getItem("obsigate-tag-filters"); - if (stored) { - try { - return JSON.parse(stored); - } catch (e) { - return { tagFilters: this.defaultFilters }; - } - } - return { tagFilters: this.defaultFilters }; - }, - - saveConfig(config) { - localStorage.setItem("obsigate-tag-filters", JSON.stringify(config)); - }, - - patternToRegex(pattern) { - // 1. Escape ALL special regex characters - // We use a broader set including * and . - let regex = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - - // 2. Convert escaped '*' to '.*' (wildcard) - regex = regex.replace(/\\\*/g, ".*"); - - // 3. Convert escaped '...' (or any sequence of 2+ dots like ..) to '.*' - // We also handle optional whitespace around it to make it more user-friendly - regex = regex.replace(/\s*\\\.{2,}\s*/g, ".*"); - - return regex; - }, - - isTagFiltered(tag) { - const config = this.getConfig(); - const filters = config.tagFilters || this.defaultFilters; - const tagWithHash = `#${tag}`; - - for (const filter of filters) { - if (!filter.enabled) continue; - try { - // Robustly handle regex with or without ^/$ - let patternStr = filter.regex; - if (!patternStr.startsWith("^")) patternStr = "^" + patternStr; - if (!patternStr.endsWith("$")) patternStr = patternStr + "$"; - - const regex = new RegExp(patternStr); - if (regex.test(tagWithHash)) { - return true; - } - } catch (e) { - console.warn("Invalid regex:", filter.regex, e); - } - } - return false; - }, - - filterTags(tags) { - const filtered = {}; - Object.entries(tags).forEach(([tag, count]) => { - if (!this.isTagFiltered(tag)) { - filtered[tag] = count; - } - }); - return filtered; - }, -}; - -// --------------------------------------------------------------------------- -// Tags -// --------------------------------------------------------------------------- -async function loadTags() { - const data = await api("/api/tags"); - const filteredTags = TagFilterService.filterTags(data.tags); - renderTagCloud(filteredTags); -} - -function renderTagCloud(tags) { - const cloud = document.getElementById("tag-cloud"); - cloud.innerHTML = ""; - - const counts = Object.values(tags); - if (counts.length === 0) return; - - const maxCount = Math.max(...counts); - const minSize = 0.7; - const maxSize = 1.25; - - Object.entries(tags).forEach(([tag, count]) => { - const ratio = maxCount > 1 ? (count - 1) / (maxCount - 1) : 0; - const size = minSize + ratio * (maxSize - minSize); - const tagEl = el("span", { class: "tag-item", style: `font-size:${size}rem` }, [document.createTextNode(`#${tag}`)]); - tagEl.addEventListener("click", () => searchByTag(tag)); - cloud.appendChild(tagEl); - }); -} - -function addTagFilter(tag) { - if (!selectedTags.includes(tag)) { - selectedTags.push(tag); - performTagSearch(); - } -} - -function removeTagFilter(tag) { - selectedTags = selectedTags.filter((t) => t !== tag); - if (selectedTags.length > 0) { - performTagSearch(); - } else { - const input = document.getElementById("search-input"); - if (input.value.trim()) { - performAdvancedSearch(input.value.trim(), document.getElementById("vault-filter").value, null); - } else { - showWelcome(); - } - } -} - -function performTagSearch() { - const input = document.getElementById("search-input"); - const query = input.value.trim(); - const vault = document.getElementById("vault-filter").value; - performAdvancedSearch(query, vault, selectedTags.length > 0 ? selectedTags.join(",") : null); -} - -function buildSearchResultsHeader(data, query, tagFilter) { - const header = el("div", { class: "search-results-header" }); - const summaryText = el("span", { class: "search-results-summary-text" }); - - if (query && tagFilter) { - summaryText.textContent = `${data.count} résultat(s) pour "${query}" avec les tags`; - } else if (query) { - summaryText.textContent = `${data.count} résultat(s) pour "${query}"`; - } else if (tagFilter) { - summaryText.textContent = `${data.count} fichier(s) avec les tags`; - } else { - summaryText.textContent = `${data.count} résultat(s)`; - } - - header.appendChild(summaryText); - - if (selectedTags.length > 0) { - const activeTags = el("div", { class: "search-results-active-tags" }); - selectedTags.forEach((tag) => { - const removeBtn = el( - "button", - { - class: "search-results-active-tag-remove", - title: `Retirer ${tag} du filtre`, - "aria-label": `Retirer ${tag} du filtre`, - }, - [document.createTextNode("×")], - ); - removeBtn.addEventListener("click", (e) => { - e.stopPropagation(); - removeTagFilter(tag); - }); - - const chip = el("span", { class: "search-results-active-tag" }, [document.createTextNode(`#${tag}`), removeBtn]); - activeTags.appendChild(chip); - }); - header.appendChild(activeTags); - } - - return header; -} - -function searchByTag(tag) { - addTagFilter(tag); -} - diff --git a/desktop/frontend-static/js/state.js b/desktop/frontend-static/js/state.js deleted file mode 100644 index e5d290c..0000000 --- a/desktop/frontend-static/js/state.js +++ /dev/null @@ -1,59 +0,0 @@ -/* ObsiGate — Shared mutable application state. - Use state.xxx to read/write any value. ES module imports are read-only, - so we export a single mutable object instead of individual let bindings. */ -export const state = { - APP_VERSION: "1.5.0", - - // Core navigation - currentVault: null, - currentPath: null, - allVaults: [], - selectedContextVault: "all", - - // Search - searchTimeout: null, - searchAbortController: null, - advancedSearchOffset: 0, - advancedSearchTotal: 0, - advancedSearchSort: "relevance", - advancedSearchLastQuery: "", - suggestAbortController: null, - dropdownActiveIndex: -1, - dropdownItems: [], - currentSearchId: 0, - selectedTags: [], - searchCaseSensitive: false, - searchWholeWord: false, - searchRegex: false, - searchFilterVisible: false, - - // Search constants - SEARCH_HISTORY_KEY: "obsigate_search_history", - MAX_HISTORY_ENTRIES: 50, - SUGGEST_DEBOUNCE_MS: 150, - ADVANCED_SEARCH_LIMIT: 50, - MIN_SEARCH_LENGTH: 2, - SEARCH_TIMEOUT_MS: 30000, - - // Viewer state - showingSource: false, - cachedRawSource: null, - editorView: null, - editorVault: null, - editorPath: null, - fallbackEditorEl: null, - _iconDebounceTimer: null, - - // Outline/TOC - outlineObserver: null, - activeHeadingId: null, - headingsCache: [], - rightSidebarVisible: true, - rightSidebarWidth: 280, - - // Sidebar - sidebarFilterCaseSensitive: false, - activeSidebarTab: "vaults", - filterDebounce: null, - vaultSettings: {}, -}; \ No newline at end of file diff --git a/desktop/frontend-static/js/sync.js b/desktop/frontend-static/js/sync.js deleted file mode 100644 index f0e6bc9..0000000 --- a/desktop/frontend-static/js/sync.js +++ /dev/null @@ -1,643 +0,0 @@ -/* ObsiGate — Sync: SSE client + PWA registration + Offline mode */ -import { state } from './state.js'; -import { t } from './i18n.js'; -import { showToast } from './ui.js'; -import { api, AuthManager } from './auth.js'; -import { loadVaults, loadTags, refreshTagsForContext, refreshSidebarTreePreservingState } from './sidebar.js'; -import { loadRecentFiles, initAboutModal } from './config.js'; -import { openFile } from './viewer.js'; -import { initOffline, syncFileIndexFromServer } from './offline.js'; -import { initThemes } from './themes.js'; - -// --------------------------------------------------------------------------- -// SSE Client — IndexUpdateManager -// --------------------------------------------------------------------------- -export const IndexUpdateManager = (() => { - let eventSource = null; - let reconnectTimer = null; - let reconnectDelay = 1000; - const MAX_RECONNECT_DELAY = 30000; - let recentEvents = []; - const MAX_RECENT_EVENTS = 20; - let connectionState = "disconnected"; // disconnected | connecting | connected - - function connect() { - if (eventSource) { - eventSource.close(); - } - connectionState = "connecting"; - _updateBadge(); - - eventSource = new EventSource("/api/events"); - - eventSource.addEventListener("connected", (e) => { - connectionState = "connected"; - reconnectDelay = 1000; - _updateBadge(); - }); - - eventSource.addEventListener("index_updated", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_updated", data); - _onIndexUpdated(data); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("index_reloaded", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_reloaded", data); - _onIndexReloaded(data); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("vault_added", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("vault_added", data); - showToast(t('sync.vault_added', { vault: data.vault, count: data.stats.file_count }), "info"); - loadVaults(); - loadTags(); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("vault_removed", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("vault_removed", data); - showToast(t('sync.vault_removed', { vault: data.vault }), "info"); - loadVaults(); - loadTags(); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("index_start", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_start", data); - connectionState = "syncing"; - _updateBadge(); - showToast(t('sync.index_started', { count: data.total_vaults }), "info"); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("index_progress", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_progress", data); - connectionState = "syncing"; - _updateBadge(); - loadVaults(); - loadTags(); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("index_complete", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_complete", data); - connectionState = "connected"; - _updateBadge(); - showToast(t('sync.index_complete', { count: data.total_files }), "success"); - loadVaults(); - loadTags(); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.onerror = () => { - connectionState = "disconnected"; - _updateBadge(); - eventSource.close(); - eventSource = null; - _scheduleReconnect(); - }; - } - - function _scheduleReconnect() { - if (reconnectTimer) clearTimeout(reconnectTimer); - reconnectTimer = setTimeout(() => { - reconnectDelay = Math.min(reconnectDelay * 2, MAX_RECONNECT_DELAY); - connect(); - }, reconnectDelay); - } - - function _addEvent(type, data) { - recentEvents.unshift({ - type, - data, - timestamp: new Date().toISOString(), - }); - if (recentEvents.length > MAX_RECENT_EVENTS) { - recentEvents = recentEvents.slice(0, MAX_RECENT_EVENTS); - } - } - - async function _onIndexUpdated(data) { - // Brief syncing state - connectionState = "syncing"; - _updateBadge(); - - const n = data.total_changes || 0; - const vaults = (data.vaults || []).join(", "); - // Toast removed: silent auto-indexing — no notification needed - - // Refresh sidebar and tags if affected vault matches current context - const affectsCurrentVault = state.selectedContextVault === "all" || (data.vaults || []).includes(state.selectedContextVault); - if (affectsCurrentVault) { - try { - await Promise.all([refreshSidebarTreePreservingState(), refreshTagsForContext()]); - // Refresh current file if it was updated - if (state.currentVault && state.currentPath) { - const changed = (data.changes || []).some((c) => c.vault === state.currentVault && c.path === state.currentPath); - if (changed) { - openFile(state.currentVault, state.currentPath); - } - } - } catch (err) { - console.error("Error refreshing after index update:", err); - } - } - - // Refresh recent tab if it is active - if (state.activeSidebarTab === "recent") { - const vaultFilter = document.getElementById("recent-vault-filter"); - loadRecentFiles(vaultFilter ? vaultFilter.value || null : null); - } - - setTimeout(() => { - connectionState = "connected"; - _updateBadge(); - }, 1500); - } - - async function _onIndexReloaded(data) { - connectionState = "syncing"; - _updateBadge(); - showToast(t("sync.index_reloaded"), "info"); - try { - await Promise.all([loadVaults(), loadTags()]); - } catch (err) { - console.error("Error refreshing after full reload:", err); - } - setTimeout(() => { - connectionState = "connected"; - _updateBadge(); - }, 1500); - } - - function _updateBadge() { - const badge = document.getElementById("sync-badge"); - if (!badge) return; - badge.className = "sync-badge sync-badge--" + connectionState; - const labels = { - disconnected: t('sync.disconnected'), - connecting: "Connexion...", - connected: t('sync.connected'), - syncing: t('sync.updating'), - }; - badge.title = labels[connectionState] || connectionState; - } - - function disconnect() { - if (eventSource) { - eventSource.close(); - eventSource = null; - } - if (reconnectTimer) { - clearTimeout(reconnectTimer); - reconnectTimer = null; - } - connectionState = "disconnected"; - _updateBadge(); - } - - function getState() { - return connectionState; - } - - function getRecentEvents() { - return recentEvents; - } - - return { connect, disconnect, getState, getRecentEvents }; -})(); - -// --------------------------------------------------------------------------- -// Sync status badge and panel -// --------------------------------------------------------------------------- - -function initSyncStatus() { - const badge = document.getElementById("sync-badge"); - if (!badge) return; - - badge.addEventListener("click", (e) => { - e.stopPropagation(); - toggleSyncPanel(); - }); - - IndexUpdateManager.connect(); - - // Initialize AI status tracking - _initAIStatus(); -} - -function toggleSyncPanel() { - let panel = document.getElementById("sync-panel"); - if (panel) { - panel.remove(); - return; - } - // Auto reconnect if disconnected when user opens the panel - if (IndexUpdateManager.getState() === "disconnected") { - IndexUpdateManager.connect(); - } - panel = document.createElement("div"); - panel.id = "sync-panel"; - panel.className = "sync-panel"; - _renderSyncPanel(panel); - document.body.appendChild(panel); - - // Close on outside click - setTimeout(() => { - document.addEventListener("click", _closeSyncPanelOutside, { once: true }); - }, 0); -} - -function _closeSyncPanelOutside(e) { - const panel = document.getElementById("sync-panel"); - if (panel && !panel.contains(e.target) && e.target.id !== "sync-badge") { - panel.remove(); - } -} - -function _renderSyncPanel(panel) { - const state = IndexUpdateManager.getState(); - const events = IndexUpdateManager.getRecentEvents(); - - const stateLabels = { - disconnected: t('sync.disconnected'), - connecting: "Connexion...", - connected: t('sync.connected_short'), - syncing: "Synchronisation...", - }; - - let html = `
    - Synchronisation - ${stateLabels[state] || state} -
    `; - - if (events.length === 0) { - html += `
    ${t('sync.no_recent_events')}
    `; - } else { - html += `
    `; - events.slice(0, 10).forEach((ev) => { - const time = new Date(ev.timestamp).toLocaleTimeString(); - const typeLabels = { - index_updated: t('sync.event_index_updated'), - index_reloaded: "Rechargement", - vault_added: t('sync.event_vault_added'), - vault_removed: t('sync.event_vault_removed'), - index_start: t('sync.event_index_start'), - index_progress: t('sync.event_index_progress'), - index_complete: "Indexation tech.", - }; - const label = typeLabels[ev.type] || ev.type; - let detail = ev.data.vaults ? ev.data.vaults.join(", ") : ev.data.vault || ""; - if (ev.type === "index_start") detail = `${ev.data.total_vaults} vaults à traiter`; - if (ev.type === "index_progress") detail = t("sync.vault_files", {vault: ev.data.vault, files: ev.data.files}); - if (ev.type === "index_complete" && ev.data.total_files !== undefined) detail = `${ev.data.total_files} fichiers total`; - html += `
    - ${label} - ${detail} - ${time} -
    `; - }); - html += `
    `; - } - - panel.innerHTML = html; - - // ── AI Status section ── - _renderAIStatusSection(panel); -} - -// --------------------------------------------------------------------------- -// AI Status Indicator (inside sync panel + header badge animation) -// --------------------------------------------------------------------------- - -let _aiProcessing = false; -let _aiConfigured = null; // null = unknown, true/false -let _aiAutocomplete = null; // null = unknown, {available, server_ok, model_loaded, model, error} - -/** Check if AI is configured by calling the /api/ai/status endpoint. - * Updates _aiConfigured, _aiAutocomplete and refreshes the panel if open. */ -async function _checkAIStatus() { - try { - const status = await api('/api/ai/status'); - _aiConfigured = status.configured === true; - _aiAutocomplete = status.autocomplete || null; - } catch { - _aiConfigured = false; - _aiAutocomplete = null; - } - _updateAIStatusInPanel(); -} - -function _renderAIStatusSection(panel) { - const section = document.createElement('div'); - section.className = 'sync-panel__ai-section'; - section.id = 'sync-panel-ai'; - - // ---- External provider status ---- - let extIcon, extText, extClass; - if (_aiProcessing) { - extIcon = 'loader'; - extText = t('sync.processing'); - extClass = 'sync-panel__ai--processing'; - } else if (_aiConfigured === true) { - extIcon = 'check-circle'; - extText = 'Fournisseur externe actif'; - extClass = 'sync-panel__ai--active'; - } else if (_aiConfigured === false) { - extIcon = 'x-circle'; - extText = t('sync.no_provider'); - extClass = 'sync-panel__ai--inactive'; - } else { - extIcon = 'help-circle'; - extText = t('sync.verifying'); - extClass = 'sync-panel__ai--unknown'; - } - - // ---- Autocomplete (Ollama) status ---- - let acIcon, acText, acClass; - if (_aiAutocomplete && _aiAutocomplete.available) { - acIcon = 'check-circle'; - acText = t('sync.autocomplete_active'); - acClass = 'sync-panel__ai--active'; - } else if (_aiAutocomplete && _aiAutocomplete.server_ok && !_aiAutocomplete.model_loaded) { - acIcon = 'alert-triangle'; - acText = t('sync.model_not_loaded'); - acClass = 'sync-panel__ai--inactive'; - } else if (_aiAutocomplete && _aiAutocomplete.error) { - acIcon = 'x-circle'; - acText = 'Serveur Ollama injoignable'; - acClass = 'sync-panel__ai--inactive'; - } else if (_aiAutocomplete === null) { - acIcon = 'help-circle'; - acText = t('sync.verifying'); - acClass = 'sync-panel__ai--unknown'; - } else { - acIcon = 'x-circle'; - acText = t('sync.not_configured'); - acClass = 'sync-panel__ai--inactive'; - } - - section.innerHTML = '' + - '
    Intelligence Artificielle
    ' + - '
    ' + - 'Fournisseur' + - '' + - '' + - extText + - '' + - '
    ' + - '
    ' + - '' + t('sync.autocomplete') + '' + - '' + - '' + - acText + - '' + - '
    '; - - panel.appendChild(section); - // Trigger icon refresh via global - if (window._obsigateRefreshIcons) window._obsigateRefreshIcons(); -} - -/** Update the AI section in the open sync panel. */ -function _updateAIStatusInPanel() { - const section = document.getElementById('sync-panel-ai'); - if (!section) return; - section.innerHTML = ''; - const panel = document.getElementById('sync-panel'); - if (panel) { - // Re-render just the AI section - const oldSection = panel.querySelector('.sync-panel__ai-section'); - if (oldSection) oldSection.remove(); - _renderAIStatusSection(panel); - } -} - -/** Flash the sync badge white during AI processing. - * NOTE: now handled via CSS class on #sync-badge. - * The visual flash in the editor itself is handled by ai.js - * which adds a processing indicator inline. */ -function _setBadgeAIProcessing(active) { - const badge = document.getElementById('sync-badge'); - if (!badge) return; - if (active) { - badge.classList.add('sync-badge--ai-processing'); - } else { - badge.classList.remove('sync-badge--ai-processing'); - } -} - -/** Initialize AI status tracking. */ -function _initAIStatus() { - // Check AI status immediately at startup - _checkAIStatus(); - - // Listen for AI processing events from ai.js - document.addEventListener('ai-processing-start', () => { - _aiProcessing = true; - _setBadgeAIProcessing(true); - _updateAIStatusInPanel(); - }); - - document.addEventListener('ai-processing-end', () => { - _aiProcessing = false; - _setBadgeAIProcessing(false); - _updateAIStatusInPanel(); - }); - - // Re-check AI status when sync panel opens (in case config changed) - const badge = document.getElementById('sync-badge'); - if (badge) { - badge.addEventListener('click', () => { - _checkAIStatus(); - }, { once: false }); - } -} - -// --------------------------------------------------------------------------- -// PWA Service Worker Registration -// --------------------------------------------------------------------------- -function registerServiceWorker() { - if ("serviceWorker" in navigator) { - window.addEventListener("load", () => { - navigator.serviceWorker - .register("/sw.js") - .then((registration) => { - console.log("[PWA] Service Worker registered successfully:", registration.scope); - - // Check for updates periodically - setInterval(() => { - registration.update(); - }, 60000); // Check every minute - - // Handle service worker updates - registration.addEventListener("updatefound", () => { - const newWorker = registration.installing; - newWorker.addEventListener("statechange", () => { - if (newWorker.state === "installed" && navigator.serviceWorker.controller) { - // New service worker available - showUpdateNotification(); - } - }); - }); - }) - .catch((error) => { - console.log("[PWA] Service Worker registration failed:", error); - }); - }); - } -} - -function showUpdateNotification() { - const message = document.createElement("div"); - message.className = "pwa-update-notification"; - message.innerHTML = ` -
    - Une nouvelle version d'ObsiGate est disponible ! - - -
    - `; - document.body.appendChild(message); - - // Auto-dismiss after 30 seconds - setTimeout(() => { - if (message.parentElement) { - message.remove(); - } - }, 30000); -} - -// Handle install prompt -let deferredPrompt; -window.addEventListener("beforeinstallprompt", (e) => { - e.preventDefault(); - deferredPrompt = e; - - // Show install button if desired - const installBtn = document.getElementById("pwa-install-btn"); - if (installBtn) { - installBtn.style.display = "block"; - installBtn.addEventListener("click", async () => { - if (deferredPrompt) { - deferredPrompt.prompt(); - const { outcome } = await deferredPrompt.userChoice; - console.log(`[PWA] User response to install prompt: ${outcome}`); - deferredPrompt = null; - installBtn.style.display = "none"; - } - }); - } -}); - -// Log when app is installed -window.addEventListener("appinstalled", () => { - console.log("[PWA] ObsiGate has been installed"); - showToast(t("sync.install_success"), "success"); -}); - -// ── Dashboard tab switching (runs on page load and after rebuild) ── -function initDashboardTabs() { - document.querySelectorAll(".dashboard-tab").forEach(tab => { - // Remove existing listeners by cloning - const newTab = tab.cloneNode(true); - tab.parentNode.replaceChild(newTab, tab); - newTab.addEventListener("click", function() { - document.querySelectorAll(".dashboard-tab").forEach(t => t.classList.remove("active")); - document.querySelectorAll(".dashboard-panel").forEach(p => p.classList.remove("active")); - this.classList.add("active"); - const panel = document.getElementById("dashboard-panel-" + this.dataset.tab); - if (panel) panel.classList.add("active"); - }); - }); -} - -// --------------------------------------------------------------------------- -// Init — called by app.js orchestrator -// --------------------------------------------------------------------------- -export { initSyncStatus, initDashboardTabs }; -export function init() { - registerServiceWorker(); - initOffline(); - initThemes(); - initAboutModal(); - // Sync file index after a short delay (let vaults load first). - // Gate on auth at execution time (not scheduling time) so that - // initAuth() has a chance to complete and set _authEnabled / token. - // The login handler triggers syncFileIndexFromServer explicitly on - // fresh login, so we only do it here for already-authenticated or - // auth-disabled sessions. - setTimeout(() => { - if (!AuthManager._authEnabled || AuthManager.getToken()) { - syncFileIndexFromServer(); - } - }, 3000); - initDashboardTabs(); - - // Listen for Forge editor rename events - window.addEventListener('message', function(e) { - if (!e.data || !e.data.type) return; - if (e.data.type === 'forge-renamed') { - var vault = e.data.vault; - var oldPath = e.data.oldPath; - var newPath = e.data.newPath; - console.log('[Forge] File renamed:', vault, oldPath, '->', newPath); - var titleEl = document.getElementById('editor-title'); - if (titleEl && titleEl.textContent.indexOf('Forge:') === 0) { - titleEl.textContent = 'Forge: ' + newPath.split('/').pop(); - } - refreshSidebarTreePreservingState(vault); - if (state.currentVault === vault && state.currentPath === oldPath) { - import('./viewer.js').then(function(m) { m.openFile(vault, newPath); }); - } - } - if (e.data.type === 'forge-close') { - var modal = document.getElementById('editor-modal'); - var forgeFrame = document.getElementById('forge-iframe'); - if (forgeFrame) forgeFrame.remove(); - if (modal) modal.classList.remove('active'); - // Restore brand text - var brand = modal.querySelector('.editor-brand'); - if (brand) brand.textContent = 'ObsiGate'; - // Restore header/footer - var headerEl = modal.querySelector('.editor-header'); - var footerEl = modal.querySelector('.editor-footer'); - if (headerEl) headerEl.style.display = ''; - if (footerEl) footerEl.style.display = ''; - // Refresh current file content - if (state.currentVault && state.currentPath) { - import('./viewer.js').then(function(m) { m.openFile(state.currentVault, state.currentPath); }); - } - } - }); -} diff --git a/desktop/frontend-static/js/themes.js b/desktop/frontend-static/js/themes.js deleted file mode 100644 index 42ea30b..0000000 --- a/desktop/frontend-static/js/themes.js +++ /dev/null @@ -1,566 +0,0 @@ -/* ObsiGate — Theme System - * 15 themes x 2 modes (dark/light) - * Persisted in localStorage as 'obsigate-theme' - * Usage: import { initThemes, applyTheme, getCurrentTheme, THEMES } from './themes.js' - */ - -// ── Theme definitions ──────────────────────────────────────────────── -// Each theme has 'dark' and 'light' variants. -// CSS variables are applied to :root via setProperty. - -var THEMES = { - - 'defaut-obsigate': { - name: 'Defaut ObsiGate', - desc: 'Theme original', - modes: { - dark: { - '--bg-primary': '#0f1117', '--bg-secondary': '#161b22', '--bg-sidebar': '#13161d', - '--bg-hover': '#1f2430', '--border': '#21262d', '--text-primary': '#e6edf3', - '--text-secondary': '#8b949e', '--text-muted': '#484f58', '--accent': '#58a6ff', - '--accent-green': '#3fb950', '--tag-bg': '#1f2a3a', '--tag-text': '#79c0ff', - '--code-bg': '#161b22', '--search-bg': '#21262d', '--scrollbar': '#30363d', - '--resize-handle': '#30363d', '--overlay-bg': 'rgba(0,0,0,0.5)', - '--danger': '#ff7b72', '--danger-bg': '#3d1a18', '--success': '#3fb950', '--success-bg': '#1a3d1f', - '--accent-card': '#58a6ff', '--accent-bg': '#1f2a3a', '--accent-text': '#79c0ff', - '--green': '#3fb950', '--green-bg': '#1a3d1f', '--purple': '#a371f7', '--purple-bg': '#2d1b4e', - '--surface': '#161b22', '--surface2': '#0f1117', '--surface3': '#0d0f14', - '--border-md': '#30363d', '--text': '#e6edf3', '--text-2': '#8b949e', '--text-3': '#484f58', - '--ok': '#34d399', '--warn': '#fbbf24', '--ai': '#8b5cf6', '--err': '#f87171' - }, - light: { - '--bg-primary': '#ffffff', '--bg-secondary': '#f6f8fa', '--bg-sidebar': '#f0f2f5', - '--bg-hover': '#e8ecf0', '--border': '#d0d7de', '--text-primary': '#1f2328', - '--text-secondary': '#57606a', '--text-muted': '#9198a1', '--accent': '#0969da', - '--accent-green': '#1a7f37', '--tag-bg': '#ddf4ff', '--tag-text': '#0969da', - '--code-bg': '#f6f8fa', '--search-bg': '#ffffff', '--scrollbar': '#d0d7de', - '--resize-handle': '#d0d7de', '--overlay-bg': 'rgba(0,0,0,0.3)', - '--danger': '#cf222e', '--danger-bg': '#ffebe9', '--success': '#1a7f37', '--success-bg': '#dafbe1', - '--accent-card': '#0969da', '--accent-bg': '#ddf4ff', '--accent-text': '#0969da', - '--green': '#1a7f37', '--green-bg': '#dafbe1', '--purple': '#8250df', '--purple-bg': '#fbefff', - '--surface': '#f6f8fa', '--surface2': '#ffffff', '--surface3': '#f0f2f5', - '--border-md': '#d0d7de', '--text': '#1f2328', '--text-2': '#57606a', '--text-3': '#9198a1', - '--ok': '#1a7f37', '--warn': '#9a6700', '--ai': '#8250df', '--err': '#cf222e' - } - } - }, - - 'github': { - name: 'GitHub', desc: 'Contraste doux', - modes: { - dark: { - '--bg-primary': '#0d1117', '--bg-secondary': '#161b22', '--bg-sidebar': '#0d1117', - '--bg-hover': '#1c2128', '--border': '#30363d', '--text-primary': '#f0f6fc', - '--text-secondary': '#8b949e', '--text-muted': '#6e7681', '--accent': '#58a6ff', - '--accent-green': '#3fb950', '--tag-bg': '#13233a', '--tag-text': '#58a6ff', - '--code-bg': '#161b22', '--search-bg': '#0d1117', '--scrollbar': '#30363d', - '--resize-handle': '#30363d', '--overlay-bg': 'rgba(0,0,0,0.6)', - '--danger': '#f85149', '--danger-bg': '#490202', '--success': '#3fb950', '--success-bg': '#04260f', - '--accent-card': '#58a6ff', '--accent-bg': '#13233a', '--accent-text': '#58a6ff', - '--green': '#3fb950', '--green-bg': '#04260f', '--purple': '#a371f7', '--purple-bg': '#1c1130', - '--surface': '#161b22', '--surface2': '#0d1117', '--surface3': '#010409', - '--border-md': '#30363d', '--text': '#f0f6fc', '--text-2': '#8b949e', '--text-3': '#6e7681', - '--ok': '#3fb950', '--warn': '#d29922', '--ai': '#a371f7', '--err': '#f85149' - }, - light: { - '--bg-primary': '#ffffff', '--bg-secondary': '#f6f8fa', '--bg-sidebar': '#f6f8fa', - '--bg-hover': '#eaeef2', '--border': '#d0d7de', '--text-primary': '#1f2328', - '--text-secondary': '#656d76', '--text-muted': '#8c959f', '--accent': '#0969da', - '--accent-green': '#1a7f37', '--tag-bg': '#ddf4ff', '--tag-text': '#0969da', - '--code-bg': '#f6f8fa', '--search-bg': '#ffffff', '--scrollbar': '#d0d7de', - '--resize-handle': '#d0d7de', '--overlay-bg': 'rgba(0,0,0,0.25)', - '--danger': '#cf222e', '--danger-bg': '#ffebe9', '--success': '#1a7f37', '--success-bg': '#dafbe1', - '--accent-card': '#0969da', '--accent-bg': '#ddf4ff', '--accent-text': '#0969da', - '--green': '#1a7f37', '--green-bg': '#dafbe1', '--purple': '#8250df', '--purple-bg': '#fbefff', - '--surface': '#f6f8fa', '--surface2': '#ffffff', '--surface3': '#ebedf0', - '--border-md': '#d0d7de', '--text': '#1f2328', '--text-2': '#656d76', '--text-3': '#8c959f', - '--ok': '#1a7f37', '--warn': '#9a6700', '--ai': '#8250df', '--err': '#cf222e' - } - } - }, - - 'linear': { - name: 'Linear', desc: 'Dégradés subtils', - modes: { - dark: { - '--bg-primary': '#1a1a2e', '--bg-secondary': '#16162a', '--bg-sidebar': '#12121f', - '--bg-hover': '#222240', '--border': '#2a2a45', '--text-primary': '#e1e1f5', - '--text-secondary': '#8888aa', '--text-muted': '#555577', '--accent': '#5e6ad2', - '--accent-green': '#2ecc71', '--tag-bg': '#222050', '--tag-text': '#8b95e0', - '--code-bg': '#16162a', '--search-bg': '#1e1e38', '--scrollbar': '#2a2a45', - '--resize-handle': '#2a2a45', '--overlay-bg': 'rgba(0,0,0,0.6)', - '--danger': '#e0556a', '--danger-bg': '#361520', '--success': '#2ecc71', '--success-bg': '#0d2818', - '--accent-card': '#5e6ad2', '--accent-bg': '#222050', '--accent-text': '#8b95e0', - '--green': '#2ecc71', '--green-bg': '#0d2818', '--purple': '#9b6bff', '--purple-bg': '#25183d', - '--surface': '#16162a', '--surface2': '#1a1a2e', '--surface3': '#12121f', - '--border-md': '#2a2a45', '--text': '#e1e1f5', '--text-2': '#8888aa', '--text-3': '#555577', - '--ok': '#2ecc71', '--warn': '#f0b429', '--ai': '#9b6bff', '--err': '#e0556a' - }, - light: { - '--bg-primary': '#fafafa', '--bg-secondary': '#f0f0f5', '--bg-sidebar': '#e8e8f0', - '--bg-hover': '#e0e0ea', '--border': '#d5d5e0', '--text-primary': '#1a1a2e', - '--text-secondary': '#5c5c7a', '--text-muted': '#9090a8', '--accent': '#5e6ad2', - '--accent-green': '#1a8b4a', '--tag-bg': '#e8e8ff', '--tag-text': '#5e6ad2', - '--code-bg': '#f0f0f5', '--search-bg': '#fafafa', '--scrollbar': '#d5d5e0', - '--resize-handle': '#d5d5e0', '--overlay-bg': 'rgba(0,0,0,0.2)', - '--danger': '#c92a3e', '--danger-bg': '#ffeaea', '--success': '#1a8b4a', '--success-bg': '#e0ffe0', - '--accent-card': '#5e6ad2', '--accent-bg': '#e8e8ff', '--accent-text': '#5e6ad2', - '--green': '#1a8b4a', '--green-bg': '#e0ffe0', '--purple': '#7c5ce0', '--purple-bg': '#efe8ff', - '--surface': '#f0f0f5', '--surface2': '#fafafa', '--surface3': '#e8e8f0', - '--border-md': '#d5d5e0', '--text': '#1a1a2e', '--text-2': '#5c5c7a', '--text-3': '#9090a8', - '--ok': '#1a8b4a', '--warn': '#9a6700', '--ai': '#7c5ce0', '--err': '#c92a3e' - } - } - }, - - 'spotify': { - name: 'Spotify', desc: 'Noir pur & vert', - modes: { - dark: { - '--bg-primary': '#000000', '--bg-secondary': '#121212', '--bg-sidebar': '#000000', - '--bg-hover': '#1a1a1a', '--border': '#282828', '--text-primary': '#ffffff', - '--text-secondary': '#b3b3b3', '--text-muted': '#727272', '--accent': '#1db954', - '--accent-green': '#1db954', '--tag-bg': '#0d3317', '--tag-text': '#1db954', - '--code-bg': '#121212', '--search-bg': '#242424', '--scrollbar': '#333333', - '--resize-handle': '#282828', '--overlay-bg': 'rgba(0,0,0,0.7)', - '--danger': '#e22134', '--danger-bg': '#2a0a0e', '--success': '#1db954', '--success-bg': '#0d3317', - '--accent-card': '#1db954', '--accent-bg': '#0d3317', '--accent-text': '#1db954', - '--green': '#1db954', '--green-bg': '#0d3317', '--purple': '#af2896', '--purple-bg': '#2a0d33', - '--surface': '#121212', '--surface2': '#000000', '--surface3': '#000000', - '--border-md': '#282828', '--text': '#ffffff', '--text-2': '#b3b3b3', '--text-3': '#727272', - '--ok': '#1db954', '--warn': '#f59b23', '--ai': '#af2896', '--err': '#e22134' - }, - light: { - '--bg-primary': '#ffffff', '--bg-secondary': '#f5f5f5', '--bg-sidebar': '#f0f0f0', - '--bg-hover': '#e5e5e5', '--border': '#d5d5d5', '--text-primary': '#121212', - '--text-secondary': '#575757', '--text-muted': '#8c8c8c', '--accent': '#1db954', - '--accent-green': '#1db954', '--tag-bg': '#e0ffe0', '--tag-text': '#128a3c', - '--code-bg': '#f5f5f5', '--search-bg': '#ffffff', '--scrollbar': '#d5d5d5', - '--resize-handle': '#d5d5d5', '--overlay-bg': 'rgba(0,0,0,0.2)', - '--danger': '#c92a2a', '--danger-bg': '#ffe3e3', '--success': '#1db954', '--success-bg': '#e0ffe0', - '--accent-card': '#1db954', '--accent-bg': '#e0ffe0', '--accent-text': '#128a3c', - '--green': '#1db954', '--green-bg': '#e0ffe0', '--purple': '#8a2be2', '--purple-bg': '#f3e0ff', - '--surface': '#f5f5f5', '--surface2': '#ffffff', '--surface3': '#f0f0f0', - '--border-md': '#d5d5d5', '--text': '#121212', '--text-2': '#575757', '--text-3': '#8c8c8c', - '--ok': '#1db954', '--warn': '#9a6700', '--ai': '#8a2be2', '--err': '#c92a2a' - } - } - }, - - 'notion': { - name: 'Notion', desc: 'Lecture propre', - modes: { - dark: { - '--bg-primary': '#191919', '--bg-secondary': '#202020', '--bg-sidebar': '#191919', - '--bg-hover': '#262626', '--border': '#333333', '--text-primary': '#e6e6e6', - '--text-secondary': '#999999', '--text-muted': '#666666', '--accent': '#4b85e8', - '--accent-green': '#0ca16a', '--tag-bg': '#1c2744', '--tag-text': '#6ba1f0', - '--code-bg': '#202020', '--search-bg': '#262626', '--scrollbar': '#333333', - '--resize-handle': '#333333', '--overlay-bg': 'rgba(0,0,0,0.6)', - '--danger': '#e03e3e', '--danger-bg': '#2a1010', '--success': '#0ca16a', '--success-bg': '#0d2818', - '--accent-card': '#4b85e8', '--accent-bg': '#1c2744', '--accent-text': '#6ba1f0', - '--green': '#0ca16a', '--green-bg': '#0d2818', '--purple': '#9065e0', '--purple-bg': '#24183d', - '--surface': '#202020', '--surface2': '#191919', '--surface3': '#141414', - '--border-md': '#333333', '--text': '#e6e6e6', '--text-2': '#999999', '--text-3': '#666666', - '--ok': '#0ca16a', '--warn': '#dfab3e', '--ai': '#9065e0', '--err': '#e03e3e' - }, - light: { - '--bg-primary': '#ffffff', '--bg-secondary': '#f7f6f3', '--bg-sidebar': '#f7f6f3', - '--bg-hover': '#edece9', '--border': '#e3e2e0', '--text-primary': '#37352f', - '--text-secondary': '#787774', '--text-muted': '#abaaa7', '--accent': '#4b85e8', - '--accent-green': '#0ca16a', '--tag-bg': '#e8f0fe', '--tag-text': '#4b85e8', - '--code-bg': '#f7f6f3', '--search-bg': '#ffffff', '--scrollbar': '#e3e2e0', - '--resize-handle': '#e3e2e0', '--overlay-bg': 'rgba(0,0,0,0.15)', - '--danger': '#e03e3e', '--danger-bg': '#fdebec', '--success': '#0ca16a', '--success-bg': '#e6f7ec', - '--accent-card': '#4b85e8', '--accent-bg': '#e8f0fe', '--accent-text': '#4b85e8', - '--green': '#0ca16a', '--green-bg': '#e6f7ec', '--purple': '#9065e0', '--purple-bg': '#f3effc', - '--surface': '#f7f6f3', '--surface2': '#ffffff', '--surface3': '#edece9', - '--border-md': '#e3e2e0', '--text': '#37352f', '--text-2': '#787774', '--text-3': '#abaaa7', - '--ok': '#0ca16a', '--warn': '#dfab3e', '--ai': '#9065e0', '--err': '#e03e3e' - } - } - }, - - 'discord': { - name: 'Discord', desc: 'Standard communautaire', - modes: { - dark: { - '--bg-primary': '#313338', '--bg-secondary': '#2b2d31', '--bg-sidebar': '#1e1f22', - '--bg-hover': '#3c3e45', '--border': '#3f4147', '--text-primary': '#f2f3f5', - '--text-secondary': '#b5bac1', '--text-muted': '#80848e', '--accent': '#5865f2', - '--accent-green': '#23a559', '--tag-bg': '#28315c', '--tag-text': '#8891f2', - '--code-bg': '#2b2d31', '--search-bg': '#383a40', '--scrollbar': '#1a1b1e', - '--resize-handle': '#3f4147', '--overlay-bg': 'rgba(0,0,0,0.7)', - '--danger': '#da373c', '--danger-bg': '#3a1518', '--success': '#23a559', '--success-bg': '#122b1a', - '--accent-card': '#5865f2', '--accent-bg': '#28315c', '--accent-text': '#8891f2', - '--green': '#23a559', '--green-bg': '#122b1a', '--purple': '#9c5bf0', '--purple-bg': '#2c1a46', - '--surface': '#2b2d31', '--surface2': '#313338', '--surface3': '#1e1f22', - '--border-md': '#3f4147', '--text': '#f2f3f5', '--text-2': '#b5bac1', '--text-3': '#80848e', - '--ok': '#23a559', '--warn': '#f0b232', '--ai': '#9c5bf0', '--err': '#da373c' - }, - light: { - '--bg-primary': '#ffffff', '--bg-secondary': '#f2f3f5', '--bg-sidebar': '#e3e5e8', - '--bg-hover': '#e3e5e8', '--border': '#d4d7dc', '--text-primary': '#313338', - '--text-secondary': '#5c5e66', '--text-muted': '#91949e', '--accent': '#5865f2', - '--accent-green': '#248046', '--tag-bg': '#e8eafe', '--tag-text': '#4752c4', - '--code-bg': '#f2f3f5', '--search-bg': '#ffffff', '--scrollbar': '#d4d7dc', - '--resize-handle': '#d4d7dc', '--overlay-bg': 'rgba(0,0,0,0.2)', - '--danger': '#d92028', '--danger-bg': '#fde8e8', '--success': '#248046', '--success-bg': '#e6f7e8', - '--accent-card': '#5865f2', '--accent-bg': '#e8eafe', '--accent-text': '#4752c4', - '--green': '#248046', '--green-bg': '#e6f7e8', '--purple': '#8b5cf6', '--purple-bg': '#f0ebff', - '--surface': '#f2f3f5', '--surface2': '#ffffff', '--surface3': '#e3e5e8', - '--border-md': '#d4d7dc', '--text': '#313338', '--text-2': '#5c5e66', '--text-3': '#91949e', - '--ok': '#248046', '--warn': '#9a6700', '--ai': '#8b5cf6', '--err': '#d92028' - } - } - }, - - 'dracula': { - name: 'Dracula', desc: 'Accents rose & violet', - modes: { - dark: { - '--bg-primary': '#282a36', '--bg-secondary': '#21222c', '--bg-sidebar': '#1d1e26', - '--bg-hover': '#343746', '--border': '#3b3d54', '--text-primary': '#f8f8f2', - '--text-secondary': '#b2b2b2', '--text-muted': '#6272a4', '--accent': '#bd93f9', - '--accent-green': '#50fa7b', '--tag-bg': '#2a2240', '--tag-text': '#bd93f9', - '--code-bg': '#21222c', '--search-bg': '#343746', '--scrollbar': '#44475a', - '--resize-handle': '#3b3d54', '--overlay-bg': 'rgba(0,0,0,0.6)', - '--danger': '#ff5555', '--danger-bg': '#3a1a1a', '--success': '#50fa7b', '--success-bg': '#0d2818', - '--accent-card': '#bd93f9', '--accent-bg': '#2a2240', '--accent-text': '#bd93f9', - '--green': '#50fa7b', '--green-bg': '#0d2818', '--purple': '#bd93f9', '--purple-bg': '#2a2240', - '--surface': '#21222c', '--surface2': '#282a36', '--surface3': '#1d1e26', - '--border-md': '#3b3d54', '--text': '#f8f8f2', '--text-2': '#b2b2b2', '--text-3': '#6272a4', - '--ok': '#50fa7b', '--warn': '#f1fa8c', '--ai': '#bd93f9', '--err': '#ff5555' - }, - light: { - '--bg-primary': '#f8f8f2', '--bg-secondary': '#f0f0ea', '--bg-sidebar': '#e8e8e0', - '--bg-hover': '#e0e0d8', '--border': '#d5d5cc', '--text-primary': '#282a36', - '--text-secondary': '#4d5066', '--text-muted': '#8b8fa8', '--accent': '#8a5cf6', - '--accent-green': '#3d8f54', '--tag-bg': '#ede0ff', '--tag-text': '#8a5cf6', - '--code-bg': '#f0f0ea', '--search-bg': '#f8f8f2', '--scrollbar': '#d5d5cc', - '--resize-handle': '#d5d5cc', '--overlay-bg': 'rgba(0,0,0,0.15)', - '--danger': '#d7373f', '--danger-bg': '#fde8e8', '--success': '#3d8f54', '--success-bg': '#e6f7e8', - '--accent-card': '#8a5cf6', '--accent-bg': '#ede0ff', '--accent-text': '#8a5cf6', - '--green': '#3d8f54', '--green-bg': '#e6f7e8', '--purple': '#8a5cf6', '--purple-bg': '#ede0ff', - '--surface': '#f0f0ea', '--surface2': '#f8f8f2', '--surface3': '#e8e8e0', - '--border-md': '#d5d5cc', '--text': '#282a36', '--text-2': '#4d5066', '--text-3': '#8b8fa8', - '--ok': '#3d8f54', '--warn': '#8b7500', '--ai': '#8a5cf6', '--err': '#d7373f' - } - } - }, - - 'one-dark': { - name: 'One Dark', desc: 'Inspire d\'Atom', - modes: { - dark: { - '--bg-primary': '#282c34', '--bg-secondary': '#21252b', '--bg-sidebar': '#1c1f26', - '--bg-hover': '#333842', '--border': '#3e4452', '--text-primary': '#abb2bf', - '--text-secondary': '#828997', '--text-muted': '#5c6370', '--accent': '#61afef', - '--accent-green': '#98c379', '--tag-bg': '#1e3350', '--tag-text': '#61afef', - '--code-bg': '#21252b', '--search-bg': '#333842', '--scrollbar': '#3e4452', - '--resize-handle': '#3e4452', '--overlay-bg': 'rgba(0,0,0,0.6)', - '--danger': '#e06c75', '--danger-bg': '#351b1e', '--success': '#98c379', '--success-bg': '#1a2e1a', - '--accent-card': '#61afef', '--accent-bg': '#1e3350', '--accent-text': '#61afef', - '--green': '#98c379', '--green-bg': '#1a2e1a', '--purple': '#c678dd', '--purple-bg': '#2c1a3a', - '--surface': '#21252b', '--surface2': '#282c34', '--surface3': '#1c1f26', - '--border-md': '#3e4452', '--text': '#abb2bf', '--text-2': '#828997', '--text-3': '#5c6370', - '--ok': '#98c379', '--warn': '#e5c07b', '--ai': '#c678dd', '--err': '#e06c75' - }, - light: { - '--bg-primary': '#fafafa', '--bg-secondary': '#f0f0f0', '--bg-sidebar': '#e8e8e8', - '--bg-hover': '#e0e0e0', '--border': '#d4d4d4', '--text-primary': '#383a42', - '--text-secondary': '#696c77', '--text-muted': '#9ca0a4', '--accent': '#4078f2', - '--accent-green': '#50a14f', '--tag-bg': '#e0e8ff', '--tag-text': '#4078f2', - '--code-bg': '#f0f0f0', '--search-bg': '#fafafa', '--scrollbar': '#d4d4d4', - '--resize-handle': '#d4d4d4', '--overlay-bg': 'rgba(0,0,0,0.15)', - '--danger': '#e45649', '--danger-bg': '#fde8e8', '--success': '#50a14f', '--success-bg': '#e6f7e6', - '--accent-card': '#4078f2', '--accent-bg': '#e0e8ff', '--accent-text': '#4078f2', - '--green': '#50a14f', '--green-bg': '#e6f7e6', '--purple': '#a626a4', '--purple-bg': '#f8e0f8', - '--surface': '#f0f0f0', '--surface2': '#fafafa', '--surface3': '#e8e8e8', - '--border-md': '#d4d4d4', '--text': '#383a42', '--text-2': '#696c77', '--text-3': '#9ca0a4', - '--ok': '#50a14f', '--warn': '#986801', '--ai': '#a626a4', '--err': '#e45649' - } - } - }, - - 'tokyo-night': { - name: 'Tokyo Night', desc: 'Bleu neon', - modes: { - dark: { - '--bg-primary': '#1a1b26', '--bg-secondary': '#16161e', '--bg-sidebar': '#13131a', - '--bg-hover': '#24283b', '--border': '#2f3545', '--text-primary': '#c0caf5', - '--text-secondary': '#a9b1d6', '--text-muted': '#565f89', '--accent': '#7aa2f7', - '--accent-green': '#9ece6a', '--tag-bg': '#1f2845', '--tag-text': '#7aa2f7', - '--code-bg': '#16161e', '--search-bg': '#24283b', '--scrollbar': '#2f3545', - '--resize-handle': '#2f3545', '--overlay-bg': 'rgba(0,0,0,0.7)', - '--danger': '#f7768e', '--danger-bg': '#361a22', '--success': '#9ece6a', '--success-bg': '#1a2e1a', - '--accent-card': '#7aa2f7', '--accent-bg': '#1f2845', '--accent-text': '#7aa2f7', - '--green': '#9ece6a', '--green-bg': '#1a2e1a', '--purple': '#bb9af7', '--purple-bg': '#241a3a', - '--surface': '#16161e', '--surface2': '#1a1b26', '--surface3': '#13131a', - '--border-md': '#2f3545', '--text': '#c0caf5', '--text-2': '#a9b1d6', '--text-3': '#565f89', - '--ok': '#9ece6a', '--warn': '#e0af68', '--ai': '#bb9af7', '--err': '#f7768e' - }, - light: { - '--bg-primary': '#d5d6db', '--bg-secondary': '#c8c9d0', '--bg-sidebar': '#bfc0c8', - '--bg-hover': '#bbbbc4', '--border': '#a9aab3', '--text-primary': '#343b58', - '--text-secondary': '#565a6e', '--text-muted': '#848cb0', '--accent': '#34548a', - '--accent-green': '#485e30', '--tag-bg': '#dfe5f5', '--tag-text': '#34548a', - '--code-bg': '#c8c9d0', '--search-bg': '#d5d6db', '--scrollbar': '#a9aab3', - '--resize-handle': '#a9aab3', '--overlay-bg': 'rgba(0,0,0,0.15)', - '--danger': '#8c4351', '--danger-bg': '#f8e0e0', '--success': '#485e30', '--success-bg': '#e0f0d8', - '--accent-card': '#34548a', '--accent-bg': '#dfe5f5', '--accent-text': '#34548a', - '--green': '#485e30', '--green-bg': '#e0f0d8', '--purple': '#5a4a9a', '--purple-bg': '#e8e0f8', - '--surface': '#c8c9d0', '--surface2': '#d5d6db', '--surface3': '#bfc0c8', - '--border-md': '#a9aab3', '--text': '#343b58', '--text-2': '#565a6e', '--text-3': '#848cb0', - '--ok': '#485e30', '--warn': '#8f5e15', '--ai': '#5a4a9a', '--err': '#8c4351' - } - } - }, - - 'nord': { - name: 'Nord', desc: 'Style arctique', - modes: { - dark: { - '--bg-primary': '#2e3440', '--bg-secondary': '#3b4252', '--bg-sidebar': '#242933', - '--bg-hover': '#434c5e', '--border': '#4c566a', '--text-primary': '#eceff4', - '--text-secondary': '#d8dee9', '--text-muted': '#7b88a1', '--accent': '#88c0d0', - '--accent-green': '#a3be8c', '--tag-bg': '#2a3a48', '--tag-text': '#88c0d0', - '--code-bg': '#3b4252', '--search-bg': '#434c5e', '--scrollbar': '#4c566a', - '--resize-handle': '#4c566a', '--overlay-bg': 'rgba(0,0,0,0.6)', - '--danger': '#bf616a', '--danger-bg': '#3a2025', '--success': '#a3be8c', '--success-bg': '#1a2e1a', - '--accent-card': '#88c0d0', '--accent-bg': '#2a3a48', '--accent-text': '#88c0d0', - '--green': '#a3be8c', '--green-bg': '#1a2e1a', '--purple': '#b48ead', '--purple-bg': '#2a2030', - '--surface': '#3b4252', '--surface2': '#2e3440', '--surface3': '#242933', - '--border-md': '#4c566a', '--text': '#eceff4', '--text-2': '#d8dee9', '--text-3': '#7b88a1', - '--ok': '#a3be8c', '--warn': '#ebcb8b', '--ai': '#b48ead', '--err': '#bf616a' - }, - light: { - '--bg-primary': '#eceff4', '--bg-secondary': '#e5e9f0', '--bg-sidebar': '#d8dee9', - '--bg-hover': '#d8dee9', '--border': '#c8cfdb', '--text-primary': '#2e3440', - '--text-secondary': '#4c566a', '--text-muted': '#7b88a1', '--accent': '#5e81ac', - '--accent-green': '#719350', '--tag-bg': '#dfe8f0', '--tag-text': '#5e81ac', - '--code-bg': '#e5e9f0', '--search-bg': '#eceff4', '--scrollbar': '#c8cfdb', - '--resize-handle': '#c8cfdb', '--overlay-bg': 'rgba(0,0,0,0.12)', - '--danger': '#bf616a', '--danger-bg': '#f8e0e0', '--success': '#719350', '--success-bg': '#e0f0d8', - '--accent-card': '#5e81ac', '--accent-bg': '#dfe8f0', '--accent-text': '#5e81ac', - '--green': '#719350', '--green-bg': '#e0f0d8', '--purple': '#7b5e95', '--purple-bg': '#e8dff0', - '--surface': '#e5e9f0', '--surface2': '#eceff4', '--surface3': '#d8dee9', - '--border-md': '#c8cfdb', '--text': '#2e3440', '--text-2': '#4c566a', '--text-3': '#7b88a1', - '--ok': '#719350', '--warn': '#8f6b20', '--ai': '#7b5e95', '--err': '#bf616a' - } - } - }, - - 'night-owl': { - name: 'Night Owl', desc: 'Optimise pour la nuit', - modes: { - dark: { - '--bg-primary': '#011627', '--bg-secondary': '#01111d', '--bg-sidebar': '#010d18', - '--bg-hover': '#0b2942', '--border': '#1d3b53', '--text-primary': '#d6deeb', - '--text-secondary': '#7e97b0', '--text-muted': '#4b6479', '--accent': '#82aaff', - '--accent-green': '#c3e88d', '--tag-bg': '#152d45', '--tag-text': '#82aaff', - '--code-bg': '#01111d', '--search-bg': '#0b2942', '--scrollbar': '#1d3b53', - '--resize-handle': '#1d3b53', '--overlay-bg': 'rgba(0,0,0,0.7)', - '--danger': '#ef5350', '--danger-bg': '#2a1018', '--success': '#c3e88d', '--success-bg': '#0d2818', - '--accent-card': '#82aaff', '--accent-bg': '#152d45', '--accent-text': '#82aaff', - '--green': '#c3e88d', '--green-bg': '#0d2818', '--purple': '#c792ea', '--purple-bg': '#201838', - '--surface': '#01111d', '--surface2': '#011627', '--surface3': '#010d18', - '--border-md': '#1d3b53', '--text': '#d6deeb', '--text-2': '#7e97b0', '--text-3': '#4b6479', - '--ok': '#c3e88d', '--warn': '#ffcb8b', '--ai': '#c792ea', '--err': '#ef5350' - }, - light: { - '--bg-primary': '#fbfbfb', '--bg-secondary': '#f0f0f0', '--bg-sidebar': '#e8e8e8', - '--bg-hover': '#e0e0e0', '--border': '#d4d4d4', '--text-primary': '#403f53', - '--text-secondary': '#5f6c7a', '--text-muted': '#8e99a8', '--accent': '#4876d6', - '--accent-green': '#2d8a4e', '--tag-bg': '#e0e8ff', '--tag-text': '#4876d6', - '--code-bg': '#f0f0f0', '--search-bg': '#fbfbfb', '--scrollbar': '#d4d4d4', - '--resize-handle': '#d4d4d4', '--overlay-bg': 'rgba(0,0,0,0.12)', - '--danger': '#c92a2a', '--danger-bg': '#ffe3e3', '--success': '#2d8a4e', '--success-bg': '#e0ffe0', - '--accent-card': '#4876d6', '--accent-bg': '#e0e8ff', '--accent-text': '#4876d6', - '--green': '#2d8a4e', '--green-bg': '#e0ffe0', '--purple': '#7c3aed', '--purple-bg': '#ede0ff', - '--surface': '#f0f0f0', '--surface2': '#fbfbfb', '--surface3': '#e8e8e8', - '--border-md': '#d4d4d4', '--text': '#403f53', '--text-2': '#5f6c7a', '--text-3': '#8e99a8', - '--ok': '#2d8a4e', '--warn': '#8f6b20', '--ai': '#7c3aed', '--err': '#c92a2a' - } - } - }, - - 'anthracite': { - name: 'Anthracite', desc: 'Material dark', - modes: { - dark: { - '--bg-primary': '#1e1e1e', '--bg-secondary': '#252526', '--bg-sidebar': '#1a1a1a', - '--bg-hover': '#2d2d2d', '--border': '#3e3e3e', '--text-primary': '#d4d4d4', - '--text-secondary': '#9d9d9d', '--text-muted': '#6e6e6e', '--accent': '#9c7aef', - '--accent-green': '#6a9955', '--tag-bg': '#2a2250', '--tag-text': '#9c7aef', - '--code-bg': '#252526', '--search-bg': '#2d2d2d', '--scrollbar': '#3e3e3e', - '--resize-handle': '#3e3e3e', '--overlay-bg': 'rgba(0,0,0,0.7)', - '--danger': '#f44747', '--danger-bg': '#3a1a1a', '--success': '#6a9955', '--success-bg': '#1a2e1a', - '--accent-card': '#9c7aef', '--accent-bg': '#2a2250', '--accent-text': '#9c7aef', - '--green': '#6a9955', '--green-bg': '#1a2e1a', '--purple': '#9c7aef', '--purple-bg': '#2a2250', - '--surface': '#252526', '--surface2': '#1e1e1e', '--surface3': '#1a1a1a', - '--border-md': '#3e3e3e', '--text': '#d4d4d4', '--text-2': '#9d9d9d', '--text-3': '#6e6e6e', - '--ok': '#6a9955', '--warn': '#d7ba7d', '--ai': '#9c7aef', '--err': '#f44747' - }, - light: { - '--bg-primary': '#fafafa', '--bg-secondary': '#f5f5f5', '--bg-sidebar': '#eeeeee', - '--bg-hover': '#e5e5e5', '--border': '#d5d5d5', '--text-primary': '#212121', - '--text-secondary': '#616161', '--text-muted': '#9e9e9e', '--accent': '#7c3aed', - '--accent-green': '#388e3c', '--tag-bg': '#ede0ff', '--tag-text': '#7c3aed', - '--code-bg': '#f5f5f5', '--search-bg': '#fafafa', '--scrollbar': '#d5d5d5', - '--resize-handle': '#d5d5d5', '--overlay-bg': 'rgba(0,0,0,0.12)', - '--danger': '#d32f2f', '--danger-bg': '#fde8e8', '--success': '#388e3c', '--success-bg': '#e8f5e9', - '--accent-card': '#7c3aed', '--accent-bg': '#ede0ff', '--accent-text': '#7c3aed', - '--green': '#388e3c', '--green-bg': '#e8f5e9', '--purple': '#7c3aed', '--purple-bg': '#ede0ff', - '--surface': '#f5f5f5', '--surface2': '#fafafa', '--surface3': '#eeeeee', - '--border-md': '#d5d5d5', '--text': '#212121', '--text-2': '#616161', '--text-3': '#9e9e9e', - '--ok': '#388e3c', '--warn': '#8f6b20', '--ai': '#7c3aed', '--err': '#d32f2f' - } - } - }, - - 'cyberpunk': { - name: 'Cyberpunk', desc: 'Neon vibrant', - modes: { - dark: { - '--bg-primary': '#0a0a0f', '--bg-secondary': '#111122', '--bg-sidebar': '#08080d', - '--bg-hover': '#1a1a33', '--border': '#2a2a55', '--text-primary': '#e0e0ff', - '--text-secondary': '#8888cc', '--text-muted': '#555599', '--accent': '#00ffff', - '--accent-green': '#00ff88', '--tag-bg': '#0a2a3a', '--tag-text': '#00ffff', - '--code-bg': '#111122', '--search-bg': '#1a1a33', '--scrollbar': '#2a2a55', - '--resize-handle': '#2a2a55', '--overlay-bg': 'rgba(0,0,0,0.8)', - '--danger': '#ff3366', '--danger-bg': '#331122', '--success': '#00ff88', '--success-bg': '#003322', - '--accent-card': '#00ffff', '--accent-bg': '#0a2a3a', '--accent-text': '#00ffff', - '--green': '#00ff88', '--green-bg': '#003322', '--purple': '#ff00ff', '--purple-bg': '#220033', - '--surface': '#111122', '--surface2': '#0a0a0f', '--surface3': '#08080d', - '--border-md': '#2a2a55', '--text': '#e0e0ff', '--text-2': '#8888cc', '--text-3': '#555599', - '--ok': '#00ff88', '--warn': '#ffaa00', '--ai': '#ff00ff', '--err': '#ff3366' - }, - light: { - '--bg-primary': '#f0f0ff', '--bg-secondary': '#e8e8ff', '--bg-sidebar': '#e0e0f8', - '--bg-hover': '#d8d8f0', '--border': '#c0c0e0', '--text-primary': '#1a1a33', - '--text-secondary': '#4a4a6a', '--text-muted': '#8080a0', '--accent': '#0077cc', - '--accent-green': '#008844', '--tag-bg': '#ddeeff', '--tag-text': '#0077cc', - '--code-bg': '#e8e8ff', '--search-bg': '#f0f0ff', '--scrollbar': '#c0c0e0', - '--resize-handle': '#c0c0e0', '--overlay-bg': 'rgba(0,0,0,0.1)', - '--danger': '#cc2244', '--danger-bg': '#ffe0e8', '--success': '#008844', '--success-bg': '#d8ffe0', - '--accent-card': '#0077cc', '--accent-bg': '#ddeeff', '--accent-text': '#0077cc', - '--green': '#008844', '--green-bg': '#d8ffe0', '--purple': '#8800cc', '--purple-bg': '#f0d8ff', - '--surface': '#e8e8ff', '--surface2': '#f0f0ff', '--surface3': '#e0e0f8', - '--border-md': '#c0c0e0', '--text': '#1a1a33', '--text-2': '#4a4a6a', '--text-3': '#8080a0', - '--ok': '#008844', '--warn': '#996600', '--ai': '#8800cc', '--err': '#cc2244' - } - } - }, - - 'navy-elegance': { - name: 'Navy Elegance', desc: 'Bleu profond & or', - modes: { - dark: { - '--bg-primary': '#0a1628', '--bg-secondary': '#0d1f3c', '--bg-sidebar': '#081220', - '--bg-hover': '#162d50', '--border': '#1e3a5f', '--text-primary': '#d4dde8', - '--text-secondary': '#8899b4', '--text-muted': '#556688', '--accent': '#c9a84c', - '--accent-green': '#4caf7c', '--tag-bg': '#1e2840', '--tag-text': '#c9a84c', - '--code-bg': '#0d1f3c', '--search-bg': '#162d50', '--scrollbar': '#1e3a5f', - '--resize-handle': '#1e3a5f', '--overlay-bg': 'rgba(0,0,0,0.7)', - '--danger': '#d94a5a', '--danger-bg': '#351a22', '--success': '#4caf7c', '--success-bg': '#12281e', - '--accent-card': '#c9a84c', '--accent-bg': '#282218', '--accent-text': '#c9a84c', - '--green': '#4caf7c', '--green-bg': '#12281e', '--purple': '#8b6fc0', '--purple-bg': '#201a3a', - '--surface': '#0d1f3c', '--surface2': '#0a1628', '--surface3': '#081220', - '--border-md': '#1e3a5f', '--text': '#d4dde8', '--text-2': '#8899b4', '--text-3': '#556688', - '--ok': '#4caf7c', '--warn': '#c9a84c', '--ai': '#8b6fc0', '--err': '#d94a5a' - }, - light: { - '--bg-primary': '#f5f0e8', '--bg-secondary': '#ede6d8', '--bg-sidebar': '#e8dfd0', - '--bg-hover': '#e0d8c8', '--border': '#c8bda8', '--text-primary': '#2a3a50', - '--text-secondary': '#5a6a80', '--text-muted': '#8a9aa8', '--accent': '#8b6914', - '--accent-green': '#3d7a4c', '--tag-bg': '#f0e8d0', '--tag-text': '#8b6914', - '--code-bg': '#ede6d8', '--search-bg': '#f5f0e8', '--scrollbar': '#c8bda8', - '--resize-handle': '#c8bda8', '--overlay-bg': 'rgba(0,0,0,0.1)', - '--danger': '#b8383a', '--danger-bg': '#f8e0e0', '--success': '#3d7a4c', '--success-bg': '#e0f0e0', - '--accent-card': '#8b6914', '--accent-bg': '#f0e8d0', '--accent-text': '#8b6914', - '--green': '#3d7a4c', '--green-bg': '#e0f0e0', '--purple': '#6a4c8a', '--purple-bg': '#e8dff0', - '--surface': '#ede6d8', '--surface2': '#f5f0e8', '--surface3': '#e8dfd0', - '--border-md': '#c8bda8', '--text': '#2a3a50', '--text-2': '#5a6a80', '--text-3': '#8a9aa8', - '--ok': '#3d7a4c', '--warn': '#8b6914', '--ai': '#6a4c8a', '--err': '#b8383a' - } - } - }, - - 'tons-terreux': { - name: 'Tons Terreux', desc: 'Sensation organique', - modes: { - dark: { - '--bg-primary': '#1c1a16', '--bg-secondary': '#252218', '--bg-sidebar': '#161410', - '--bg-hover': '#302b20', '--border': '#3d3628', '--text-primary': '#e8e0d0', - '--text-secondary': '#a89880', '--text-muted': '#6b5d48', '--accent': '#c8a050', - '--accent-green': '#6b9b50', '--tag-bg': '#2a2418', '--tag-text': '#c8a050', - '--code-bg': '#252218', '--search-bg': '#302b20', '--scrollbar': '#3d3628', - '--resize-handle': '#3d3628', '--overlay-bg': 'rgba(0,0,0,0.7)', - '--danger': '#c86050', '--danger-bg': '#352018', '--success': '#6b9b50', '--success-bg': '#1a2a14', - '--accent-card': '#c8a050', '--accent-bg': '#2a2418', '--accent-text': '#c8a050', - '--green': '#6b9b50', '--green-bg': '#1a2a14', '--purple': '#9070b0', '--purple-bg': '#221a30', - '--surface': '#252218', '--surface2': '#1c1a16', '--surface3': '#161410', - '--border-md': '#3d3628', '--text': '#e8e0d0', '--text-2': '#a89880', '--text-3': '#6b5d48', - '--ok': '#6b9b50', '--warn': '#c8a050', '--ai': '#9070b0', '--err': '#c86050' - }, - light: { - '--bg-primary': '#f8f4ec', '--bg-secondary': '#f0e8d8', '--bg-sidebar': '#e8e0d0', - '--bg-hover': '#e0d8c8', '--border': '#c8bda0', '--text-primary': '#3d3028', - '--text-secondary': '#6b5d48', '--text-muted': '#9a8a70', '--accent': '#8b6914', - '--accent-green': '#5a8440', '--tag-bg': '#f0e0c8', '--tag-text': '#8b6914', - '--code-bg': '#f0e8d8', '--search-bg': '#f8f4ec', '--scrollbar': '#c8bda0', - '--resize-handle': '#c8bda0', '--overlay-bg': 'rgba(0,0,0,0.1)', - '--danger': '#a84040', '--danger-bg': '#f8e0e0', '--success': '#5a8440', '--success-bg': '#e0f0d8', - '--accent-card': '#8b6914', '--accent-bg': '#f0e0c8', '--accent-text': '#8b6914', - '--green': '#5a8440', '--green-bg': '#e0f0d8', '--purple': '#7058a0', '--purple-bg': '#e8dff8', - '--surface': '#f0e8d8', '--surface2': '#f8f4ec', '--surface3': '#e8e0d0', - '--border-md': '#c8bda0', '--text': '#3d3028', '--text-2': '#6b5d48', '--text-3': '#9a8a70', - '--ok': '#5a8440', '--warn': '#8b6914', '--ai': '#7058a0', '--err': '#a84040' - } - } - } -}; - -// ── Theme Engine ───────────────────────────────────────────────────── -var _currentTheme = 'defaut-obsigate'; -var _currentMode = 'dark'; - -function applyTheme(themeKey, mode) { - var theme = THEMES[themeKey]; - if (!theme) return; - mode = mode || _currentMode || 'dark'; - var vars = theme.modes[mode]; - if (!vars) return; - - var root = document.documentElement; - Object.keys(vars).forEach(function(key) { - root.style.setProperty(key, vars[key]); - }); - - _currentTheme = themeKey; - _currentMode = mode; - try { localStorage.setItem('obsigate-theme', themeKey); } catch(e) {} - try { localStorage.setItem('obsigate-theme-mode', mode); } catch(e) {} -} - -function toggleThemeMode() { - var newMode = _currentMode === 'dark' ? 'light' : 'dark'; - applyTheme(_currentTheme, newMode); - return newMode; -} - -function getCurrentTheme() { return _currentTheme; } -function getCurrentMode() { return _currentMode; } - -function initThemes() { - var saved = null; - var savedMode = null; - try { saved = localStorage.getItem('obsigate-theme'); } catch(e) {} - try { savedMode = localStorage.getItem('obsigate-theme-mode'); } catch(e) {} - if (saved && THEMES[saved]) _currentTheme = saved; - if (savedMode) _currentMode = savedMode; - applyTheme(_currentTheme, _currentMode); -} - -export { THEMES, applyTheme, toggleThemeMode, getCurrentTheme, getCurrentMode, initThemes }; diff --git a/desktop/frontend-static/js/ui.js b/desktop/frontend-static/js/ui.js deleted file mode 100644 index 0c4ec8e..0000000 --- a/desktop/frontend-static/js/ui.js +++ /dev/null @@ -1,2351 +0,0 @@ -/* ObsiGate — UI module */ -import { api, AuthManager, initLoginForm } from './auth.js'; -import { state } from './state.js'; -import { openFile, showWelcome, renderFile, el } from './viewer.js'; -import { safeCreateIcons, getFileIcon, escapeHtml } from './utils.js'; -import { syncActiveFileTreeItem, refreshSidebarTreePreservingState } from './sidebar.js'; -import { GraphViewManager } from './graph.js'; -import { DashboardConflictsWidget } from './dashboard.js'; -import { t, tr } from './i18n.js'; -import { toggleThemeMode } from './themes.js'; -// --------------------------------------------------------------------------- -// Right Sidebar Manager -// --------------------------------------------------------------------------- - -export const RightSidebarManager = { - init() { - this.loadState(); - this.initToggle(); - this.initResize(); - }, - - loadState() { - const savedVisible = localStorage.getItem("obsigate-right-sidebar-visible"); - const savedWidth = localStorage.getItem("obsigate-right-sidebar-width"); - - if (savedVisible !== null) { - state.rightSidebarVisible = savedVisible === "true"; - } - - if (savedWidth) { - state.rightSidebarWidth = parseInt(savedWidth) || 280; - } - - this.applyState(); - }, - - applyState() { - const sidebar = document.getElementById("right-sidebar"); - const handle = document.getElementById("right-sidebar-resize-handle"); - const tocBtn = document.getElementById("toc-toggle-btn"); - const headerToggleBtn = document.getElementById("right-sidebar-toggle-btn"); - - if (!sidebar) return; - - if (state.rightSidebarVisible) { - sidebar.classList.remove("hidden"); - sidebar.style.width = `${state.rightSidebarWidth}px`; - if (handle) handle.classList.remove("hidden"); - if (tocBtn) { - tocBtn.classList.add("active"); - tocBtn.title = "Masquer le sommaire"; - } - if (headerToggleBtn) { - headerToggleBtn.title = "Masquer le panneau"; - headerToggleBtn.setAttribute("aria-label", "Masquer le panneau"); - } - } else { - sidebar.classList.add("hidden"); - if (handle) handle.classList.add("hidden"); - if (tocBtn) { - tocBtn.classList.remove("active"); - tocBtn.title = "Afficher le sommaire"; - } - if (headerToggleBtn) { - headerToggleBtn.title = "Afficher le panneau"; - headerToggleBtn.setAttribute("aria-label", "Afficher le panneau"); - } - } - - // Update icons - safeCreateIcons(); - }, - - toggle() { - state.rightSidebarVisible = !state.rightSidebarVisible; - localStorage.setItem("obsigate-right-sidebar-visible", state.rightSidebarVisible); - this.applyState(); - }, - - initToggle() { - const toggleBtn = document.getElementById("right-sidebar-toggle-btn"); - if (toggleBtn) { - toggleBtn.addEventListener("click", () => this.toggle()); - } - }, - - initResize() { - const handle = document.getElementById("right-sidebar-resize-handle"); - const sidebar = document.getElementById("right-sidebar"); - - if (!handle || !sidebar) return; - - let isResizing = false; - let startX = 0; - let startWidth = 0; - - const onMouseDown = (e) => { - isResizing = true; - startX = e.clientX; - startWidth = sidebar.offsetWidth; - handle.classList.add("active"); - document.body.style.cursor = "ew-resize"; - document.body.style.userSelect = "none"; - }; - - const onMouseMove = (e) => { - if (!isResizing) return; - - const delta = startX - e.clientX; - let newWidth = startWidth + delta; - - // Constrain width - newWidth = Math.max(200, Math.min(400, newWidth)); - - sidebar.style.width = `${newWidth}px`; - state.rightSidebarWidth = newWidth; - }; - - const onMouseUp = () => { - if (!isResizing) return; - - isResizing = false; - handle.classList.remove("active"); - document.body.style.cursor = ""; - document.body.style.userSelect = ""; - - localStorage.setItem("obsigate-right-sidebar-width", state.rightSidebarWidth); - }; - - handle.addEventListener("mousedown", onMouseDown); - document.addEventListener("mousemove", onMouseMove); - document.addEventListener("mouseup", onMouseUp); - }, -}; - - -// --------------------------------------------------------------------------- -// Theme -// --------------------------------------------------------------------------- -export function initTheme() { - const saved = localStorage.getItem("obsigate-theme") || "dark"; - applyTheme(saved); -} - -export function applyTheme(theme) { - document.documentElement.setAttribute("data-theme", theme); - localStorage.setItem("obsigate-theme", theme); - - // Update theme button icon and label - const themeBtn = document.getElementById("theme-toggle"); - const themeLabel = document.getElementById("theme-label"); - if (themeBtn && themeLabel) { - const icon = themeBtn.querySelector("i"); - if (icon) { - icon.setAttribute("data-lucide", theme === "dark" ? "moon" : "sun"); - } - themeLabel.textContent = theme === "dark" ? t('theme.dark') : t('theme.light'); - safeCreateIcons(); - } - - // Swap highlight.js theme - const darkSheet = document.getElementById("hljs-theme-dark"); - const lightSheet = document.getElementById("hljs-theme-light"); - if (darkSheet && lightSheet) { - darkSheet.disabled = theme !== "dark"; - lightSheet.disabled = theme !== "light"; - } - - // Update Mermaid theme for newly rendered diagrams - import('./mermaid-viewer.js').then(function(m) { - m.updateMermaidTheme(theme === 'dark'); - }).catch(function() {}); -} - -export function toggleTheme() { - const newMode = toggleThemeMode(); - // Update the theme toggle label - const themeLabel = document.getElementById("theme-label"); - if (themeLabel) { - themeLabel.textContent = newMode === "dark" ? t('theme.dark') : t('theme.light'); - } - // Update the theme toggle icon - const themeBtn = document.getElementById("theme-toggle"); - if (themeBtn) { - const icon = themeBtn.querySelector("i"); - if (icon) { - icon.setAttribute("data-lucide", newMode === "dark" ? "moon" : "sun"); - } - } - safeCreateIcons(); -} - -export function initHeaderMenu() { - const menuBtn = document.getElementById("header-menu-btn"); - const menuDropdown = document.getElementById("header-menu-dropdown"); - - if (!menuBtn || !menuDropdown) return; - - menuBtn.addEventListener("click", (e) => { - e.stopPropagation(); - menuBtn.classList.toggle("active"); - menuDropdown.classList.toggle("active"); - }); - - // Close menu when clicking outside - document.addEventListener("click", (e) => { - if (!menuDropdown.contains(e.target) && e.target !== menuBtn) { - menuBtn.classList.remove("active"); - menuDropdown.classList.remove("active"); - } - }); - - // Prevent menu from closing when clicking inside - menuDropdown.addEventListener("click", (e) => { - e.stopPropagation(); - }); -} - -export function closeHeaderMenu() { - const menuBtn = document.getElementById("header-menu-btn"); - const menuDropdown = document.getElementById("header-menu-dropdown"); - if (!menuBtn || !menuDropdown) return; - menuBtn.classList.remove("active"); - menuDropdown.classList.remove("active"); -} - - -// --------------------------------------------------------------------------- -// Custom Dropdowns -// --------------------------------------------------------------------------- -export function initCustomDropdowns() { - document.querySelectorAll(".custom-dropdown").forEach((dropdown) => { - const trigger = dropdown.querySelector(".custom-dropdown-trigger"); - const options = dropdown.querySelectorAll(".custom-dropdown-option"); - const hiddenInput = dropdown.querySelector('input[type="hidden"]'); - const selectedText = dropdown.querySelector(".custom-dropdown-selected"); - const menu = dropdown.querySelector(".custom-dropdown-menu"); - - if (!trigger) return; - - // Toggle dropdown - trigger.addEventListener("click", (e) => { - e.stopPropagation(); - const isOpen = dropdown.classList.contains("open"); - - // Close all other dropdowns - document.querySelectorAll(".custom-dropdown.open").forEach((d) => { - if (d !== dropdown) d.classList.remove("open"); - }); - - dropdown.classList.toggle("open", !isOpen); - trigger.setAttribute("aria-expanded", !isOpen); - - // Position fixed menu for sidebar dropdowns - if (!isOpen && dropdown.classList.contains("sidebar-dropdown") && menu) { - const rect = trigger.getBoundingClientRect(); - menu.style.top = `${rect.bottom + 4}px`; - menu.style.left = `${rect.left}px`; - menu.style.width = `${rect.width}px`; - } - }); - - // Handle option selection - options.forEach((option) => { - option.addEventListener("click", (e) => { - e.stopPropagation(); - const value = option.getAttribute("data-value"); - const text = option.textContent; - - // Update hidden input - if (hiddenInput) { - hiddenInput.value = value; - // Trigger change event - hiddenInput.dispatchEvent(new Event("change", { bubbles: true })); - } - - // Update selected text - if (selectedText) { - selectedText.textContent = text; - } - - // Update visual selection - options.forEach((opt) => opt.classList.remove("selected")); - option.classList.add("selected"); - - // Close dropdown - dropdown.classList.remove("open"); - trigger.setAttribute("aria-expanded", "false"); - }); - }); - }); - - // Close dropdowns when clicking outside - document.addEventListener("click", () => { - document.querySelectorAll(".custom-dropdown.open").forEach((dropdown) => { - dropdown.classList.remove("open"); - const trigger = dropdown.querySelector(".custom-dropdown-trigger"); - if (trigger) trigger.setAttribute("aria-expanded", "false"); - }); - }); -} - -// Helper to populate custom dropdown options -export function populateCustomDropdown(dropdownId, optionsList, defaultValue) { - const dropdown = document.getElementById(dropdownId); - if (!dropdown) return; - - const optionsContainer = dropdown.querySelector(".custom-dropdown-menu"); - const hiddenInput = dropdown.querySelector('input[type="hidden"]'); - const selectedText = dropdown.querySelector(".custom-dropdown-selected"); - - if (!optionsContainer) return; - - // Clear existing options (keep the first one if it's the default) - optionsContainer.innerHTML = ""; - - // Add new options - optionsList.forEach((opt) => { - const li = document.createElement("li"); - li.className = "custom-dropdown-option"; - li.setAttribute("role", "option"); - li.setAttribute("data-value", opt.value); - li.textContent = opt.text; - if (opt.value === defaultValue) { - li.classList.add("selected"); - if (selectedText) selectedText.textContent = opt.text; - if (hiddenInput) hiddenInput.value = opt.value; - } - optionsContainer.appendChild(li); - }); - - // Re-initialize click handlers - optionsContainer.querySelectorAll(".custom-dropdown-option").forEach((option) => { - option.addEventListener("click", (e) => { - e.stopPropagation(); - const value = option.getAttribute("data-value"); - const text = option.textContent; - - if (hiddenInput) { - hiddenInput.value = value; - hiddenInput.dispatchEvent(new Event("change", { bubbles: true })); - } - - if (selectedText) { - selectedText.textContent = text; - } - - optionsContainer.querySelectorAll(".custom-dropdown-option").forEach((opt) => opt.classList.remove("selected")); - option.classList.add("selected"); - - dropdown.classList.remove("open"); - const trigger = dropdown.querySelector(".custom-dropdown-trigger"); - if (trigger) trigger.setAttribute("aria-expanded", "false"); - }); - }); -} - - -// --------------------------------------------------------------------------- -// Toast notifications -// --------------------------------------------------------------------------- - -/** Display a brief toast message at the bottom of the viewport. */ -export function showToast(message, type) { - // Auto-translate French messages via reverse lookup - message = tr(message); - type = type || "info"; - let container = document.getElementById("toast-container"); - if (!container) { - container = document.createElement("div"); - container.id = "toast-container"; - container.className = "toast-container"; - container.setAttribute("aria-live", "polite"); - document.body.appendChild(container); - } - var toast = document.createElement("div"); - toast.className = "toast toast-" + type; - toast.textContent = message; - container.appendChild(toast); - // Trigger entrance animation - requestAnimationFrame(function () { - toast.classList.add("show"); - }); - setTimeout(function () { - toast.classList.remove("show"); - toast.addEventListener("transitionend", function () { - toast.remove(); - }); - }, 3500); -} - - -// --------------------------------------------------------------------------- -// Sidebar toggle (desktop) -// --------------------------------------------------------------------------- -export function initSidebarToggle() { - const toggleBtn = document.getElementById("sidebar-toggle-btn"); - const sidebar = document.getElementById("sidebar"); - const resizeHandle = document.getElementById("sidebar-resize-handle"); - - if (!toggleBtn || !sidebar || !resizeHandle) return; - - // Restore saved state - const savedState = localStorage.getItem("obsigate-sidebar-hidden"); - if (savedState === "true") { - sidebar.classList.add("hidden"); - resizeHandle.classList.add("hidden"); - toggleBtn.classList.add("active"); - } - - toggleBtn.addEventListener("click", () => { - const isHidden = sidebar.classList.toggle("hidden"); - resizeHandle.classList.toggle("hidden", isHidden); - toggleBtn.classList.toggle("active", isHidden); - localStorage.setItem("obsigate-sidebar-hidden", isHidden ? "true" : "false"); - }); -} - - -// --------------------------------------------------------------------------- -// Mobile sidebar -// --------------------------------------------------------------------------- -export function initMobile() { - const hamburger = document.getElementById("hamburger-btn"); - const overlay = document.getElementById("sidebar-overlay"); - const sidebar = document.getElementById("sidebar"); - - hamburger.addEventListener("click", () => { - sidebar.classList.toggle("mobile-open"); - overlay.classList.toggle("active"); - }); - - overlay.addEventListener("click", () => { - sidebar.classList.remove("mobile-open"); - overlay.classList.remove("active"); - }); -} - -export function closeMobileSidebar() { - const sidebar = document.getElementById("sidebar"); - const overlay = document.getElementById("sidebar-overlay"); - if (sidebar) sidebar.classList.remove("mobile-open"); - if (overlay) overlay.classList.remove("active"); -} - - -// --------------------------------------------------------------------------- -// Resizable sidebar (horizontal) -// --------------------------------------------------------------------------- -export function initSidebarResize() { - const handle = document.getElementById("sidebar-resize-handle"); - const sidebar = document.getElementById("sidebar"); - if (!handle || !sidebar) return; - - // Restore saved width - const savedWidth = localStorage.getItem("obsigate-sidebar-width"); - if (savedWidth) { - sidebar.style.width = savedWidth + "px"; - } - - let startX = 0; - let startWidth = 0; - - function onMouseMove(e) { - const newWidth = Math.min(500, Math.max(200, startWidth + (e.clientX - startX))); - sidebar.style.width = newWidth + "px"; - } - - function onMouseUp() { - document.body.classList.remove("resizing"); - handle.classList.remove("active"); - document.removeEventListener("mousemove", onMouseMove); - document.removeEventListener("mouseup", onMouseUp); - localStorage.setItem("obsigate-sidebar-width", parseInt(sidebar.style.width)); - } - - handle.addEventListener("mousedown", (e) => { - e.preventDefault(); - startX = e.clientX; - startWidth = sidebar.getBoundingClientRect().width; - document.body.classList.add("resizing"); - handle.classList.add("active"); - document.addEventListener("mousemove", onMouseMove); - document.addEventListener("mouseup", onMouseUp); - }); -} - - -// --------------------------------------------------------------------------- -// Resizable tag section (vertical) -// --------------------------------------------------------------------------- -export function initTagResize() { - const handle = document.getElementById("tag-resize-handle"); - const tagSection = document.getElementById("tag-cloud-section"); - if (!handle || !tagSection) return; - - // Restore saved height - const savedHeight = localStorage.getItem("obsigate-tag-height"); - if (savedHeight) { - tagSection.style.height = savedHeight + "px"; - } - - let startY = 0; - let startHeight = 0; - - function onMouseMove(e) { - // Dragging up increases height, dragging down decreases - const newHeight = Math.min(400, Math.max(60, startHeight - (e.clientY - startY))); - tagSection.style.height = newHeight + "px"; - } - - function onMouseUp() { - document.body.classList.remove("resizing-v"); - handle.classList.remove("active"); - document.removeEventListener("mousemove", onMouseMove); - document.removeEventListener("mouseup", onMouseUp); - localStorage.setItem("obsigate-tag-height", parseInt(tagSection.style.height)); - } - - handle.addEventListener("mousedown", (e) => { - e.preventDefault(); - startY = e.clientY; - startHeight = tagSection.getBoundingClientRect().height; - document.body.classList.add("resizing-v"); - handle.classList.add("active"); - document.addEventListener("mousemove", onMouseMove); - document.addEventListener("mouseup", onMouseUp); - }); -} - - -// --------------------------------------------------------------------------- -// Frontmatter Accent Card Builder -// --------------------------------------------------------------------------- - -// Persist toggle state across document openings -let _frontmatterOpen = false; - -export function buildFrontmatterCard(frontmatter) { - // Helper: format date - function formatDate(iso) { - if (!iso) return "—"; - const d = new Date(iso); - const date = d.toISOString().slice(0, 10); - const time = d.toTimeString().slice(0, 5); - return `${date} · ${time}`; - } - - // Extract boolean flags - const booleanFlags = ["publish", "favoris", "template", "task", "archive", "draft", "private"].map((key) => ({ key, value: !!frontmatter[key] })); - - // Toggle state (persisted across documents) - let isOpen = _frontmatterOpen; - - // Build header with chevron - const chevron = el("span", { class: "fm-chevron " + (isOpen ? "open" : "closed") }); - chevron.innerHTML = ''; - - const fmHeader = el("div", { class: "fm-header" }, [chevron, document.createTextNode("Frontmatter")]); - - // ZONE 1: Top strip - const topBadges = []; - - // Title badge - const title = frontmatter.titre || frontmatter.title || ""; - if (title) { - topBadges.push(el("span", { class: "ac-title" }, [document.createTextNode(`"${title}"`)])); - } - - // Status badge - if (frontmatter.statut) { - const statusBadge = el("span", { class: "ac-badge green" }, [el("span", { class: "ac-dot" }), document.createTextNode(frontmatter.statut)]); - topBadges.push(statusBadge); - } - - // Category badge - if (frontmatter.catégorie || frontmatter.categorie) { - const cat = frontmatter.catégorie || frontmatter.categorie; - const catBadge = el("span", { class: "ac-badge blue" }, [document.createTextNode(cat)]); - topBadges.push(catBadge); - } - - // Publish badge - if (frontmatter.publish) { - topBadges.push(el("span", { class: "ac-badge purple" }, [document.createTextNode("publié")])); - } - - // Favoris badge - if (frontmatter.favoris) { - topBadges.push(el("span", { class: "ac-badge purple" }, [document.createTextNode("favori")])); - } - - const acTop = el("div", { class: "ac-top" }, topBadges); - - // ZONE 2: Body 2 columns - const leftCol = el("div", { class: "ac-col" }, [ - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("auteur")]), el("span", { class: "ac-v" }, [document.createTextNode(frontmatter.auteur || "—")])]), - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("catégorie")]), el("span", { class: "ac-v" }, [document.createTextNode(frontmatter.catégorie || frontmatter.categorie || "—")])]), - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("statut")]), el("span", { class: "ac-v" }, [document.createTextNode(frontmatter.statut || "—")])]), - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("aliases")]), el("span", { class: "ac-v muted" }, [document.createTextNode(frontmatter.aliases && frontmatter.aliases.length > 0 ? frontmatter.aliases.join(", ") : "[]")])]), - ]); - - const rightCol = el("div", { class: "ac-col" }, [ - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("creation_date")]), el("span", { class: "ac-v mono" }, [document.createTextNode(formatDate(frontmatter.creation_date))])]), - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("modification_date")]), el("span", { class: "ac-v mono" }, [document.createTextNode(formatDate(frontmatter.modification_date))])]), - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("publish")]), el("span", { class: "ac-v" }, [document.createTextNode(String(frontmatter.publish || false))])]), - el("div", { class: "ac-row" }, [el("span", { class: "ac-k" }, [document.createTextNode("favoris")]), el("span", { class: "ac-v" }, [document.createTextNode(String(frontmatter.favoris || false))])]), - ]); - - const acBody = el("div", { class: "ac-body" }, [leftCol, rightCol]); - - // ZONE 3: Tags row - const tagPills = []; - if (frontmatter.tags && frontmatter.tags.length > 0) { - frontmatter.tags.forEach((tag) => { - tagPills.push(el("span", { class: "ac-tag" }, [document.createTextNode(tag)])); - }); - } - - const acTagsRow = el("div", { class: "ac-tags-row" }, [el("span", { class: "ac-tags-k" }, [document.createTextNode("tags")]), el("div", { class: "ac-tags-wrap" }, tagPills)]); - - // ZONE 4: Flags row - const flagChips = []; - booleanFlags.forEach((flag) => { - const chipClass = flag.value ? "flag-chip on" : "flag-chip off"; - flagChips.push(el("span", { class: chipClass }, [el("span", { class: "flag-dot" }), document.createTextNode(flag.key)])); - }); - - const acFlagsRow = el("div", { class: "ac-flags-row" }, [el("span", { class: "ac-flags-k" }, [document.createTextNode("flags")]), ...flagChips]); - - // Assemble the card - const acCard = el("div", { class: "ac-card" }, [acTop, acBody, acTagsRow, acFlagsRow]); - - // Set initial display based on persisted state - if (!isOpen) acCard.style.display = "none"; - - // Toggle functionality - fmHeader.addEventListener("click", () => { - isOpen = !isOpen; - _frontmatterOpen = isOpen; - if (isOpen) { - acCard.style.display = "block"; - chevron.classList.remove("closed"); - chevron.classList.add("open"); - } else { - acCard.style.display = "none"; - chevron.classList.remove("open"); - chevron.classList.add("closed"); - } - safeCreateIcons(); - }); - - // Wrap in section - const fmSection = el("div", { class: "fm-section" }, [fmHeader, acCard]); - - return fmSection; -} - - -// --------------------------------------------------------------------------- -// File Operations Manager -// --------------------------------------------------------------------------- - -const FileOperations = { - showCreateDirectoryModal(vault, parentPath) { - const overlay = this._createModalOverlay(); - const modal = document.createElement('div'); - modal.className = 'obsigate-modal'; - modal.innerHTML = ` -
    -

    Créer un dossier

    -
    -
    - -
    - - `; - - overlay.appendChild(modal); - document.body.appendChild(overlay); - - setTimeout(() => overlay.classList.add('active'), 10); - - const input = modal.querySelector('#dir-name-input'); - const errorDiv = modal.querySelector('#dir-error'); - const createBtn = modal.querySelector('#dir-create-btn'); - const cancelBtn = modal.querySelector('#dir-cancel-btn'); - - input.focus(); - - const validateName = (name) => { - if (!name.trim()) return 'Le nom ne peut pas être vide'; - if (/[/\\:*?"<>|]/.test(name)) return 'Caractères interdits: / \\ : * ? " < > |'; - return null; - }; - - input.addEventListener('input', () => { - const error = validateName(input.value); - if (error) { - errorDiv.textContent = error; - errorDiv.style.display = 'block'; - input.classList.add('error'); - } else { - errorDiv.style.display = 'none'; - input.classList.remove('error'); - } - }); - - const create = async () => { - const name = input.value.trim(); - const error = validateName(name); - if (error) { - errorDiv.textContent = error; - errorDiv.style.display = 'block'; - return; - } - - const path = parentPath ? `${parentPath}/${name}` : name; - createBtn.disabled = true; - createBtn.textContent = t('modal.creating'); - - try { - await api(`/api/directory/${encodeURIComponent(vault)}`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ path }), - }); - - showToast(t('toast.dir_created', {name: name}), 'success'); - this._closeModal(overlay); - await refreshSidebarTreePreservingState(); - } catch (err) { - showToast(err.message || t('toast.create_error'), 'error'); - createBtn.disabled = false; - createBtn.textContent = t('modal.create_btn'); - } - }; - - createBtn.addEventListener('click', create); - cancelBtn.addEventListener('click', () => this._closeModal(overlay)); - - input.addEventListener('keydown', (e) => { - if (e.key === 'Enter') create(); - if (e.key === 'Escape') this._closeModal(overlay); - }); - }, - - showCreateFileModal(vault, parentPath) { - const overlay = this._createModalOverlay(); - const modal = document.createElement('div'); - modal.className = 'obsigate-modal'; - modal.innerHTML = ` -
    -

    ${t('modal.create_file')}

    -
    -
    - - -
    - - `; - - overlay.appendChild(modal); - document.body.appendChild(overlay); - - setTimeout(() => overlay.classList.add('active'), 10); - - const input = modal.querySelector('#file-name-input'); - const extSelect = modal.querySelector('#file-ext-select'); - const errorDiv = modal.querySelector('#file-error'); - const createBtn = modal.querySelector('#file-create-btn'); - const cancelBtn = modal.querySelector('#file-cancel-btn'); - - input.focus(); - - const validateName = (name) => { - if (!name.trim()) return 'Le nom ne peut pas être vide'; - if (/[/\\:*?"<>|]/.test(name)) return 'Caractères interdits: / \\ : * ? " < > |'; - return null; - }; - - input.addEventListener('input', () => { - const error = validateName(input.value); - if (error) { - errorDiv.textContent = error; - errorDiv.style.display = 'block'; - input.classList.add('error'); - } else { - errorDiv.style.display = 'none'; - input.classList.remove('error'); - } - }); - - const create = async () => { - let name = input.value.trim(); - const error = validateName(name); - if (error) { - errorDiv.textContent = error; - errorDiv.style.display = 'block'; - return; - } - - const ext = extSelect.value; - if (!name.endsWith(ext)) { - name += ext; - } - - const path = parentPath ? `${parentPath}/${name}` : name; - createBtn.disabled = true; - createBtn.textContent = t('modal.creating'); - - try { - await api(`/api/file/${encodeURIComponent(vault)}`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ path, content: '' }), - }); - - showToast(t('toast.file_created', {name: name}), 'success'); - this._closeModal(overlay); - await refreshSidebarTreePreservingState(); - openFile(vault, path); - } catch (err) { - showToast(err.message || t('toast.create_error'), 'error'); - createBtn.disabled = false; - createBtn.textContent = t('modal.create_btn'); - } - }; - - createBtn.addEventListener('click', create); - cancelBtn.addEventListener('click', () => this._closeModal(overlay)); - - input.addEventListener('keydown', (e) => { - if (e.key === 'Enter') create(); - if (e.key === 'Escape') this._closeModal(overlay); - }); - }, - - async startInlineRename(vault, path, type) { - const item = document.querySelector(`.tree-item[data-vault="${CSS.escape(vault)}"][data-path="${CSS.escape(path)}"]`); - if (!item) { - showToast('Élément introuvable dans l’arborescence', 'error'); - return; - } - - // Find the text span (.tree-item-text) — tree items use spans, not direct text nodes - const textSpan = item.querySelector('.tree-item-text'); - if (!textSpan) { - showToast(t('ui.cannot_rename'), 'error'); - return; - } - - const originalText = textSpan.textContent; - const trimmedOriginal = originalText.trim(); - const currentName = path.split('/').pop() || trimmedOriginal; - const baseName = type === 'file' ? currentName.replace(/(\.[^./\\]+)$/i, '') : currentName; - const extension = type === 'file' ? (currentName.match(/(\.[^./\\]+)$/i)?.[1] || '') : ''; - - const input = document.createElement('input'); - input.type = 'text'; - input.className = 'sidebar-item-input'; - input.value = baseName; - - // Hide the text span, show input - textSpan.style.display = 'none'; - textSpan.insertAdjacentElement('afterend', input); - - const restore = () => { - input.remove(); - textSpan.style.display = ''; - }; - - const validateName = (name) => { - if (!name.trim()) return 'Le nom ne peut pas être vide'; - if (/[/\\:*?"<>|]/.test(name)) return 'Caractères interdits: / \\ : * ? " < > |'; - return null; - }; - - const submit = async () => { - const name = input.value.trim(); - const error = validateName(name); - if (error) { - showToast(error, 'error'); - input.focus(); - input.select(); - return; - } - - const newName = `${name}${extension}`; - if (newName === currentName) { - restore(); - return; - } - - input.disabled = true; - try { - const endpoint = type === 'directory' ? `/api/directory/${encodeURIComponent(vault)}` : `/api/file/${encodeURIComponent(vault)}`; - const result = await api(endpoint, { - method: 'PATCH', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ path, new_name: newName }), - }); - - const nextPath = result.new_path; - await refreshSidebarTreePreservingState(); - - if (type === 'file' && state.currentVault === vault && state.currentPath === path) { - await openFile(vault, nextPath); - } else if (type === 'directory' && state.currentVault === vault && state.currentPath && (state.currentPath === path || currentPath.startsWith(`${path}/`))) { - const suffix = state.currentPath === path ? '' : currentPath.slice(path.length); - state.currentPath = `${nextPath}${suffix}`; - await focusPathInSidebar(vault, state.currentPath, { alignToTop: false }); - } - - showToast(type === 'directory' ? t('toast.dir_renamed') : t('toast.file_renamed'), 'success'); - } catch (err) { - input.disabled = false; - showToast(err.message || t('toast.rename_error'), 'error'); - input.focus(); - input.select(); - return; - } - }; - - input.addEventListener('click', (e) => e.stopPropagation()); - input.addEventListener('keydown', async (e) => { - e.stopPropagation(); - if (e.key === 'Enter') { - e.preventDefault(); - await submit(); - } - if (e.key === 'Escape') { - e.preventDefault(); - restore(); - } - }); - input.addEventListener('blur', async () => { - if (!input.disabled) { - await submit(); - } - }); - - input.focus(); - input.setSelectionRange(0, input.value.length); - }, - - confirmDeleteDirectory(vault, path) { - const overlay = this._createModalOverlay(); - const modal = document.createElement('div'); - modal.className = 'obsigate-modal'; - modal.innerHTML = ` -
    -

    ${t('modal.delete_dir')}

    -
    -
    - - -
    - - `; - - overlay.appendChild(modal); - document.body.appendChild(overlay); - - setTimeout(() => overlay.classList.add('active'), 10); - safeCreateIcons(); - - const confirmBtn = modal.querySelector('#del-confirm-btn'); - const cancelBtn = modal.querySelector('#del-cancel-btn'); - - const deleteDir = async () => { - confirmBtn.disabled = true; - confirmBtn.textContent = t('modal.creating'); - - try { - const result = await api(`/api/directory/${encodeURIComponent(vault)}?path=${encodeURIComponent(path)}`, { - method: 'DELETE', - }); - - showToast(t('toast.dir_deleted', {count: result.deleted_count}), 'success'); - this._closeModal(overlay); - await refreshSidebarTreePreservingState(); - - if (state.currentVault === vault && state.currentPath && currentPath.startsWith(path)) { - showWelcome(); - } - } catch (err) { - showToast(err.message || t('toast.delete_error'), 'error'); - confirmBtn.disabled = false; - confirmBtn.textContent = t('modal.delete_permanently'); - } - }; - - confirmBtn.addEventListener('click', deleteDir); - cancelBtn.addEventListener('click', () => this._closeModal(overlay)); - }, - - confirmDeleteFile(vault, path) { - const overlay = this._createModalOverlay(); - const modal = document.createElement('div'); - modal.className = 'obsigate-modal'; - modal.innerHTML = ` -
    -

    ${t('modal.delete_file')}

    -
    -
    - - -
    - - `; - - overlay.appendChild(modal); - document.body.appendChild(overlay); - - setTimeout(() => overlay.classList.add('active'), 10); - safeCreateIcons(); - - const confirmBtn = modal.querySelector('#del-confirm-btn'); - const cancelBtn = modal.querySelector('#del-cancel-btn'); - - const deleteFile = async () => { - confirmBtn.disabled = true; - confirmBtn.textContent = t('modal.creating'); - - try { - await api(`/api/file/${encodeURIComponent(vault)}?path=${encodeURIComponent(path)}`, { - method: 'DELETE', - }); - - showToast(t('toast.file_deleted'), 'success'); - this._closeModal(overlay); - await refreshSidebarTreePreservingState(); - - if (state.currentVault === vault && state.currentPath === path) { - showWelcome(); - } - } catch (err) { - showToast(err.message || t('toast.delete_error'), 'error'); - confirmBtn.disabled = false; - confirmBtn.textContent = t('modal.delete_permanently'); - } - }; - - confirmBtn.addEventListener('click', deleteFile); - cancelBtn.addEventListener('click', () => this._closeModal(overlay)); - }, - - _createModalOverlay() { - const overlay = document.createElement('div'); - overlay.className = 'obsigate-modal-overlay'; - overlay.addEventListener('click', (e) => { - if (e.target === overlay) { - this._closeModal(overlay); - } - }); - return overlay; - }, - - _closeModal(overlay) { - overlay.classList.remove('active'); - setTimeout(() => overlay.remove(), 200); - } -}; - - -// --------------------------------------------------------------------------- -// Find in Page Manager -// --------------------------------------------------------------------------- -export const FindInPageManager = { - isOpen: false, - searchTerm: "", - matches: [], - currentIndex: -1, - options: { - caseSensitive: false, - wholeWord: false, - useRegex: false, - }, - debounceTimer: null, - previousFocus: null, - - init() { - const bar = document.getElementById("find-in-page-bar"); - const input = document.getElementById("find-input"); - const prevBtn = document.getElementById("find-prev"); - const nextBtn = document.getElementById("find-next"); - const closeBtn = document.getElementById("find-close"); - const caseSensitiveBtn = document.getElementById("find-case-sensitive"); - const wholeWordBtn = document.getElementById("find-whole-word"); - const regexBtn = document.getElementById("find-regex"); - - if (!bar || !input) return; - - // Keyboard shortcuts - document.addEventListener("keydown", (e) => { - // Ctrl+F or Cmd+F to open - if ((e.ctrlKey || e.metaKey) && e.key === "f") { - e.preventDefault(); - this.open(); - } - // Escape to close - if (e.key === "Escape" && this.isOpen) { - e.preventDefault(); - this.close(); - } - // Enter to go to next - if (e.key === "Enter" && this.isOpen && document.activeElement === input) { - e.preventDefault(); - if (e.shiftKey) { - this.goToPrevious(); - } else { - this.goToNext(); - } - } - // F3 for next/previous - if (e.key === "F3" && this.isOpen) { - e.preventDefault(); - if (e.shiftKey) { - this.goToPrevious(); - } else { - this.goToNext(); - } - } - }); - - // Input event with debounce - input.addEventListener("input", (e) => { - clearTimeout(this.debounceTimer); - this.debounceTimer = setTimeout(() => { - this.search(e.target.value); - }, 250); - }); - - // Navigation buttons - prevBtn.addEventListener("click", () => this.goToPrevious()); - nextBtn.addEventListener("click", () => this.goToNext()); - - // Close button - closeBtn.addEventListener("click", () => this.close()); - - // Option toggles - caseSensitiveBtn.addEventListener("click", () => { - this.options.caseSensitive = !this.options.caseSensitive; - caseSensitiveBtn.setAttribute("aria-pressed", this.options.caseSensitive); - this.saveState(); - if (this.searchTerm) this.search(this.searchTerm); - }); - - wholeWordBtn.addEventListener("click", () => { - this.options.wholeWord = !this.options.wholeWord; - wholeWordBtn.setAttribute("aria-pressed", this.options.wholeWord); - this.saveState(); - if (this.searchTerm) this.search(this.searchTerm); - }); - - regexBtn.addEventListener("click", () => { - this.options.useRegex = !this.options.useRegex; - regexBtn.setAttribute("aria-pressed", this.options.useRegex); - this.saveState(); - if (this.searchTerm) this.search(this.searchTerm); - }); - - // Load saved state - this.loadState(); - }, - - open() { - const bar = document.getElementById("find-in-page-bar"); - const input = document.getElementById("find-input"); - if (!bar || !input) return; - - this.previousFocus = document.activeElement; - this.isOpen = true; - bar.hidden = false; - input.focus(); - input.select(); - safeCreateIcons(); - }, - - close() { - const bar = document.getElementById("find-in-page-bar"); - if (!bar) return; - - this.isOpen = false; - bar.hidden = true; - this.clearHighlights(); - this.matches = []; - this.currentIndex = -1; - this.searchTerm = ""; - - // Restore previous focus - if (this.previousFocus && this.previousFocus.focus) { - this.previousFocus.focus(); - } - }, - - search(term) { - this.searchTerm = term; - this.clearHighlights(); - this.hideError(); - - if (!term || term.trim().length === 0) { - this.updateCounter(); - this.updateNavButtons(); - return; - } - - const contentArea = document.querySelector(".md-content"); - if (!contentArea) { - this.updateCounter(); - this.updateNavButtons(); - return; - } - - try { - const regex = this.createRegex(term); - this.matches = []; - this.findMatches(contentArea, regex); - this.currentIndex = this.matches.length > 0 ? 0 : -1; - this.highlightMatches(); - this.updateCounter(); - this.updateNavButtons(); - - if (this.matches.length > 0) { - this.scrollToMatch(0); - } - } catch (err) { - this.showError(err.message); - this.matches = []; - this.currentIndex = -1; - this.updateCounter(); - this.updateNavButtons(); - } - }, - - createRegex(term) { - let pattern = term; - - if (!this.options.useRegex) { - // Escape special regex characters - pattern = term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - } - - if (this.options.wholeWord) { - pattern = "\\b" + pattern + "\\b"; - } - - const flags = this.options.caseSensitive ? "g" : "gi"; - return new RegExp(pattern, flags); - }, - - findMatches(container, regex) { - const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT, { - acceptNode: (node) => { - // Skip code blocks, scripts, styles - const parent = node.parentElement; - if (!parent) return NodeFilter.FILTER_REJECT; - const tagName = parent.tagName.toLowerCase(); - if (["code", "pre", "script", "style"].includes(tagName)) { - return NodeFilter.FILTER_REJECT; - } - // Skip empty text nodes - if (!node.textContent || node.textContent.trim().length === 0) { - return NodeFilter.FILTER_REJECT; - } - return NodeFilter.FILTER_ACCEPT; - }, - }); - - let node; - while ((node = walker.nextNode())) { - const text = node.textContent; - let match; - regex.lastIndex = 0; // Reset regex - - while ((match = regex.exec(text)) !== null) { - this.matches.push({ - node: node, - index: match.index, - length: match[0].length, - text: match[0], - }); - - // Prevent infinite loop with zero-width matches - if (match.index === regex.lastIndex) { - regex.lastIndex++; - } - } - } - }, - - highlightMatches() { - const matchesByNode = new Map(); - - this.matches.forEach((match, idx) => { - if (!matchesByNode.has(match.node)) { - matchesByNode.set(match.node, []); - } - matchesByNode.get(match.node).push({ match, idx }); - }); - - matchesByNode.forEach((entries, node) => { - if (!node || !node.parentNode) return; - - const text = node.textContent || ""; - let cursor = 0; - const fragment = document.createDocumentFragment(); - - entries.sort((a, b) => a.match.index - b.match.index); - - entries.forEach(({ match, idx }) => { - if (match.index > cursor) { - fragment.appendChild(document.createTextNode(text.substring(cursor, match.index))); - } - - const matchText = text.substring(match.index, match.index + match.length); - const mark = document.createElement("mark"); - mark.className = idx === this.currentIndex ? "find-highlight find-highlight-active" : "find-highlight"; - mark.textContent = matchText; - mark.setAttribute("data-find-index", idx); - fragment.appendChild(mark); - - match.element = mark; - cursor = match.index + match.length; - }); - - if (cursor < text.length) { - fragment.appendChild(document.createTextNode(text.substring(cursor))); - } - - node.parentNode.replaceChild(fragment, node); - }); - }, - - clearHighlights() { - const contentArea = document.querySelector(".md-content"); - if (!contentArea) return; - - const marks = contentArea.querySelectorAll("mark.find-highlight"); - marks.forEach((mark) => { - if (!mark.parentNode) return; - const text = mark.textContent; - const textNode = document.createTextNode(text); - mark.parentNode.replaceChild(textNode, mark); - }); - - // Normalize text nodes to merge adjacent text nodes - contentArea.normalize(); - }, - - goToNext() { - if (this.matches.length === 0) return; - - // Remove active class from current - if (this.currentIndex >= 0 && this.matches[this.currentIndex].element) { - this.matches[this.currentIndex].element.classList.remove("find-highlight-active"); - } - - // Move to next (with wrapping) - this.currentIndex = (this.currentIndex + 1) % this.matches.length; - - // Add active class to new current - if (this.matches[this.currentIndex].element) { - this.matches[this.currentIndex].element.classList.add("find-highlight-active"); - } - - this.scrollToMatch(this.currentIndex); - this.updateCounter(); - }, - - goToPrevious() { - if (this.matches.length === 0) return; - - // Remove active class from current - if (this.currentIndex >= 0 && this.matches[this.currentIndex].element) { - this.matches[this.currentIndex].element.classList.remove("find-highlight-active"); - } - - // Move to previous (with wrapping) - this.currentIndex = this.currentIndex <= 0 ? this.matches.length - 1 : this.currentIndex - 1; - - // Add active class to new current - if (this.matches[this.currentIndex].element) { - this.matches[this.currentIndex].element.classList.add("find-highlight-active"); - } - - this.scrollToMatch(this.currentIndex); - this.updateCounter(); - }, - - scrollToMatch(index) { - if (index < 0 || index >= this.matches.length) return; - - const match = this.matches[index]; - if (!match.element) return; - - const contentArea = document.getElementById("content-area"); - if (!contentArea) { - match.element.scrollIntoView({ behavior: "smooth", block: "center" }); - return; - } - - // Calculate position with offset for header - const elementTop = match.element.offsetTop; - const offset = 100; // Offset for header - - contentArea.scrollTo({ - top: elementTop - offset, - behavior: "smooth", - }); - }, - - updateCounter() { - const counter = document.getElementById("find-counter"); - if (!counter) return; - - const count = this.matches.length; - if (count === 0) { - counter.textContent = "0 occurrence"; - } else if (count === 1) { - counter.textContent = "1 occurrence"; - } else { - counter.textContent = `${count} occurrences`; - } - }, - - updateNavButtons() { - const prevBtn = document.getElementById("find-prev"); - const nextBtn = document.getElementById("find-next"); - if (!prevBtn || !nextBtn) return; - - const hasMatches = this.matches.length > 0; - prevBtn.disabled = !hasMatches; - nextBtn.disabled = !hasMatches; - }, - - showError(message) { - const errorEl = document.getElementById("find-error"); - if (!errorEl) return; - - errorEl.textContent = message; - errorEl.hidden = false; - }, - - hideError() { - const errorEl = document.getElementById("find-error"); - if (!errorEl) return; - - errorEl.hidden = true; - }, - - saveState() { - try { - const state = { - options: this.options, - }; - localStorage.setItem("obsigate-find-in-page-state", JSON.stringify(state)); - } catch (e) { - // Ignore localStorage errors - } - }, - - loadState() { - try { - const saved = localStorage.getItem("obsigate-find-in-page-state"); - if (saved) { - const state = JSON.parse(saved); - if (state.options) { - this.options = { ...this.options, ...state.options }; - - // Update button states - const caseSensitiveBtn = document.getElementById("find-case-sensitive"); - const wholeWordBtn = document.getElementById("find-whole-word"); - const regexBtn = document.getElementById("find-regex"); - - if (caseSensitiveBtn) caseSensitiveBtn.setAttribute("aria-pressed", this.options.caseSensitive); - if (wholeWordBtn) wholeWordBtn.setAttribute("aria-pressed", this.options.wholeWord); - if (regexBtn) regexBtn.setAttribute("aria-pressed", this.options.useRegex); - } - } - } catch (e) { - // Ignore localStorage errors - } - }, -}; - - -// --------------------------------------------------------------------------- -// Init -// --------------------------------------------------------------------------- -async function init() { - initTheme(); - initHeaderMenu(); - initCustomDropdowns(); - document.getElementById("theme-toggle").addEventListener("click", toggleTheme); - document.getElementById("header-logo").addEventListener("click", goHome); - const refreshBtn = document.getElementById("header-refresh-btn"); - if (refreshBtn) refreshBtn.addEventListener("click", goHome); - initSearch(); - initSidebarToggle(); - initMobile(); - initVaultContext(); - initSidebarTabs(); - initHelpModal(); - initConfigModal(); - initSidebarFilter(); - initSidebarResize(); - initEditor(); - initLoginForm(); - initRecentTab(); - RightSidebarManager.init(); - FindInPageManager.init(); - ContextMenuManager.init(); - - // Check auth status first - const authOk = await AuthManager.initAuth(); - - if (authOk) { - // Start SSE sync AFTER auth is established (cookie available) - initSyncStatus(); - - try { - await Promise.all([loadVaultSettings(), loadVaults(), loadTags()]); - - // Initialize dashboard widgets now that vaults are loaded - if (typeof DashboardRecentWidget !== "undefined") { - DashboardRecentWidget.init(); - } - - // Check for popup mode query parameter - const urlParams = new URLSearchParams(window.location.search); - if (urlParams.get("popup") === "true") { - document.body.classList.add("popup-mode"); - } - - // Handle direct deep-link to file via #file=... - if (window.location.hash && window.location.hash.startsWith("#file=")) { - const hashVal = window.location.hash.substring(6); - const sepIndex = hashVal.indexOf(":"); - if (sepIndex > -1) { - const vault = decodeURIComponent(hashVal.substring(0, sepIndex)); - const path = decodeURIComponent(hashVal.substring(sepIndex + 1)); - openFile(vault, path); - } - } else if (urlParams.get("popup") !== "true") { - // Default to dashboard if no deep link and not in popup mode - showWelcome(); - } - } catch (err) { - console.error("Failed to initialize ObsiGate:", err); - showToast(t("error.initialization"), "error"); - } - } - - safeCreateIcons(); -} - - - -// ---- Keyboard shortcuts for tabs ---- -document.addEventListener("keydown", (e) => { - if (e.ctrlKey || e.metaKey) { - if (e.key === "w" || e.key === "W") { - e.preventDefault(); - if (TabManager._activeTabId) { - TabManager.close(TabManager._activeTabId); - } - } else if (e.key === "Tab" && !e.shiftKey) { - e.preventDefault(); - const tabs = TabManager._tabs; - const currentIdx = tabs.findIndex(t => t.id === TabManager._activeTabId); - if (currentIdx >= 0 && tabs.length > 1) { - const nextIdx = (currentIdx + 1) % tabs.length; - TabManager.activate(tabs[nextIdx].id); - } - } else if (e.key === "Tab" && e.shiftKey) { - e.preventDefault(); - const tabs = TabManager._tabs; - const currentIdx = tabs.findIndex(t => t.id === TabManager._activeTabId); - if (currentIdx >= 0 && tabs.length > 1) { - const prevIdx = (currentIdx - 1 + tabs.length) % tabs.length; - TabManager.activate(tabs[prevIdx].id); - } - } - } -}); - - - - -// ===== MISSING MANAGERS (extracted separately) ===== - -export const ContextMenuManager = { - _menu: null, - _targetElement: null, - _targetVault: null, - _targetPath: null, - _targetType: null, - - init() { - this._menu = document.createElement('div'); - this._menu.className = 'context-menu'; - this._menu.id = 'context-menu'; - document.body.appendChild(this._menu); - - document.addEventListener('click', () => this.hide()); - document.addEventListener('contextmenu', (e) => { - if (!e.target.closest('.tree-item')) { - this.hide(); - } - }); - - document.addEventListener('keydown', (e) => { - if (e.key === 'Escape') this.hide(); - }); - - document.addEventListener('scroll', () => this.hide(), true); - }, - - show(x, y, vault, path, type, isReadonly) { - this._targetVault = vault; - this._targetPath = path; - this._targetType = type; - - this._menu.innerHTML = ''; - - // Copy path — available for all types - const pathToCopy = type === 'vault' ? vault : `${vault}/${path}`; - this._addItem('clipboard-copy', 'Copier le chemin', () => this._copyPath(pathToCopy), false); - - // Graph view — available for all types - const graphPath = type === 'vault' ? '' : path; - this._addItem('git-graph', 'Vue Graphique', () => GraphViewManager.open(vault, graphPath, type), false); - - this._addSeparator(); - - if (type === 'vault') { - this._addItem('folder-plus', 'Nouveau dossier', () => this._createDirectory(), isReadonly); - this._addItem('file-plus', 'Nouveau fichier', () => this._createFile(), isReadonly); - } else if (type === 'directory') { - this._addItem('folder-plus', 'Nouveau sous-dossier', () => this._createDirectory(), isReadonly); - this._addItem('file-plus', 'Nouveau fichier ici', () => this._createFile(), isReadonly); - this._addSeparator(); - this._addItem('bookmark-plus', 'Ajouter aux recherches sauvegardees', () => this._saveDirectorySearch(), false); - this._addSeparator(); - this._addItem('edit', 'Renommer', () => this._renameItem(), isReadonly); - this._addItem('trash-2', 'Supprimer', () => this._deleteDirectory(), isReadonly); - } else if (type === 'file') { - this._addItem('edit', 'Renommer', () => this._renameItem(), isReadonly); - this._addItem('trash-2', 'Supprimer', () => this._deleteFile(), isReadonly); - this._addSeparator(); - this._addItem('bookmark-plus', t("viewer.bookmark_add"), () => this._toggleBookmark(), false); - this._addSeparator(); - this._addItem('history', t("ui.backups_versions"), () => this._openBackupViewer(), false); - } - - this._menu.classList.add('active'); - - const rect = this._menu.getBoundingClientRect(); - const viewportWidth = window.innerWidth; - const viewportHeight = window.innerHeight; - - let finalX = x; - let finalY = y; - - if (x + rect.width > viewportWidth) { - finalX = viewportWidth - rect.width - 10; - } - - if (y + rect.height > viewportHeight) { - finalY = viewportHeight - rect.height - 10; - } - - this._menu.style.left = `${finalX}px`; - this._menu.style.top = `${finalY}px`; - - safeCreateIcons(); - }, - - hide() { - if (this._menu) { - this._menu.classList.remove('active'); - } - }, - - _addItem(icon, label, callback, disabled) { - const item = document.createElement('div'); - item.className = 'context-menu-item' + (disabled ? ' disabled' : ''); - item.innerHTML = ` - - ${label} - `; - - if (!disabled) { - item.addEventListener('click', (e) => { - e.stopPropagation(); - this.hide(); - callback(); - }); - } else { - item.title = t("ui.vault_readonly"); - } - - this._menu.appendChild(item); - }, - - _addSeparator() { - const sep = document.createElement('div'); - sep.className = 'context-menu-separator'; - this._menu.appendChild(sep); - }, - - _createDirectory() { - FileOperations.showCreateDirectoryModal(this._targetVault, this._targetPath); - }, - - _createFile() { - FileOperations.showCreateFileModal(this._targetVault, this._targetPath); - }, - - _renameItem() { - FileOperations.startInlineRename(this._targetVault, this._targetPath, this._targetType); - }, - - _deleteDirectory() { - FileOperations.confirmDeleteDirectory(this._targetVault, this._targetPath); - }, - - _deleteFile() { - FileOperations.confirmDeleteFile(this._targetVault, this._targetPath); - }, - - _copyPath(path) { - // Try modern clipboard API first, fall back to execCommand for non-secure contexts - if (navigator.clipboard && navigator.clipboard.writeText) { - navigator.clipboard.writeText(path).then(() => { - showToast(t('toast.path_copied', {path: path}), 'success'); - }).catch(() => { - this._copyPathFallback(path); - }); - } else { - this._copyPathFallback(path); - } - }, - - _copyPathFallback(path) { - const textarea = document.createElement('textarea'); - textarea.value = path; - textarea.style.position = 'fixed'; - textarea.style.left = '-9999px'; - textarea.style.top = '-9999px'; - document.body.appendChild(textarea); - textarea.focus(); - textarea.select(); - try { - const success = document.execCommand('copy'); - if (success) { - showToast(t('toast.path_copied', {path: path}), 'success'); - } else { - showToast(t('toast.copy_error'), 'error'); - } - } catch (e) { - showToast(t('toast.copy_error'), 'error'); - } - document.body.removeChild(textarea); - }, - - async _toggleBookmark() { - try { - const data = await api("/api/bookmarks/toggle", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ vault: this._targetVault, path: this._targetPath, title: this._targetPath.split("/").pop() }), - }); - showToast(data.bookmarked ? t("toast.bookmark_added") : t("toast.bookmark_removed"), "success"); - if (typeof DashboardBookmarkWidget !== "undefined" && DashboardBookmarkWidget.load) { - DashboardBookmarkWidget.load(); - } - } catch (err) { showToast("Erreur: " + err.message, "error"); } - }, - - async _saveDirectorySearch() { - try { - var vault = this._targetVault || "all"; - var dirPath = this._targetPath; - var dirName = dirPath.split("/").pop() || dirPath; - await api("/api/saved-searches", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - query: "", - vault: vault, - case_sensitive: false, - whole_word: false, - regex: false, - include_paths: dirPath + "/**", - exclude_paths: "", - }), - }); - showToast(t("toast.dir_saved_search"), "success"); - // Switch to saved searches tab - var savedTab = document.getElementById("sidebar-tab-saved"); - if (savedTab) savedTab.click(); - // Reload saved searches - import('./viewer.js').then(function(m) { m.loadSavedSearches(); }); - } catch (err) { showToast("Erreur: " + err.message, "error"); } - }, - - _openBackupViewer() { - // Dynamically import the backup viewer module to avoid circular deps - import('./backups.js').then(mod => { - mod.openBackupViewer(this._targetVault, this._targetPath); - }).catch(err => { - showToast(t("toast.viewer_error") + ": " + err.message, "error"); - }); - this.hide(); - } -}; -export const TabManager = { - _tabs: [], - _activeTabId: null, - _previewTabId: null, // single-click preview tab (temporary, replaced on next preview) - _tabCache: {}, // { tabId: { vault, path, title, data, rawSource, sourceView, scrollTop, icon } } - _tabBar: null, - _tabList: null, - _dirtyTabs: new Set(), - - init() { - this._tabBar = document.getElementById("tab-bar"); - this._tabList = document.getElementById("tab-list"); - }, - - /** Open a file as a preview tab (single-click). - * Replaces any existing preview tab. If the file is already - * open as a persistent tab, just activates it. */ - async openPreview(vault, path) { - const tabId = `${vault}::${path}`; - - // If already open as persistent tab, just activate it - const existing = this._tabs.find(t => t.id === tabId && !t.preview); - if (existing) { - this.activate(tabId); - return; - } - - // Close existing preview tab - if (this._previewTabId && this._previewTabId !== tabId) { - this.close(this._previewTabId); - } - - // If already open as preview, just focus it - const previewExisting = this._tabs.find(t => t.id === tabId && t.preview); - if (previewExisting) { - this.activate(tabId); - return; - } - - // Create preview tab - const name = path.split("/").pop().replace(/\.md$/i, ""); - const icon = getFileIcon(name + ".md"); - - this._tabs.push({ id: tabId, vault, path, name, icon, preview: true }); - this._tabCache[tabId] = { vault, path, title: name, data: null, rawSource: null, sourceView: false, scrollTop: 0, icon }; - this._previewTabId = tabId; - - this._renderTabs(); - this.activate(tabId); - }, - - /** Convert a preview tab to a persistent tab (double-click). - * If already persistent, opens a new duplicate (same file, different tab). */ - async openPersistent(vault, path) { - const tabId = `${vault}::${path}`; - - // If it's already a preview tab, convert it to persistent - const previewTab = this._tabs.find(t => t.id === tabId && t.preview); - if (previewTab) { - previewTab.preview = false; - if (this._previewTabId === tabId) { - this._previewTabId = null; - } - this._renderTabs(); - this.activate(tabId); - return; - } - - // If already persistent, just focus it - const existing = this._tabs.find(t => t.id === tabId && !t.preview); - if (existing) { - this.activate(tabId); - return; - } - - // Create a new persistent tab - this.open(vault, path); - }, - - /** Open a file in a tab (or focus existing) */ - async open(vault, path, options = {}) { - const tabId = `${vault}::${path}`; - - // If already open, just focus it - const existing = this._tabs.find(t => t.id === tabId); - if (existing) { - // Convert preview to persistent if needed - if (existing.preview) { - existing.preview = false; - if (this._previewTabId === tabId) this._previewTabId = null; - this._renderTabs(); - } - this.activate(tabId); - return; - } - - // Create new tab - const name = path.split("/").pop().replace(/\.md$/i, ""); - const icon = getFileIcon(name + ".md"); - - this._tabs.push({ id: tabId, vault, path, name, icon }); - this._tabCache[tabId] = { vault, path, title: name, data: null, rawSource: null, sourceView: false, scrollTop: 0, icon }; - - this._renderTabs(); - this.activate(tabId); - }, - - /** Activate a specific tab */ - async activate(tabId) { - if (this._activeTabId === tabId && this._tabs.length > 0) return; - - // Save current tab state - if (this._activeTabId && this._tabCache[this._activeTabId]) { - this._saveCurrentTabState(); - } - - this._activeTabId = tabId; - this._renderTabs(); - - // Load tab content - const cache = this._tabCache[tabId]; - if (!cache) return; - - // Update global state - state.currentVault = cache.vault; - state.currentPath = cache.path; - syncActiveFileTreeItem(cache.vault, cache.path); - - const area = document.getElementById("content-area"); - - if (cache.data) { - // Use cached data - this._restoreTabContent(cache, area); - } else { - // Fetch file content - area.innerHTML = '
    Chargement...
    '; - try { - const data = await api(`/api/file/${encodeURIComponent(cache.vault)}?path=${encodeURIComponent(cache.path)}`); - cache.data = data; - cache.title = data.title; - renderFile(cache.data); - - // Restore source view if needed - if (cache.sourceView) { - await this._toggleSourceView(cache, area); - } - if (cache.scrollTop) { - area.scrollTop = cache.scrollTop; - } - } catch (err) { - area.innerHTML = `
    Erreur: ${escapeHtml(err.message)}
    `; - } - } - - // Update URL hash - if (history.pushState) { - history.pushState(null, "", `#/file/${encodeURIComponent(cache.vault)}/${encodeURIComponent(cache.path)}`); - } - - // Hide dashboard - const dashboard = document.getElementById("dashboard-home"); - if (dashboard) dashboard.style.display = "none"; - }, - - /** Close a tab */ - close(tabId) { - const idx = this._tabs.findIndex(t => t.id === tabId); - if (idx === -1) return; - - this._tabs.splice(idx, 1); - delete this._tabCache[tabId]; - this._dirtyTabs.delete(tabId); - - if (this._tabs.length === 0) { - this._activeTabId = null; - this._showDashboard(); - if (this._tabBar) this._tabBar.hidden = true; - } else if (this._activeTabId === tabId) { - // Activate adjacent tab - const newIdx = Math.min(idx, this._tabs.length - 1); - this.activate(this._tabs[newIdx].id); - } - - this._renderTabs(); - }, - - /** Close all tabs */ - closeAll() { - this._tabs = []; - this._tabCache = {}; - this._dirtyTabs.clear(); - this._activeTabId = null; - this._showDashboard(); - if (this._tabBar) this._tabBar.hidden = true; - }, - - /** Close tabs to the right */ - closeRight(tabId) { - const idx = this._tabs.findIndex(t => t.id === tabId); - if (idx === -1) return; - const toClose = this._tabs.slice(idx + 1); - for (const tab of toClose) { - delete this._tabCache[tab.id]; - this._dirtyTabs.delete(tab.id); - } - this._tabs = this._tabs.slice(0, idx + 1); - if (!this._tabs.find(t => t.id === this._activeTabId)) { - this.activate(tabId); - } - this._renderTabs(); - }, - - /** Close other tabs */ - closeOthers(tabId) { - const tab = this._tabs.find(t => t.id === tabId); - if (!tab) return; - for (const t of this._tabs) { - if (t.id !== tabId) { - delete this._tabCache[t.id]; - this._dirtyTabs.delete(t.id); - } - } - this._tabs = [tab]; - this.activate(tabId); - this._renderTabs(); - }, - - /** Reorder tabs by drag and drop */ - moveTab(fromIdx, toIdx) { - if (fromIdx === toIdx || fromIdx < 0 || toIdx < 0) return; - const tab = this._tabs.splice(fromIdx, 1)[0]; - this._tabs.splice(toIdx, 0, tab); - this._renderTabs(); - }, - - /** Save current tab state before switching */ - _saveCurrentTabState() { - const cache = this._tabCache[this._activeTabId]; - if (!cache) return; - - const area = document.getElementById("content-area"); - const rendered = document.getElementById("file-rendered-content"); - - cache.scrollTop = area.scrollTop; - cache.sourceView = rendered ? rendered.style.display === "none" : false; - }, - - /** Restore tab content from cache */ - _restoreTabContent(cache, area) { - renderFile(cache.data); - if (cache.sourceView) { - this._restoreSourceView(cache, area); - } - if (cache.scrollTop) { - area.scrollTop = cache.scrollTop; - } - }, - - async _toggleSourceView(cache, area) { - const rendered = document.getElementById("file-rendered-content"); - const raw = document.getElementById("file-raw-content"); - if (!rendered || !raw) return; - - if (!cache.rawSource) { - const rawData = await api(`/api/file/${encodeURIComponent(cache.vault)}/raw?path=${encodeURIComponent(cache.path)}`); - cache.rawSource = rawData.raw; - } - raw.textContent = cache.rawSource; - rendered.style.display = "none"; - raw.style.display = "block"; - }, - - _restoreSourceView(cache, area) { - requestAnimationFrame(() => { - const rendered = document.getElementById("file-rendered-content"); - const raw = document.getElementById("file-raw-content"); - if (rendered && raw && cache.rawSource) { - raw.textContent = cache.rawSource; - rendered.style.display = "none"; - raw.style.display = "block"; - } - }); - }, - - _showDashboard() { - const area = document.getElementById("content-area"); - // Save dashboard DOM before clearing (it may have been removed from DOM by renderFile) - let dashboard = document.getElementById("dashboard-home"); - if (!dashboard) { - // Dashboard was destroyed — rebuild via showWelcome - area.innerHTML = ""; - showWelcome(); - return; - } - area.innerHTML = ""; - dashboard.style.display = ""; - area.appendChild(dashboard); - // Refresh widgets after restoring - if (typeof DashboardStatsWidget !== "undefined") DashboardStatsWidget.load(); - if (typeof DashboardConflictsWidget !== "undefined") DashboardConflictsWidget.load(); - if (typeof DashboardRecentWidget !== "undefined") DashboardRecentWidget.load(state.selectedContextVault); - if (typeof DashboardBookmarkWidget !== "undefined") DashboardBookmarkWidget.load(state.selectedContextVault); - if (history.pushState) { - history.pushState(null, "", "#"); - } - }, - - /** Render the tab bar */ - _renderTabs() { - if (!this._tabList) return; - - this._tabList.innerHTML = ""; - - if (this._tabs.length === 0) { - this._tabBar.hidden = true; - return; - } - - this._tabBar.hidden = false; - - this._tabs.forEach((tab, idx) => { - const el = document.createElement("div"); - el.className = "tab-item" + (tab.id === this._activeTabId ? " active" : "") + (tab.preview ? " preview" : ""); - el.draggable = true; - el.dataset.tabId = tab.id; - el.dataset.index = idx; - - // Icon - const iconEl = document.createElement("i"); - iconEl.setAttribute("data-lucide", tab.icon); - iconEl.className = "tab-icon"; - iconEl.style.width = "14px"; - iconEl.style.height = "14px"; - el.appendChild(iconEl); - - // Name - const nameEl = document.createElement("span"); - nameEl.className = "tab-name"; - nameEl.textContent = tab.name; - nameEl.title = `${tab.vault}/${tab.path}`; - el.appendChild(nameEl); - - // Close button - const closeEl = document.createElement("span"); - closeEl.className = "tab-close"; - closeEl.innerHTML = ''; - closeEl.addEventListener("click", (e) => { - e.stopPropagation(); - this.close(tab.id); - }); - el.appendChild(closeEl); - - // Click to activate - el.addEventListener("click", () => this.activate(tab.id)); - - // Double-click to close - el.addEventListener("dblclick", (e) => { - e.preventDefault(); - this.close(tab.id); - }); - - // Middle-click to close - el.addEventListener("mousedown", (e) => { - if (e.button === 1) { - e.preventDefault(); - this.close(tab.id); - } - }); - - // Context menu on tab - el.addEventListener("contextmenu", (e) => { - e.preventDefault(); - this._showTabContextMenu(e.clientX, e.clientY, tab.id); - }); - - // Drag and drop - el.addEventListener("dragstart", (e) => { - e.dataTransfer.setData("text/plain", String(idx)); - el.classList.add("dragging"); - }); - el.addEventListener("dragend", () => { - el.classList.remove("dragging"); - document.querySelectorAll(".tab-drop-indicator").forEach(d => d.remove()); - }); - el.addEventListener("dragover", (e) => { - e.preventDefault(); - e.dataTransfer.dropEffect = "move"; - const rect = el.getBoundingClientRect(); - const mid = rect.left + rect.width / 2; - document.querySelectorAll(".tab-drop-indicator").forEach(d => d.remove()); - const indicator = document.createElement("div"); - indicator.className = "tab-drop-indicator"; - if (e.clientX < mid) { - el.before(indicator); - } else { - el.after(indicator); - } - }); - el.addEventListener("drop", (e) => { - e.preventDefault(); - document.querySelectorAll(".tab-drop-indicator").forEach(d => d.remove()); - const fromIdx = parseInt(e.dataTransfer.getData("text/plain")); - const rect = el.getBoundingClientRect(); - const mid = rect.left + rect.width / 2; - const toIdx = e.clientX < mid ? idx : idx + 1; - if (fromIdx !== toIdx && fromIdx !== toIdx - 1) { - this.moveTab(fromIdx, toIdx); - } - }); - - this._tabList.appendChild(el); - }); - - safeCreateIcons(); - }, - - _showTabContextMenu(x, y, tabId) { - const existing = document.getElementById("tab-context-menu"); - if (existing) existing.remove(); - - const menu = document.createElement("div"); - menu.id = "tab-context-menu"; - menu.className = "context-menu active"; - menu.style.left = x + "px"; - menu.style.top = y + "px"; - menu.innerHTML = ` -
    Fermer
    -
    Fermer les autres
    -
    Fermer à droite
    -
    -
    Fermer tout
    - `; - document.body.appendChild(menu); - safeCreateIcons(); - - menu.addEventListener("click", (e) => { - const action = e.target.closest(".context-menu-item")?.dataset.action; - if (action === "close") this.close(tabId); - else if (action === "closeOthers") this.closeOthers(tabId); - else if (action === "closeRight") this.closeRight(tabId); - else if (action === "closeAll") this.closeAll(); - menu.remove(); - }); - - const closeMenu = () => menu.remove(); - document.addEventListener("click", closeMenu, { once: true }); - document.addEventListener("keydown", (e) => { if (e.key === "Escape") { menu.remove(); } }, { once: true }); - }, -}; - - - -// ---- Keyboard shortcuts for tabs ---- -document.addEventListener("keydown", (e) => { - if (e.ctrlKey || e.metaKey) { - if (e.key === "w" || e.key === "W") { - e.preventDefault(); - if (TabManager._activeTabId) { - TabManager.close(TabManager._activeTabId); - } - } else if (e.key === "Tab" && !e.shiftKey) { - e.preventDefault(); - const tabs = TabManager._tabs; - const currentIdx = tabs.findIndex(t => t.id === TabManager._activeTabId); - if (currentIdx >= 0 && tabs.length > 1) { - const nextIdx = (currentIdx + 1) % tabs.length; - TabManager.activate(tabs[nextIdx].id); - } - } else if (e.key === "Tab" && e.shiftKey) { - e.preventDefault(); - const tabs = TabManager._tabs; - const currentIdx = tabs.findIndex(t => t.id === TabManager._activeTabId); - if (currentIdx >= 0 && tabs.length > 1) { - const prevIdx = (currentIdx - 1 + tabs.length) % tabs.length; - TabManager.activate(tabs[prevIdx].id); - } - } - } -}); - -// ---- Modify init to include TabManager ---- diff --git a/desktop/frontend-static/js/utils.js b/desktop/frontend-static/js/utils.js deleted file mode 100644 index b5ab338..0000000 --- a/desktop/frontend-static/js/utils.js +++ /dev/null @@ -1,679 +0,0 @@ -import { state } from './state.js'; -import { api } from './auth.js'; -import { openFile, showWelcome } from './viewer.js'; -import { refreshSidebarForContext, refreshTagsForContext } from './sidebar.js'; -import { createAIToolbar } from './ai.js'; - -// --------------------------------------------------------------------------- -// File extension → Lucide icon mapping -// --------------------------------------------------------------------------- -const EXT_ICONS = { - // Text files - ".md": "file-text", - ".txt": "file-text", - ".log": "file-text", - ".readme": "file-text", - ".rst": "file-text", - ".adoc": "file-text", - - // Web development - ".html": "file-code", - ".htm": "file-code", - ".css": "file-code", - ".scss": "file-code", - ".sass": "file-code", - ".less": "file-code", - ".js": "file-code", - ".jsx": "file-code", - ".ts": "file-code", - ".tsx": "file-code", - ".vue": "file-code", - ".svelte": "file-code", - - // Programming languages - ".py": "file-code", - ".java": "file-code", - ".c": "file-code", - ".cpp": "file-code", - ".cc": "file-code", - ".cxx": "file-code", - ".h": "file-code", - ".hpp": "file-code", - ".cs": "file-code", - ".go": "file-code", - ".rs": "file-code", - ".rb": "file-code", - ".php": "file-code", - ".swift": "file-code", - ".kt": "file-code", - ".scala": "file-code", - ".r": "file-code", - ".m": "file-code", - ".pl": "file-code", - ".lua": "file-code", - ".dart": "file-code", - ".nim": "file-code", - ".zig": "file-code", - ".odin": "file-code", - ".v": "file-code", - ".cr": "file-code", - ".ex": "file-code", - ".exs": "file-code", - ".elm": "file-code", - ".purs": "file-code", - ".hs": "file-code", - ".ml": "file-code", - ".ocaml": "file-code", - ".fs": "file-code", - ".fsx": "file-code", - ".vb": "file-code", - ".pas": "file-code", - ".pp": "file-code", - ".inc": "file-code", - - // Data formats - ".json": "file-json", - ".yaml": "file-cog", - ".yml": "file-cog", - ".toml": "file-cog", - ".xml": "file-code", - ".csv": "table", - ".tsv": "table", - ".sql": "database", - ".db": "database", - ".sqlite": "database", - ".sqlite3": "database", - ".parquet": "database", - ".avro": "database", - - // Configuration files - ".ini": "file-cog", - ".cfg": "file-cog", - ".conf": "file-cog", - ".env": "file-cog", - ".dockerfile": "file-cog", - ".gitignore": "file-cog", - ".gitattributes": "file-cog", - ".editorconfig": "file-cog", - ".eslintrc": "file-cog", - ".prettierrc": "file-cog", - ".babelrc": "file-cog", - ".tsconfig": "file-cog", - "package.json": "file-cog", - "package-lock.json": "file-cog", - "yarn.lock": "file-cog", - "composer.json": "file-cog", - "requirements.txt": "file-cog", - "pipfile": "file-cog", - "gemfile": "file-cog", - "cargo.toml": "file-cog", - "go.mod": "file-cog", - "go.sum": "file-cog", - "pom.xml": "file-cog", - "build.gradle": "file-cog", - "cmakelists.txt": "file-cog", - "makefile": "file-cog", - - // Shell scripts - ".sh": "terminal", - ".bash": "terminal", - ".zsh": "terminal", - ".fish": "terminal", - ".bat": "terminal", - ".cmd": "terminal", - ".ps1": "terminal", - ".psm1": "terminal", - ".psd1": "terminal", - - // Document formats - ".pdf": "file-text", - ".doc": "file-text", - ".docx": "file-text", - ".rtf": "file-text", - ".odt": "file-text", - ".tex": "file-text", - ".latex": "file-text", - - // Image files - ".png": "file-image", - ".jpg": "file-image", - ".jpeg": "file-image", - ".gif": "file-image", - ".svg": "file-image", - ".webp": "file-image", - ".bmp": "file-image", - ".ico": "file-image", - ".tiff": "file-image", - ".tif": "file-image", - - // Audio files - ".mp3": "file-music", - ".wav": "file-music", - ".flac": "file-music", - ".aac": "file-music", - ".ogg": "file-music", - ".m4a": "file-music", - ".wma": "file-music", - - // Video files - ".mp4": "play", - ".avi": "play", - ".mov": "play", - ".wmv": "play", - ".flv": "play", - ".webm": "play", - ".mkv": "play", - ".m4v": "play", - ".3gp": "play", - - // Archive files - ".zip": "file-archive", - ".rar": "file-archive", - ".7z": "file-archive", - ".tar": "file-archive", - ".gz": "file-archive", - ".tgz": "file-archive", - ".bz2": "file-archive", - ".xz": "file-archive", - ".deb": "file-archive", - ".rpm": "file-archive", - ".dmg": "file-archive", - ".pkg": "file-archive", - ".msi": "file-archive", - ".exe": "file-archive", - - // Font files - ".ttf": "file-type", - ".otf": "file-type", - ".woff": "file-type", - ".woff2": "file-type", - ".eot": "file-type", - - // Other common files - ".key": "file-cog", - ".pem": "file-cog", - ".crt": "file-cog", - ".cert": "file-cog", - ".p12": "file-cog", - ".pfx": "file-cog", - ".lock": "file-cog", - ".tmp": "file", - ".bak": "file", - ".old": "file", - ".orig": "file", - ".save": "file", -}; - -function getFileIcon(name) { - const ext = "." + name.split(".").pop().toLowerCase(); - return EXT_ICONS[ext] || "file"; -} - -// --------------------------------------------------------------------------- -// Safe CDN helpers -// --------------------------------------------------------------------------- - -let _iconDebounceTimer = null; - -/** - * Debounced icon creation — batches multiple rapid calls into one - * DOM scan to avoid excessive reflows when building large trees. - */ -function safeCreateIcons() { - if (typeof lucide === "undefined" || !lucide.createIcons) return; - if (state._iconDebounceTimer) return; // already scheduled - state._iconDebounceTimer = requestAnimationFrame(() => { - state._iconDebounceTimer = null; - try { - lucide.createIcons(); - } catch (e) { - /* CDN not loaded */ - } - }); -} - -/** Force-flush icon creation immediately (use sparingly). */ -function flushIcons() { - if (state._iconDebounceTimer) { - cancelAnimationFrame(state._iconDebounceTimer); - state._iconDebounceTimer = null; - } - if (typeof lucide !== "undefined" && lucide.createIcons) { - try { - lucide.createIcons(); - } catch (e) { - /* CDN not loaded */ - } - } -} - -function safeHighlight(block) { - // Skip mermaid blocks — they're rendered by Mermaid.js, not highlighted - if (block.className && block.className.indexOf('language-mermaid') !== -1) return; - if (typeof hljs !== "undefined" && hljs.highlightElement) { - try { - hljs.highlightElement(block); - } catch (e) { - /* CDN not loaded */ - } - } -} - -// --------------------------------------------------------------------------- -// Helpers -// --------------------------------------------------------------------------- -function escapeHtml(str) { - if (!str) return ""; - return String(str).replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); -} - -// --------------------------------------------------------------------------- -// Editor (CodeMirror) -// --------------------------------------------------------------------------- -async function openEditor(vaultName, filePath) { - state.editorVault = vaultName; - state.editorPath = filePath; - - const modal = document.getElementById("editor-modal"); - const titleInput = document.getElementById("editor-title-input"); - const filenameInput = document.getElementById("editor-filename-input"); - const statFile = document.getElementById("editor-stat-file"); - const statWords = document.getElementById("editor-stat-words"); - const bodyEl = document.getElementById("editor-body"); - - // Restore header/footer (may be hidden by Forge) - var headerEl = modal.querySelector(".editor-header"); - var footerEl = modal.querySelector(".editor-footer"); - var container = modal.querySelector(".editor-container"); - if (headerEl) headerEl.style.display = ""; - if (footerEl) footerEl.style.display = ""; - if (container) container.style.maxHeight = ""; - - filenameInput.value = filePath.split("/").pop(); - statFile.textContent = vaultName + "/" + filePath; - - // Fetch raw content - const rawUrl = `/api/file/${encodeURIComponent(vaultName)}/raw?path=${encodeURIComponent(filePath)}`; - const rawData = await api(rawUrl); - - // Clear previous editor - bodyEl.innerHTML = ""; - if (state.editorView) { - state.editorView.destroy(); - state.editorView = null; - } - state.fallbackEditorEl = null; - - // Re-create AI toolbar container (was cleared by innerHTML above) - const aiContainer = document.createElement('div'); - aiContainer.id = 'ai-toolbar-container'; - bodyEl.appendChild(aiContainer); - - try { - await waitForCodeMirror(); - - const { EditorView, EditorState, basicSetup, markdown, python, javascript, html, css, json, xml, sql, php, cpp, java, rust, oneDark, keymap } = window.CodeMirror; - - const currentTheme = document.documentElement.getAttribute("data-theme"); - const fileExt = filePath.split(".").pop().toLowerCase(); - - const extensions = [ - basicSetup, - keymap.of([ - { - key: "Mod-s", - run: () => { - saveFile(); - return true; - }, - }, - ]), - EditorView.lineWrapping, - // Auto-save: debounced save after 2s of inactivity - EditorView.updateListener.of((update) => { - if (update.docChanged) { - clearTimeout(window._obsigateAutoSaveTimer); - window._obsigateAutoSaveTimer = setTimeout(() => saveFile(true), 2000); - // Mark dirty - var sd = document.getElementById("editor-save-dot"); - var sl = document.getElementById("editor-save-label"); - if (sd) sd.className = "editor-save-dot dirty"; - if (sl) sl.textContent = "Unsaved"; - } - }), - ]; - - // Add language support based on file extension - const langMap = { - md: markdown, - markdown: markdown, - py: python, - js: javascript, - jsx: javascript, - ts: javascript, - tsx: javascript, - mjs: javascript, - cjs: javascript, - html: html, - htm: html, - css: css, - scss: css, - less: css, - json: json, - xml: xml, - svg: xml, - sql: sql, - php: php, - cpp: cpp, - cc: cpp, - cxx: cpp, - c: cpp, - h: cpp, - hpp: cpp, - java: java, - rs: rust, - sh: javascript, // Using javascript for shell scripts as fallback - bash: javascript, - zsh: javascript, - }; - - const langMode = langMap[fileExt]; - if (langMode) { - extensions.push(langMode()); - } - - if (currentTheme === "dark") { - extensions.push(oneDark); - } - - const cmState = EditorState.create({ - doc: rawData.raw, - extensions: extensions, - }); - - state.editorView = new EditorView({ - state: cmState, - parent: bodyEl, - }); - } catch (err) { - console.error("CodeMirror init failed, falling back to textarea:", err); - state.fallbackEditorEl = document.createElement("textarea"); - state.fallbackEditorEl.className = "fallback-editor"; - state.fallbackEditorEl.value = rawData.raw; - bodyEl.appendChild(state.fallbackEditorEl); - } - - // Set up AI toolbar (recreate each time editor opens) - var container = document.getElementById('ai-toolbar-container'); - if (container && !container.querySelector('.ai-toolbar') && !container.querySelector('div')) { - createAIToolbar(container, function() { return state.editorView || null; }); - } - - // Mermaid live preview panel (#26) - var existingPreview = document.getElementById('mermaid-live-preview'); - if (existingPreview) existingPreview.remove(); - var previewPanel = document.createElement('div'); - previewPanel.id = 'mermaid-live-preview'; - previewPanel.className = 'mermaid-live-preview'; - previewPanel.style.display = 'none'; - bodyEl.appendChild(previewPanel); - - // Debounced live preview on content change - var mermaidTimer = null; - var updateMermaidPreview = function() { - clearTimeout(mermaidTimer); - mermaidTimer = setTimeout(function() { - var content = state.editorView ? state.editorView.state.doc.toString() : (state.fallbackEditorEl ? state.fallbackEditorEl.value : ''); - var match = content.match(/```mermaid\n([\s\S]*?)```/); - if (match) { - previewPanel.style.display = 'block'; - previewPanel.innerHTML = ''; - var code = match[1]; - import('./mermaid-viewer.js').then(function(m) { - // Create a temp container and render - var tmp = document.createElement('div'); - tmp.innerHTML = '
    ' + code.replace(/&/g,'&').replace(//g,'>') + '
    '; - previewPanel.appendChild(tmp); - m.renderMermaidBlocks(previewPanel); - }); - } else { - previewPanel.style.display = 'none'; - } - }, 500); - }; - - if (state.editorView) { - // Attach to CodeMirror - var extUpdate = state.editorView.state.updateListener; - // Use the existing update listener approach - just add debounce on any change - } - - modal.classList.add("active"); - safeCreateIcons(); - - // Initial preview if content has mermaid - updateMermaidPreview(); -} - -async function waitForCodeMirror() { - let attempts = 0; - while (!window.CodeMirror && attempts < 50) { - await new Promise((resolve) => setTimeout(resolve, 100)); - attempts++; - } - if (!window.CodeMirror) { - throw new Error("CodeMirror failed to load"); - } -} - -function closeEditor() { - const vault = state.editorVault; - const path = state.editorPath; - const modal = document.getElementById("editor-modal"); - modal.classList.remove("active"); - // Restore brand text - var brand = modal.querySelector('.editor-brand'); - if (brand) brand.textContent = 'ObsiGate'; - if (state.editorView) { - state.editorView.destroy(); - state.editorView = null; - } - state.fallbackEditorEl = null; - // Remove forge iframe if present + refresh current file - var forgeFrame = document.getElementById("forge-iframe"); - if (forgeFrame) { - forgeFrame.remove(); - if (state.currentVault && state.currentPath) openFile(state.currentVault, state.currentPath); - } - state.editorVault = null; - state.editorPath = null; - // Refresh file content if we're viewing the edited file - if (vault && path && state.currentVault === vault && state.currentPath === path) { - openFile(vault, path); - } -} - -async function saveFile(silent = false) { - // If Forge is open, delegate save to the iframe - var forgeFrame = document.getElementById("forge-iframe"); - if (forgeFrame && forgeFrame.contentWindow) { - if (!state.editorVault || !state.editorPath) return; - var fSaveBtn = document.getElementById("editor-save"); - var fSaveDot = document.getElementById("editor-save-dot"); - var fSaveLabel = document.getElementById("editor-save-label"); - if (fSaveDot) { fSaveDot.className = 'editor-save-dot saving'; } - if (fSaveLabel) fSaveLabel.textContent = 'Saving...'; - if (fSaveBtn) { fSaveBtn.disabled = true; } - forgeFrame.contentWindow.postMessage({ type: 'parent-save' }, '*'); - return; - } - - if ((!state.editorView && !state.fallbackEditorEl) || !state.editorVault || !state.editorPath) return; - - const content = state.editorView ? state.editorView.state.doc.toString() : state.fallbackEditorEl.value; - const saveBtn = document.getElementById("editor-save"); - const saveDot = document.getElementById("editor-save-dot"); - const saveLabel = document.getElementById("editor-save-label"); - - try { - // Update save dot to saving state - if (saveDot) { saveDot.className = 'editor-save-dot saving'; } - if (saveLabel) saveLabel.textContent = 'Saving...'; - if (saveBtn && !silent) { - saveBtn.disabled = true; - saveBtn.innerHTML = ''; - safeCreateIcons(); - } - - const backupParam = silent ? '&backup=false' : ''; - const response = await fetch(`/api/file/${encodeURIComponent(state.editorVault)}/save?path=${encodeURIComponent(state.editorPath)}${backupParam}`, { - method: "PUT", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ content }), - }); - - if (!response.ok) { - const error = await response.json(); - throw new Error(error.detail || "Erreur de sauvegarde"); - } - - // Update save dot to saved state - if (saveDot) { saveDot.className = 'editor-save-dot ok'; } - if (saveLabel) saveLabel.textContent = 'Saved'; - - if (silent) { - // Auto-save: brief green flash on save button - if (saveBtn) { - saveBtn.style.background = '#22c55e'; - saveBtn.style.color = '#fff'; - saveBtn.style.borderColor = '#22c55e'; - } - setTimeout(() => { - if (saveBtn) { - saveBtn.style.background = ''; - saveBtn.style.color = ''; - saveBtn.style.borderColor = ''; - } - }, 1500); - } else { - closeEditor(); - } - } catch (err) { - console.error("Save error:", err); - if (saveDot) { saveDot.className = 'editor-save-dot err'; } - if (saveLabel) saveLabel.textContent = 'Erreur'; - // If offline, queue the save for later sync - if (!navigator.onLine) { - try { - const { queueOfflineSave } = await import('./offline.js'); - await queueOfflineSave(state.editorVault, state.editorPath, content); - alert('Vous etes hors-ligne. La modification a ete enregistree localement.'); - } catch (e) { alert('Erreur: ' + err.message); } - } else { - alert('Erreur: ' + err.message); - } - } -} - -async function deleteFile() { - // If Forge is open, delegate delete to the iframe - var forgeFrame = document.getElementById("forge-iframe"); - if (forgeFrame && forgeFrame.contentWindow) { - if (!state.editorVault || !state.editorPath) return; - forgeFrame.contentWindow.postMessage({ type: 'parent-delete' }, '*'); - return; - } - - if (!state.editorVault || !state.editorPath) return; - - const deleteBtn = document.getElementById("editor-delete"); - const originalHTML = deleteBtn.innerHTML; - let success = false; - - try { - deleteBtn.disabled = true; - deleteBtn.innerHTML = ''; - safeCreateIcons(); - - const response = await fetch(`/api/file/${encodeURIComponent(state.editorVault)}?path=${encodeURIComponent(state.editorPath)}`, { method: "DELETE" }); - - if (!response.ok) { - const error = await response.json(); - throw new Error(error.detail || "Erreur de suppression"); - } - - success = true; - closeEditor(); - showWelcome(); - await refreshSidebarForContext(); - await refreshTagsForContext(); - } catch (err) { - console.error("Delete error:", err); - alert(`Erreur: ${err.message}`); - } finally { - deleteBtn.innerHTML = originalHTML; - deleteBtn.disabled = false; - if (success) safeCreateIcons(); - } -} - -function initEditor() { - const cancelBtn = document.getElementById("editor-cancel"); - const deleteBtn = document.getElementById("editor-delete"); - const saveBtn = document.getElementById("editor-save"); - const modal = document.getElementById("editor-modal"); - - cancelBtn.addEventListener("click", closeEditor); - deleteBtn.addEventListener("click", deleteFile); - saveBtn.addEventListener("click", () => saveFile()); - - // ESC to close - document.addEventListener("keydown", (e) => { - if (e.key === "Escape" && modal.classList.contains("active")) { - closeEditor(); - } - }); - - // Fix mouse wheel scrolling in editor - modal.addEventListener( - "wheel", - (e) => { - const editorBody = document.getElementById("editor-body"); - if (editorBody && editorBody.contains(e.target)) { - // Let the editor handle the scroll - return; - } - // Prevent modal from scrolling if not in editor area - e.preventDefault(); - }, - { passive: false }, - ); -} - -/** Copy text to clipboard — works on both HTTP and HTTPS */ -function copyToClipboard(text) { - // Try modern API first (HTTPS-only) - if (navigator.clipboard && window.isSecureContext) { - navigator.clipboard.writeText(text).catch(() => {}); - return true; - } - // Fallback for HTTP contexts - const ta = document.createElement("textarea"); - ta.value = text; - ta.style.position = "fixed"; - ta.style.left = "-9999px"; - ta.style.top = "-9999px"; - document.body.appendChild(ta); - ta.focus(); - ta.select(); - try { - document.execCommand("copy"); - return true; - } catch (e) { - return false; - } finally { - document.body.removeChild(ta); - } -} - -export { getFileIcon, safeCreateIcons, flushIcons, safeHighlight, escapeHtml, EXT_ICONS, openEditor, closeEditor, saveFile, deleteFile, waitForCodeMirror, initEditor, copyToClipboard }; diff --git a/desktop/frontend-static/js/vaulthome.js b/desktop/frontend-static/js/vaulthome.js deleted file mode 100644 index f21f44b..0000000 --- a/desktop/frontend-static/js/vaulthome.js +++ /dev/null @@ -1,384 +0,0 @@ -/** - * Vault Home Page module for ObsiGate. - * - * When a specific vault is selected (not "All"), replaces the dashboard - * with a non-recursive file listing sorted by modification time (newest first). - * Only files from the selected directory are shown (not subdirectories) - * to keep the listing fast and lightweight. - * The listing updates automatically when browsing into subdirectories. - * - * The visual style mirrors the search results (.search-result-item) for - * consistency. - * - * Usage: - * import { showVaultHome, updateVaultHomeDir, isVaultHomeActive } from './vaulthome.js'; - */ - -import { api } from './auth.js'; -import { el } from './viewer.js'; -import { getFileIcon, safeCreateIcons } from './utils.js'; -import { TabManager } from './ui.js'; -import { t, getLocale } from './i18n.js'; - -// --------------------------------------------------------------------------- -// State -// --------------------------------------------------------------------------- - -const state = { - active: false, - currentVault: null, - currentDir: '', // empty = vault root -}; - -// --------------------------------------------------------------------------- -// Public API -// --------------------------------------------------------------------------- - -/** Check if vault home is currently displayed. */ -export function isVaultHomeActive() { - return state.active; -} - -/** - * Display the vault home page for a vault directory. - * @param {string} vaultName - Vault name - * @param {string} dirPath - Directory path (empty for root) - */ -export async function showVaultHome(vaultName, dirPath = '') { - if (vaultName === 'all' || !vaultName) { - state.active = false; - return; - } - - state.active = true; - state.currentVault = vaultName; - state.currentDir = dirPath || ''; - - const area = document.getElementById('content-area'); - if (!area) return; - - // Remove any existing dashboard - const home = document.getElementById('dashboard-home'); - if (home) home.remove(); - - // Build vault home container - area.innerHTML = ''; - - const container = el('div', { class: 'vault-home', id: 'vault-home' }); - area.appendChild(container); - - // Breadcrumb - renderBreadcrumb(container, vaultName, state.currentDir); - - // Results container - const resultsArea = el('div', { class: 'vault-home-results', id: 'vault-home-results' }); - container.appendChild(resultsArea); - - // Show loading - resultsArea.innerHTML = ` -
    -
    -

    ${t('vaulthome.loading')}

    -
    `; - - await loadAndRender(vaultName, state.currentDir, resultsArea); - - // Also load recent files for this vault (only at root level) - if (!state.currentDir) { - loadRecentSection(vaultName, container); - } -} - -/** - * Update the vault home directory without rebuilding the whole page. - * Called when navigating into a subdirectory. - * @param {string} vaultName - * @param {string} dirPath - */ -export async function updateVaultHomeDir(vaultName, dirPath) { - if (!state.active || state.currentVault !== vaultName) return; - - state.currentDir = dirPath || ''; - - const container = document.getElementById('vault-home'); - if (!container) return; - - // Update breadcrumb - const bc = container.querySelector('.vault-home-breadcrumb'); - if (bc) { - bc.innerHTML = ''; - buildBreadcrumbHTML(bc, vaultName, state.currentDir); - safeCreateIcons(); - } - - // Remove recent section when navigating into subdirectory - const recentSection = container.querySelector('.vault-home-recent'); - if (recentSection) recentSection.remove(); - - // Reload results - const resultsArea = document.getElementById('vault-home-results'); - if (resultsArea) { - resultsArea.innerHTML = ` -
    -
    -
    `; - await loadAndRender(vaultName, state.currentDir, resultsArea); - } -} - -// --------------------------------------------------------------------------- -// Tree click delegation — update vault home on directory clicks -// --------------------------------------------------------------------------- - -let _treeDelegationInstalled = false; - -function _initTreeDelegation() { - if (_treeDelegationInstalled) return; - - const tree = document.getElementById('vault-tree'); - if (!tree) { - // Retry once when DOM might not be ready — use MutationObserver as fallback - const observer = new MutationObserver(() => { - const t = document.getElementById('vault-tree'); - if (t) { - observer.disconnect(); - _attachTreeListener(t); - } - }); - observer.observe(document.body, { childList: true, subtree: true }); - return; - } - - _attachTreeListener(tree); -} - -function _attachTreeListener(tree) { - if (_treeDelegationInstalled) return; - _treeDelegationInstalled = true; - - tree.addEventListener('click', (e) => { - if (!state.active) return; - - // Find the closest tree-item that is a directory - const item = e.target.closest('.tree-item'); - if (!item || !item.dataset.vault || item.dataset.path === undefined) return; - - const vault = item.dataset.vault; - const path = item.dataset.path; - - // Only react to directory clicks (items that have a child container) - const hasChildContainer = item.nextElementSibling - && item.nextElementSibling.classList.contains('tree-children'); - if (!hasChildContainer) return; - - // Update vault home dir - updateVaultHomeDir(vault, path); - }); -} - -// Initialize delegation when module loads -_initTreeDelegation(); - -// --------------------------------------------------------------------------- -// Rendering -// --------------------------------------------------------------------------- - -function renderBreadcrumb(container, vaultName, dirPath) { - const bc = el('div', { class: 'vault-home-breadcrumb' }); - buildBreadcrumbHTML(bc, vaultName, dirPath); - container.appendChild(bc); -} - -function buildBreadcrumbHTML(parentEl, vaultName, dirPath) { - // Vault icon + name (root) - const vaultLink = el('span', { class: 'vault-home-breadcrumb-item vault-home-breadcrumb-root' }, [ - el('i', { 'data-lucide': 'database', style: 'width:14px;height:14px' }), - el('span', {}, [document.createTextNode(vaultName)]), - ]); - vaultLink.addEventListener('click', () => updateVaultHomeDir(vaultName, '')); - vaultLink.style.cursor = 'pointer'; - parentEl.appendChild(vaultLink); - - if (!dirPath) return; - - const segments = dirPath.split('/').filter(Boolean); - let cumulative = ''; - for (const seg of segments) { - cumulative = cumulative ? cumulative + '/' + seg : seg; - const sep = el('span', { class: 'vault-home-breadcrumb-sep' }, [document.createTextNode(' / ')]); - parentEl.appendChild(sep); - const segLink = el('span', { class: 'vault-home-breadcrumb-item' }, [ - el('i', { 'data-lucide': 'folder', style: 'width:14px;height:14px' }), - el('span', {}, [document.createTextNode(seg)]), - ]); - segLink.addEventListener('click', () => updateVaultHomeDir(vaultName, cumulative)); - segLink.style.cursor = 'pointer'; - parentEl.appendChild(segLink); - } -} - -async function loadAndRender(vaultName, dirPath, container) { - try { - const url = `/api/vault/${encodeURIComponent(vaultName)}/files?dir=${encodeURIComponent(dirPath)}&limit=200&recursive=false`; - const data = await api(url); - - if (!data.files || data.files.length === 0) { - container.innerHTML = ` -
    - -

    ${t('vaulthome.empty')}

    -
    `; - safeCreateIcons(); - return; - } - - // Header - const header = el('div', { class: 'vault-home-header' }); - const countKey = data.files.length > 1 ? 'vaulthome.file_count_plural' : 'vaulthome.file_count'; - const countStr = t(countKey, { count: data.files.length }); - const count = el('span', { class: 'vault-home-count', 'data-i18n': countKey }, [ - document.createTextNode(countStr), - ]); - header.appendChild(count); - - // Directory label - const dirLabel = dirPath ? `/${dirPath}` : ` ${t('common.root')}`; - const dirInfo = el('span', { class: 'vault-home-dir-info' }, [ - document.createTextNode(dirLabel), - ]); - header.appendChild(dirInfo); - - container.innerHTML = ''; - container.appendChild(header); - - // File list — using search-result-item style - const list = el('div', { class: 'search-results' }); - const locale = getLocale(); - - data.files.forEach((f) => { - const fileIconName = getFileIcon ? getFileIcon(f.name) : 'file'; - const displayName = f.name.endsWith('.md') ? f.name.slice(0, -3) : f.name; - const ext = f.extension || ''; - - const titleDiv = el('div', { class: 'search-result-title' }, [ - document.createTextNode(displayName), - ]); - - // Format date using current locale - const modDate = new Date(f.modified * 1000); - const dateStr = modDate.toLocaleDateString(locale === 'fr' ? 'fr-CA' : 'en-CA', { - year: 'numeric', month: 'short', day: 'numeric', - hour: '2-digit', minute: '2-digit', - }); - - // Build metadata line: date + size - const metaParts = []; - metaParts.push(dateStr); - metaParts.push(formatSize(f.size)); - - const metaDiv = el('div', { class: 'search-result-vault' }, [ - document.createTextNode(metaParts.join(' · ')), - ]); - - const item = el('div', { - class: 'search-result-item vault-home-item', - 'data-vault': f.vault, - 'data-path': f.path, - }, [ - el('span', { class: 'search-result-ext' }, [document.createTextNode(ext)]), - el('i', { 'data-lucide': fileIconName, style: 'width:14px;height:14px;margin-right:4px;opacity:0.6' }), - titleDiv, - metaDiv, - ]); - - item.addEventListener('click', () => TabManager.openPreview(f.vault, f.path)); - item.addEventListener('dblclick', (e) => { - e.preventDefault(); - TabManager.openPersistent(f.vault, f.path); - }); - - list.appendChild(item); - }); - - container.appendChild(list); - safeCreateIcons(); - } catch (err) { - const errMsg = t('vaulthome.error_loading') + ' ' + escapeHtml(err?.detail || err?.message || t('common.unknown')); - container.innerHTML = ` -
    -

    ${errMsg}

    -
    `; - } -} - -// --------------------------------------------------------------------------- -// Recent files section (loaded at vault root only) -// --------------------------------------------------------------------------- - -async function loadRecentSection(vaultName, container) { - try { - const data = await api(`/api/recent?mode=opened&vault=${encodeURIComponent(vaultName)}&limit=5`); - const files = data.files || []; - if (files.length === 0) return; - - // Insert recent section BEFORE the results area - const resultsArea = document.getElementById('vault-home-results'); - const section = el('div', { class: 'vault-home-recent' }); - - const header = el('div', { class: 'vault-home-recent-header' }); - header.innerHTML = ` - - ${t('dashboard.recent')}`; - section.appendChild(header); - - const list = el('div', { class: 'vault-home-recent-list' }); - files.forEach((f) => { - const title = f.title || f.path.split('/').pop() || ''; - const displayTitle = title.endsWith('.md') ? title.slice(0, -3) : title; - const dir = f.path.includes('/') ? f.path.split('/').slice(0, -1).join('/') + '/' : ''; - - const item = el('div', { class: 'vault-home-recent-item' }); - item.innerHTML = ` - - ${escapeHtml(displayTitle)} - ${escapeHtml(dir)} - ${escapeHtml(f.mtime_human || '')}`; - - item.addEventListener('click', () => TabManager.openPreview(f.vault, f.path)); - item.addEventListener('dblclick', (e) => { - e.preventDefault(); - TabManager.openPersistent(f.vault, f.path); - }); - list.appendChild(item); - }); - - section.appendChild(list); - - // Insert before the results area - if (resultsArea) { - container.insertBefore(section, resultsArea); - } else { - container.appendChild(section); - } - - safeCreateIcons(); - } catch { - // Silently skip if recent files can't be loaded - } -} - -// --------------------------------------------------------------------------- -// Utility -// --------------------------------------------------------------------------- - -function formatSize(bytes) { - if (bytes < 1024) return bytes + ' ' + t('vaulthome.size_bytes'); - if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' ' + t('vaulthome.size_kb'); - return (bytes / (1024 * 1024)).toFixed(1) + ' ' + t('vaulthome.size_mb'); -} - -function escapeHtml(str) { - const div = document.createElement('div'); - div.textContent = str; - return div.innerHTML; -} diff --git a/desktop/frontend-static/js/viewer.js b/desktop/frontend-static/js/viewer.js deleted file mode 100644 index 735f04f..0000000 --- a/desktop/frontend-static/js/viewer.js +++ /dev/null @@ -1,1550 +0,0 @@ -/* ObsiGate — Viewer module */ -import { api } from './auth.js'; -import { state } from './state.js'; -import { escapeHtml, safeCreateIcons, safeHighlight, getFileIcon, openEditor, copyToClipboard } from './utils.js'; -import { TabManager, closeMobileSidebar, ContextMenuManager, RightSidebarManager, showToast, buildFrontmatterCard } from './ui.js'; -import { syncActiveFileTreeItem, searchByTag, TagFilterService, refreshSidebarTreePreservingState, focusPathInSidebar } from './sidebar.js'; -import { AutocompleteDropdown, performAdvancedSearch } from './search.js'; -import { initDashboardTabs } from './sync.js'; -import { renderMermaidBlocks } from './mermaid-viewer.js'; -import { DashboardStatsWidget, DashboardRecentWidget, DashboardBookmarkWidget, DashboardSharedWidget, DashboardConflictsWidget } from './dashboard.js'; -import { openShareDialog } from './config.js'; -import { cacheViewedFile, getCachedFile } from './offline.js'; -import { t } from './i18n.js'; -// --------------------------------------------------------------------------- -// Outline/TOC Manager -// --------------------------------------------------------------------------- - -const OutlineManager = { - /** - * Slugify text to create valid IDs - */ - slugify(text) { - return ( - text - .toLowerCase() - .normalize("NFD") - .replace(/[\u0300-\u036f]/g, "") - .replace(/[^\p{L}\p{N}\s-]/gu, "") - .replace(/\s+/g, "-") - .replace(/-+/g, "-") - .trim() || "heading" - ); - }, - - /** - * Parse headings from markdown content - */ - parseHeadings() { - const contentArea = document.querySelector(".md-content"); - if (!contentArea) return []; - - const headings = []; - const h2s = contentArea.querySelectorAll("h2"); - const h3s = contentArea.querySelectorAll("h3"); - const allHeadings = [...h2s, ...h3s].sort((a, b) => { - return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1; - }); - - const usedIds = new Map(); - - allHeadings.forEach((heading) => { - const text = heading.textContent.trim(); - if (!text) return; - - const level = parseInt(heading.tagName[1]); - let id = this.slugify(text); - - // Handle duplicate IDs - if (usedIds.has(id)) { - const count = usedIds.get(id) + 1; - usedIds.set(id, count); - id = `${id}-${count}`; - } else { - usedIds.set(id, 1); - } - - // Inject ID into heading if not present - if (!heading.id) { - heading.id = id; - } else { - id = heading.id; - } - - headings.push({ - id, - level, - text, - element: heading, - }); - }); - - return headings; - }, - - /** - * Render outline list - */ - renderOutline(headings) { - const outlineList = document.getElementById("outline-list"); - const outlineEmpty = document.getElementById("outline-empty"); - - if (!outlineList) return; - - outlineList.innerHTML = ""; - - if (!headings || headings.length === 0) { - outlineList.hidden = true; - if (outlineEmpty) { - outlineEmpty.hidden = false; - safeCreateIcons(); - } - return; - } - - outlineList.hidden = false; - if (outlineEmpty) outlineEmpty.hidden = true; - - headings.forEach((heading) => { - const item = el( - "a", - { - class: `outline-item level-${heading.level}`, - href: `#${heading.id}`, - "data-heading-id": heading.id, - role: "link", - }, - [document.createTextNode(heading.text)], - ); - - item.addEventListener("click", (e) => { - e.preventDefault(); - this.scrollToHeading(heading.id); - }); - - outlineList.appendChild(item); - }); - - state.headingsCache = headings; - }, - - /** - * Scroll to heading with smooth behavior - */ - scrollToHeading(headingId) { - const heading = document.getElementById(headingId); - if (!heading) return; - - const contentArea = document.getElementById("content-area"); - if (!contentArea) return; - - // Calculate offset for fixed header (if any) - const headerHeight = 80; - const headingTop = heading.offsetTop; - - contentArea.scrollTo({ - top: headingTop - headerHeight, - behavior: "smooth", - }); - - // Update active state immediately - this.setActiveHeading(headingId); - }, - - /** - * Set active heading in outline - */ - setActiveHeading(headingId) { - if (state.activeHeadingId === headingId) return; - - state.activeHeadingId = headingId; - - const items = document.querySelectorAll(".outline-item"); - items.forEach((item) => { - if (item.getAttribute("data-heading-id") === headingId) { - item.classList.add("active"); - item.setAttribute("aria-current", "location"); - // Scroll outline item into view - item.scrollIntoView({ block: "nearest", behavior: "smooth" }); - } else { - item.classList.remove("active"); - item.removeAttribute("aria-current"); - } - }); - }, - - /** - * Initialize outline for current document - */ - init() { - const headings = this.parseHeadings(); - this.renderOutline(headings); - ScrollSpyManager.init(headings); - ReadingProgressManager.init(); - }, - - /** - * Cleanup - */ - destroy() { - ScrollSpyManager.destroy(); - ReadingProgressManager.destroy(); - state.headingsCache = []; - state.activeHeadingId = null; - }, -}; - - -// --------------------------------------------------------------------------- -// Scroll Spy Manager -// --------------------------------------------------------------------------- - -const ScrollSpyManager = { - observer: null, - headings: [], - - init(headings) { - this.destroy(); - this.headings = headings; - - if (!headings || headings.length === 0) return; - - const contentArea = document.getElementById("content-area"); - if (!contentArea) return; - - const options = { - root: contentArea, - rootMargin: "-20% 0px -70% 0px", - threshold: [0, 0.3, 0.5, 1.0], - }; - - this.observer = new IntersectionObserver((entries) => { - // Find the most visible heading - let mostVisible = null; - let maxRatio = 0; - - entries.forEach((entry) => { - if (entry.isIntersecting && entry.intersectionRatio > maxRatio) { - maxRatio = entry.intersectionRatio; - mostVisible = entry.target; - } - }); - - if (mostVisible && mostVisible.id) { - OutlineManager.setActiveHeading(mostVisible.id); - } - }, options); - - // Observe all headings - headings.forEach((heading) => { - if (heading.element) { - this.observer.observe(heading.element); - } - }); - }, - - destroy() { - if (this.observer) { - this.observer.disconnect(); - this.observer = null; - } - this.headings = []; - }, -}; - - -// --------------------------------------------------------------------------- -// Reading Progress Manager -// --------------------------------------------------------------------------- - -const ReadingProgressManager = { - scrollHandler: null, - - init() { - this.destroy(); - - const contentArea = document.getElementById("content-area"); - if (!contentArea) return; - - this.scrollHandler = this.throttle(() => { - this.updateProgress(); - }, 100); - - contentArea.addEventListener("scroll", this.scrollHandler); - this.updateProgress(); - }, - - updateProgress() { - const contentArea = document.getElementById("content-area"); - const progressFill = document.getElementById("reading-progress-fill"); - const progressText = document.getElementById("reading-progress-text"); - - if (!contentArea || !progressFill || !progressText) return; - - const scrollTop = contentArea.scrollTop; - const scrollHeight = contentArea.scrollHeight; - const clientHeight = contentArea.clientHeight; - - const maxScroll = scrollHeight - clientHeight; - const percentage = maxScroll > 0 ? Math.round((scrollTop / maxScroll) * 100) : 0; - - progressFill.style.width = `${percentage}%`; - progressText.textContent = `${percentage}%`; - }, - - throttle(func, delay) { - let lastCall = 0; - return function (...args) { - const now = Date.now(); - if (now - lastCall >= delay) { - lastCall = now; - func.apply(this, args); - } - }; - }, - - destroy() { - const contentArea = document.getElementById("content-area"); - if (contentArea && this.scrollHandler) { - contentArea.removeEventListener("scroll", this.scrollHandler); - } - this.scrollHandler = null; - - // Reset progress - const progressFill = document.getElementById("reading-progress-fill"); - const progressText = document.getElementById("reading-progress-text"); - if (progressFill) progressFill.style.width = "0%"; - if (progressText) progressText.textContent = "0%"; - }, -}; - - -// --------------------------------------------------------------------------- -// File viewer -// --------------------------------------------------------------------------- -export async function openFile(vaultName, filePath) { - state.currentVault = vaultName; - state.currentPath = filePath; - state.showingSource = false; - state.cachedRawSource = null; - - // Highlight active - syncActiveFileTreeItem(vaultName, filePath); - - // Show loading state while fetching - const area = document.getElementById("content-area"); - area.innerHTML = '
    Chargement...
    '; - - try { - const url = `/api/file/${encodeURIComponent(vaultName)}?path=${encodeURIComponent(filePath)}`; - const data = await api(url); - // Cache the file for offline use - if (data && !data.unsupported && data.content) { - cacheViewedFile(vaultName, filePath, data.content, data.modified); - } - renderFile(data); - } catch (err) { - // Try IndexedDB fallback - console.log('[Viewer] Network failed, trying offline cache:', err); - const cached = await getCachedFile(vaultName, filePath); - if (cached && cached.content) { - const fakeData = { - vault: vaultName, - path: filePath, - title: filePath.split('/').pop().replace(/\.md$/, ''), - content: cached.content, - html: null, - raw_size: cached.content.length, - modified: cached.modified || '', - tags: [], - offline: true - }; - renderFile(fakeData); - showToast(t('viewer.loaded_from_cache'), 'info'); - } else { - area.innerHTML = '

    Impossible de charger le fichier — vous etes hors-ligne et ce fichier n\'est pas en cache.

    '; - } - } -} - -async function renderBacklinksPanel(vault, path, container) { - try { - const data = await api(`/api/file/${encodeURIComponent(vault)}/backlinks?path=${encodeURIComponent(path)}`); - if (!data.backlinks || data.backlinks.length === 0) return; - - const panel = el("div", { class: "backlinks-panel" }); - const header = el("div", { class: "backlinks-header" }, [ - icon("link", 14), - document.createTextNode(` ${data.total} lien(s) entrant(s)`), - ]); - panel.appendChild(header); - - const list = el("div", { class: "backlinks-list" }); - data.backlinks.forEach((bl) => { - const item = el("div", { class: "backlink-item" }); - const vaultBadge = el("span", { class: "backlink-vault" }, [document.createTextNode(bl.vault)]); - const titleEl = el("span", { class: "backlink-title" }, [document.createTextNode(bl.title || bl.path.split("/").pop().replace(/\.md$/i, ""))]); - item.appendChild(icon(getFileIcon(bl.path), 12)); - item.appendChild(vaultBadge); - item.appendChild(titleEl); - item.addEventListener("click", () => TabManager.openPreview(bl.vault, bl.path)); - item.addEventListener("dblclick", (e) => { e.preventDefault(); TabManager.openPersistent(bl.vault, bl.path); }); - list.appendChild(item); - }); - panel.appendChild(list); - container.appendChild(panel); - } catch (err) { - // Silently ignore — backlinks are optional - console.debug("Backlinks fetch failed:", err); - } -} - -export function renderFile(data) { - const area = document.getElementById("content-area"); - - // Handle PDF files — render in iframe - if (data.is_pdf) { - const pdfUrl = `/api/file/${encodeURIComponent(data.vault)}/pdf/stream?path=${encodeURIComponent(data.path)}`; - const pages = data.pdf_metadata && data.pdf_metadata.pages ? data.pdf_metadata.pages : '?'; - area.innerHTML = ` -
    -
    - PDF — ${pages} pages - - -
    - -
    `; - lucide.createIcons(); - return; - } - - // Handle unsupported (binary) files - if (data.unsupported) { - const sizeStr = data.size_bytes - ? data.size_bytes < 1024 ? `${data.size_bytes} o` - : data.size_bytes < 1048576 ? `${(data.size_bytes / 1024).toFixed(1)} Ko` - : `${(data.size_bytes / 1048576).toFixed(1)} Mo` - : ""; - area.innerHTML = ` -
    - -
    ${escapeHtml(data.path.split("/").pop())}
    -
    Ce fichier est binaire et ne peut pas être affiché.
    - ${sizeStr ? `
    Taille : ${sizeStr}
    ` : ""} - -
    `; - lucide.createIcons(); - document.getElementById("unsupported-download-btn").addEventListener("click", () => { - const dlUrl = `/api/file/${encodeURIComponent(data.vault)}/download?path=${encodeURIComponent(data.path)}`; - window.open(dlUrl, "_blank"); - }); - return; - } - - // Breadcrumb - const parts = data.path.split("/"); - const breadcrumbEls = []; - breadcrumbEls.push( - makeBreadcrumbSpan(data.vault, () => { - focusPathInSidebar(data.vault, "", { alignToTop: "center" }); - }), - ); - let accumulated = ""; - parts.forEach((part, i) => { - breadcrumbEls.push(el("span", { class: "sep" }, [document.createTextNode(" / ")])); - accumulated += (accumulated ? "/" : "") + part; - const p = accumulated; - if (i < parts.length - 1) { - breadcrumbEls.push( - makeBreadcrumbSpan(part, () => { - focusPathInSidebar(data.vault, p, { alignToTop: "center" }); - }), - ); - } else { - breadcrumbEls.push( - makeBreadcrumbSpan(part.replace(/\.md$/i, ""), () => { - focusPathInSidebar(data.vault, data.path, { alignToTop: "center" }); - }), - ); - } - }); - - const breadcrumb = el("div", { class: "breadcrumb" }, breadcrumbEls); - - // Tags - const tagsDiv = el("div", { class: "file-tags" }); - (data.tags || []).forEach((tag) => { - if (!TagFilterService.isTagFiltered(tag)) { - const t = el("span", { class: "file-tag" }, [document.createTextNode(`#${tag}`)]); - t.addEventListener("click", () => searchByTag(tag)); - tagsDiv.appendChild(t); - } - }); - - // Action buttons - const copyBtn = el("button", { class: "btn-action", title: "Copier la source" }, [icon("copy", 14), document.createTextNode("Copier")]); - copyBtn.addEventListener("click", async () => { - try { - // Fetch raw content if not already cached - if (!state.cachedRawSource) { - const rawUrl = `/api/file/${encodeURIComponent(data.vault)}/raw?path=${encodeURIComponent(data.path)}`; - const rawData = await api(rawUrl); - state.cachedRawSource = rawData.raw; - } - if (navigator.clipboard) { - await navigator.clipboard.writeText(state.cachedRawSource); - } else { - // Fallback for non-secure contexts - const ta = document.createElement("textarea"); - ta.value = state.cachedRawSource; - ta.style.position = "fixed"; ta.style.opacity = "0"; - document.body.appendChild(ta); ta.select(); - document.execCommand("copy"); - document.body.removeChild(ta); - } - copyBtn.lastChild.textContent = t('viewer.copied'); - setTimeout(() => (copyBtn.lastChild.textContent = t('viewer.copy')), 1500); - } catch (err) { - console.error("Copy error:", err); - showToast(t("viewer.copy_error"), "error"); - } - }); - - const sourceBtn = el("button", { class: "btn-action", title: "Voir la source" }, [icon("code", 14), document.createTextNode("Source")]); - - // MD download button - const mdBtn = el("button", { class: "btn-action", title: t("viewer.download_md") }, [icon("file-text", 14), document.createTextNode(".md")]); - mdBtn.addEventListener("click", () => { - const dlUrl = `/api/file/${encodeURIComponent(data.vault)}/download?path=${encodeURIComponent(data.path)}`; - const a = document.createElement("a"); - a.href = dlUrl; - a.download = data.path.split("/").pop(); - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - }); - - // PDF download button - const pdfBtn = el("button", { class: "btn-action", title: t("viewer.download_pdf") }, [icon("file", 14), document.createTextNode("PDF")]); - pdfBtn.addEventListener("click", () => { - const pdfUrl = `/api/file/${encodeURIComponent(data.vault)}/pdf?path=${encodeURIComponent(data.path)}`; - window.open(pdfUrl, "_blank"); - }); - - const editBtn = el("button", { class: "btn-action", title: "Editer" }, [icon("edit", 14), document.createTextNode("Editer")]); - editBtn.addEventListener("click", () => { - openEditor(data.vault, data.path); - }); - - const forgeBtn = el("button", { class: "btn-action btn-forge", title: t("viewer.forge_title") }, [icon("hammer", 14), document.createTextNode("Forge")]); - forgeBtn.addEventListener("click", () => { - var modal = document.getElementById("editor-modal"); - var container = modal.querySelector(".editor-container"); - var bodyEl = document.getElementById("editor-body"); - // Set editor state so parent buttons work - state.editorVault = data.vault; - state.editorPath = data.path; - // Update header: show "Forge" brand + filename - var brand = modal.querySelector(".editor-brand"); - var titleInp = document.getElementById("editor-title-input"); - var fileInp = document.getElementById("editor-filename-input"); - if (brand) brand.textContent = t("viewer.forge_brand"); - if (titleInp) { titleInp.value = data.title || ''; titleInp.placeholder = t('forge.title_placeholder'); } - if (fileInp) fileInp.value = data.path.split('/').pop(); - bodyEl.innerHTML = ""; - bodyEl.style.overflow = "hidden"; - var iframe = document.createElement("iframe"); - iframe.id = "forge-iframe"; - iframe.src = "/editor-poc?vault=" + encodeURIComponent(data.vault) + "&path=" + encodeURIComponent(data.path) + "&_ts=" + Date.now(); - iframe.style.cssText = "width:100%;height:82vh;border:none;display:block;"; - bodyEl.appendChild(iframe); - modal.classList.add("active"); - safeCreateIcons(); - }); - - const openNewWindowBtn = el("button", { class: "btn-action", title: t("forge.popout") }, [icon("external-link", 14), document.createTextNode(t("forge.popout_label"))]); - openNewWindowBtn.addEventListener("click", () => { - const theme = document.documentElement.getAttribute('data-theme') || 'dark'; - const popoutUrl = `/popout/${encodeURIComponent(data.vault)}/${encodeURIComponent(data.path)}?theme=${theme}`; - window.open(popoutUrl, `popout_${data.vault}_${data.path.replace(/[^a-zA-Z0-9]/g, "_")}`, "width=1000,height=700,menubar=no,toolbar=no,location=no,status=no,resizable=yes,scrollbars=no"); - }); - - const tocBtn = el("button", { class: "btn-action", id: "toc-toggle-btn", title: "Afficher/Masquer le sommaire" }, [icon("list", 14), document.createTextNode("TOC")]); - tocBtn.addEventListener("click", () => { - RightSidebarManager.toggle(); - }); - - // Share button — check if already shared - const shareBtn = el("button", { class: "btn-action btn-share", title: "Partager ce document" }, [icon("share-2", 14), document.createTextNode("Partager")]); - // Check if already shared and color the button - (async () => { - try { - const shares = await api("/api/shares"); - if (shares.some(s => s.vault === data.vault && s.path === data.path)) { - shareBtn.classList.add("shared"); - shareBtn.title = t('viewer.shared_doc_title'); - } - } catch (e) { /* ignore */ } - })(); - shareBtn.addEventListener("click", () => openShareDialog(data.vault, data.path)); - - // Bookmark button — check if already bookmarked - const bookmarkBtn = el("button", { class: "btn-action btn-bookmark", title: t("viewer.bookmark_toggle") }, [icon("bookmark-plus", 14), document.createTextNode("Bookmark")]); - // Check bookmark status and color the button - (async () => { - try { - const bms = await api("/api/bookmarks"); - if (Array.isArray(bms) && bms.some(b => b.vault === data.vault && b.path === data.path)) { - bookmarkBtn.classList.add("active"); - bookmarkBtn.title = t("viewer.bookmark_remove"); - } - } catch (e) { /* ignore */ } - })(); - bookmarkBtn.addEventListener("click", async () => { - try { - const res = await api("/api/bookmarks/toggle", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ vault: data.vault, path: data.path, title: data.title }) }); - bookmarkBtn.classList.toggle("active", res.bookmarked); - bookmarkBtn.title = res.bookmarked ? t("viewer.bookmark_remove") : t("viewer.bookmark_add"); - showToast(res.bookmarked ? "Ajouté aux bookmarks" : "Retiré des bookmarks", "success"); - if (typeof DashboardBookmarkWidget !== "undefined") DashboardBookmarkWidget.load(); - } catch (err) { showToast("Erreur: " + err.message, "error"); } - }); - - // Frontmatter — Accent Card - let fmSection = null; - if (data.frontmatter && Object.keys(data.frontmatter).length > 0) { - fmSection = buildFrontmatterCard(data.frontmatter); - } - - // Content container (rendered HTML) - const mdDiv = el("div", { class: "md-content", id: "file-rendered-content" }); - mdDiv.innerHTML = data.html; - - // Raw source container (hidden initially) - const rawDiv = el("div", { class: "raw-source-view", id: "file-raw-content", style: "display:none" }); - - // Source button toggle logic - sourceBtn.addEventListener("click", async () => { - const rendered = document.getElementById("file-rendered-content"); - const raw = document.getElementById("file-raw-content"); - if (!rendered || !raw) return; - - state.showingSource = !state.showingSource; - if (state.showingSource) { - sourceBtn.classList.add("active"); - if (!state.cachedRawSource) { - const rawUrl = `/api/file/${encodeURIComponent(data.vault)}/raw?path=${encodeURIComponent(data.path)}`; - const rawData = await api(rawUrl); - state.cachedRawSource = rawData.raw; - } - raw.textContent = state.cachedRawSource; - rendered.style.display = "none"; - raw.style.display = "block"; - } else { - sourceBtn.classList.remove("active"); - rendered.style.display = "block"; - raw.style.display = "none"; - } - }); - - // Assemble - area.innerHTML = ""; - area.appendChild(breadcrumb); - area.appendChild(el("div", { class: "file-header" }, [el("div", { class: "file-title" }, [document.createTextNode(data.title)]), tagsDiv, el("div", { class: "file-actions" }, [copyBtn, sourceBtn, mdBtn, pdfBtn, editBtn, forgeBtn, openNewWindowBtn, tocBtn, shareBtn, bookmarkBtn])])); - if (fmSection) area.appendChild(fmSection); - area.appendChild(mdDiv); - area.appendChild(rawDiv); - - // Backlinks panel - if (data.is_markdown) { - renderBacklinksPanel(data.vault, data.path, area); - } - - // Highlight code blocks - area.querySelectorAll("pre code").forEach((block) => { - safeHighlight(block); - }); - - // Add copy buttons to code blocks - area.querySelectorAll("pre").forEach((pre) => { - if (pre.parentElement?.classList.contains("code-block-wrapper")) return; - const wrapper = el("div", { class: "code-block-wrapper" }, []); - wrapper.style.position = "relative"; - pre.replaceWith(wrapper); - wrapper.appendChild(pre); - - const btn = el("button", { class: "copy-code-btn", title: "Copier le code" }, [document.createTextNode("Copier")]); - btn.addEventListener("click", (e) => { - e.stopPropagation(); - const code = pre.querySelector("code")?.textContent || pre.textContent; - const copied = copyToClipboard(code); - if (copied) { - btn.textContent = "✓ Copié"; - btn.classList.add("copied"); - if (typeof showToast === "function") showToast("Code copié dans le presse-papiers", "success"); - setTimeout(() => { btn.textContent = "Copier"; btn.classList.remove("copied"); }, 2000); - } else { - if (typeof showToast === "function") showToast("Erreur lors de la copie", "error"); - } - }); - wrapper.appendChild(btn); - }); - - // Render Mermaid diagrams - renderMermaidBlocks(area); - - // Wire up wikilinks - area.querySelectorAll(".wikilink").forEach((link) => { - link.addEventListener("click", (e) => { - e.preventDefault(); - const v = link.getAttribute("data-vault"); - const p = link.getAttribute("data-path"); - if (v && p) TabManager.openPreview(v, p); - }); - }); - - safeCreateIcons(); - area.scrollTop = 0; - - // Initialize outline/TOC for this document - OutlineManager.init(); -} - - -// --------------------------------------------------------------------------- -// Helpers (escapeHtml imported from utils.js) -// --------------------------------------------------------------------------- -export function el(tag, attrs, children) { - const e = document.createElement(tag); - if (attrs) { - Object.entries(attrs).forEach(([k, v]) => { - // Skip boolean false for standard HTML boolean attributes to avoid setAttribute("checked", "false") bug - if (v === false && (k === "checked" || k === "disabled" || k === "hidden" || k === "required" || k === "readonly")) { - return; - } - e.setAttribute(k, v); - }); - } - if (children) { - children.forEach((c) => { - if (c) e.appendChild(c); - }); - } - return e; -} - -export function icon(name, size) { - const i = document.createElement("i"); - i.setAttribute("data-lucide", name); - i.style.width = size + "px"; - i.style.height = size + "px"; - i.classList.add("icon"); - return i; -} - -export function smallBadge(count) { - const s = document.createElement("span"); - s.className = "badge-small"; - s.style.cssText = "font-size:0.68rem;color:var(--text-muted);margin-left:4px"; - s.textContent = `(${count})`; - return s; -} - -function getContextMenuPositionFromElement(target) { - const rect = target.getBoundingClientRect(); - return { - x: Math.min(rect.right - 8, window.innerWidth - 16), - y: Math.min(rect.top + rect.height / 2, window.innerHeight - 16), - }; -} - -export function attachTreeItemActionButton(itemEl, vault, path, type, isReadonly) { - const button = document.createElement("button"); - button.type = "button"; - button.className = "tree-item-action-btn"; - button.setAttribute("aria-label", "Afficher le menu d’actions"); - button.setAttribute("title", "Actions"); - const iconEl = icon("more-vertical", 16); - button.appendChild(iconEl); - button.addEventListener("click", (e) => { - e.preventDefault(); - e.stopPropagation(); - const pos = getContextMenuPositionFromElement(button); - ContextMenuManager.show(pos.x, pos.y, vault, path, type, isReadonly); - }); - itemEl.appendChild(button); - // Ensure Lucide icons are rendered for the button - setTimeout(() => { - safeCreateIcons(); - }, 0); -} - -export function attachTreeItemLongPress(itemEl, getMenuData) { - let pressTimer = null; - let pressHandled = false; - let startX = 0; - let startY = 0; - const longPressDelay = 550; - const moveThreshold = 10; - - const clearPressTimer = () => { - if (pressTimer) { - clearTimeout(pressTimer); - pressTimer = null; - } - }; - - itemEl.addEventListener("touchstart", (e) => { - if (!e.touches || e.touches.length !== 1) return; - pressHandled = false; - startX = e.touches[0].clientX; - startY = e.touches[0].clientY; - clearPressTimer(); - pressTimer = setTimeout(() => { - const data = getMenuData(); - if (!data) return; - pressHandled = true; - ContextMenuManager.show(startX, startY, data.vault, data.path, data.type, data.isReadonly); - }, longPressDelay); - }, { passive: true }); - - itemEl.addEventListener("touchmove", (e) => { - if (!e.touches || e.touches.length !== 1) return; - const dx = Math.abs(e.touches[0].clientX - startX); - const dy = Math.abs(e.touches[0].clientY - startY); - if (dx > moveThreshold || dy > moveThreshold) { - clearPressTimer(); - } - }, { passive: true }); - - itemEl.addEventListener("touchend", () => { - clearPressTimer(); - }, { passive: true }); - - itemEl.addEventListener("touchcancel", () => { - clearPressTimer(); - }, { passive: true }); - - itemEl.addEventListener("click", (e) => { - if (pressHandled) { - e.preventDefault(); - e.stopPropagation(); - setTimeout(() => { - pressHandled = false; - }, 0); - } - }, true); -} - -export function getVaultIcon(vaultName, size = 16) { - const v = state.allVaults.find((val) => val.name === vaultName); - const type = v ? v.type : "VAULT"; - - if (type === "DIR") { - const i = icon("folder", size); - i.style.color = "#eab308"; // yellow tint - return i; - } else { - const purple = "#8b5cf6"; - const svgNS = "http://www.w3.org/2000/svg"; - const svg = document.createElementNS(svgNS, "svg"); - svg.setAttribute("xmlns", svgNS); - svg.setAttribute("width", size); - svg.setAttribute("height", size); - svg.setAttribute("viewBox", "0 0 24 24"); - svg.setAttribute("fill", "none"); - svg.setAttribute("stroke", purple); - svg.setAttribute("stroke-width", "2"); - svg.setAttribute("stroke-linecap", "round"); - svg.setAttribute("stroke-linejoin", "round"); - svg.classList.add("icon"); - - const path1 = document.createElementNS(svgNS, "path"); - path1.setAttribute("d", "M6 3h12l4 6-10 12L2 9z"); - const path2 = document.createElementNS(svgNS, "path"); - path2.setAttribute("d", "M11 3 8 9l4 12"); - const path3 = document.createElementNS(svgNS, "path"); - path3.setAttribute("d", "M12 21l4-12-3-6"); - const path4 = document.createElementNS(svgNS, "path"); - path4.setAttribute("d", "M2 9h20"); - - svg.appendChild(path1); - svg.appendChild(path2); - svg.appendChild(path3); - svg.appendChild(path4); - return svg; - } -} - -function makeBreadcrumbSpan(text, onClick) { - const s = document.createElement("span"); - s.textContent = text; - if (onClick) { - s.addEventListener("click", async (event) => { - event.preventDefault(); - if (s.dataset.busy === "true") return; - s.dataset.busy = "true"; - s.style.pointerEvents = "none"; - try { - await onClick(event); - } finally { - s.dataset.busy = "false"; - s.style.pointerEvents = ""; - } - }); - } - return s; -} - -export function appendHighlightedText(container, text, query, caseSensitive) { - container.textContent = ""; - if (!query) { - container.appendChild(document.createTextNode(text)); - return; - } - - const source = caseSensitive ? text : text.toLowerCase(); - const needle = caseSensitive ? query : query.toLowerCase(); - let start = 0; - let index = source.indexOf(needle, start); - - if (index === -1) { - container.appendChild(document.createTextNode(text)); - return; - } - - while (index !== -1) { - if (index > start) { - container.appendChild(document.createTextNode(text.slice(start, index))); - } - const mark = el("mark", { class: "filter-highlight" }, [document.createTextNode(text.slice(index, index + query.length))]); - container.appendChild(mark); - start = index + query.length; - index = source.indexOf(needle, start); - } - - if (start < text.length) { - container.appendChild(document.createTextNode(text.slice(start))); - } -} - -export function highlightSearchText(container, text, query, caseSensitive) { - container.textContent = ""; - if (!query || !text) { - container.appendChild(document.createTextNode(text || "")); - return; - } - - const source = caseSensitive ? text : text.toLowerCase(); - const needle = caseSensitive ? query : query.toLowerCase(); - let start = 0; - let index = source.indexOf(needle, start); - - if (index === -1) { - container.appendChild(document.createTextNode(text)); - return; - } - - while (index !== -1) { - if (index > start) { - container.appendChild(document.createTextNode(text.slice(start, index))); - } - const mark = el("mark", { class: "search-highlight" }, [document.createTextNode(text.slice(index, index + query.length))]); - container.appendChild(mark); - start = index + query.length; - index = source.indexOf(needle, start); - } - - if (start < text.length) { - container.appendChild(document.createTextNode(text.slice(start))); - } -} - -export function showWelcome() { - hideProgressBar(); - - // Restore or rebuild the dashboard with tabbed sections - const area = document.getElementById("content-area"); - const home = document.getElementById("dashboard-home"); - - if (area && !home) { - area.innerHTML = ` -
    - -
    - - - - -
    - - -
    -
    -
    ${t('common.loading')}
    -
    -
    -
    - - -
    -
    -
    - - ${t('dashboard.no_bookmarks')} -

    ${t('dashboard.pin_hint')}

    -
    -
    - - -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    - -
    - - -
    -
    -
    - - ${t('dashboard.no_shares')} -

    ${t('dashboard.shared_hint')}

    -
    -
    -
    `; - - // Re-initialize widgets and dashboard tabs - if (typeof DashboardRecentWidget !== "undefined") { - DashboardRecentWidget.init(); - } - initDashboardTabs(); - safeCreateIcons(); - } else if (home) { - // Dashboard already exists, show it with default tab - home.style.display = ""; - // Reset tabs to default - document.querySelectorAll(".dashboard-tab").forEach(t => t.classList.remove("active")); - document.querySelectorAll(".dashboard-panel").forEach(p => p.classList.remove("active")); - const defaultTab = document.querySelector('.dashboard-tab[data-tab="stats"]'); - const defaultPanel = document.getElementById("dashboard-panel-stats"); - if (defaultTab) defaultTab.classList.add("active"); - if (defaultPanel) defaultPanel.classList.add("active"); - } - - // Load all widgets (they handle missing elements gracefully) - if (typeof DashboardStatsWidget !== "undefined") { - DashboardStatsWidget.load(); - } - if (typeof DashboardConflictsWidget !== "undefined") { - DashboardConflictsWidget.load(); - } - if (typeof DashboardRecentWidget !== "undefined") { - DashboardRecentWidget.load(state.selectedContextVault); - } - if (typeof DashboardBookmarkWidget !== "undefined") { - DashboardBookmarkWidget.load(state.selectedContextVault); - } - if (typeof DashboardSharedWidget !== "undefined") { - DashboardSharedWidget.load(); - } - - // Load saved searches sidebar - loadSavedSearches(); -} - -export async function loadSavedSearches() { - const list = document.getElementById("saved-searches-list"); - const empty = document.getElementById("saved-searches-empty"); - if (!list) return; - try { - const searches = await api("/api/saved-searches"); - if (!searches.length) { - list.innerHTML = ""; - if (empty) empty.style.display = ""; - return; - } - if (empty) empty.style.display = "none"; - list.innerHTML = searches.map(s => { - // Detect directory-based saved search (empty query + include_paths) - var isDirSearch = (!s.query || s.query.trim() === '') && s.include_paths; - var displayQuery = isDirSearch ? (s.include_paths || 'Dossier') : escapeHtml(s.query); - // Icon: folder-search for directories, search for regular queries - var typeIcon = isDirSearch - ? '' - : ''; - const badges = []; - if (s.case_sensitive) badges.push('Aa'); - if (s.whole_word) badges.push('wd'); - if (s.regex) badges.push('.*'); - const pathFilters = []; - if (s.include_paths) pathFilters.push(`📥 ${escapeHtml(s.include_paths)}`); - if (s.exclude_paths) pathFilters.push(`📤 ${escapeHtml(s.exclude_paths)}`); - const vaultStr = s.vault && s.vault !== "all" ? `📁 ${escapeHtml(s.vault)}` : ""; - return ` -
    -
    ${displayQuery}
    -
    - ${badges.join("")} ${vaultStr} - ${typeIcon} -
    - ${pathFilters.length ? '
    ' + pathFilters.join(" ") + '
    ' : ""} - -
    - `}).join(""); - // Apply saved filter - _applySavedFilter(); - // Set up filter bar (once) - _initSavedFilter(); - list.querySelectorAll(".saved-search-item").forEach(item => { - item.addEventListener("click", (e) => { - if (e.target.classList.contains("saved-search-delete")) return; - const idx = Array.from(list.children).indexOf(item); - const s = searches[idx]; - if (!s) return; - // Apply the saved search - const input = document.getElementById("search-input"); - if (input) input.value = s.query; - state.searchCaseSensitive = s.case_sensitive || false; - state.searchWholeWord = s.whole_word || false; - state.searchRegex = s.regex || false; - if (typeof _updateToggleUI === "function") _updateToggleUI(); - if (s.include_paths) { - const incl = document.getElementById("search-include-input"); - if (incl) incl.value = s.include_paths; - } - if (s.exclude_paths) { - const excl = document.getElementById("search-exclude-input"); - if (excl) excl.value = s.exclude_paths; - } - // Execute the search — suppress dropdown from appearing - AutocompleteDropdown.hide(); - AutocompleteDropdown._suppressNext = true; - const vault = s.vault || "all"; - if (input) { input.dispatchEvent(new Event("input")); } - clearTimeout(state.searchTimeout); - state.advancedSearchOffset = 0; - performAdvancedSearch(s.query, vault, null); - }); - }); - list.querySelectorAll(".saved-search-delete").forEach(b => b.addEventListener("click", async (e) => { - e.stopPropagation(); - await api(`/api/saved-searches/${b.dataset.id}`, { method: "DELETE" }); - loadSavedSearches(); - })); - safeCreateIcons(); - } catch (err) { /* silently ignore */ } -} - -export function showLoading() { - const area = document.getElementById("content-area"); - area.innerHTML = ` -
    -
    -
    Recherche en cours...
    -
    `; - showProgressBar(); -} - -export function showProgressBar() { - const bar = document.getElementById("search-progress-bar"); - if (bar) bar.classList.add("active"); -} - -export function hideProgressBar() { - const bar = document.getElementById("search-progress-bar"); - if (bar) bar.classList.remove("active"); -} - -function goHome() { - const searchInput = document.getElementById("search-input"); - if (searchInput) searchInput.value = ""; - - document.querySelectorAll(".tree-item.active").forEach((el) => el.classList.remove("active")); - - state.currentVault = null; - state.currentPath = null; - state.showingSource = false; - state.cachedRawSource = null; - - closeMobileSidebar(); - showWelcome(); -} - - -// --------------------------------------------------------------------------- -// SSE Client — IndexUpdateManager -// --------------------------------------------------------------------------- -const IndexUpdateManager = (() => { - let eventSource = null; - let reconnectTimer = null; - let reconnectDelay = 1000; - const MAX_RECONNECT_DELAY = 30000; - let recentEvents = []; - const MAX_RECENT_EVENTS = 20; - let connectionState = "disconnected"; // disconnected | connecting | connected - - function connect() { - if (eventSource) { - eventSource.close(); - } - connectionState = "connecting"; - _updateBadge(); - - eventSource = new EventSource("/api/events"); - - eventSource.addEventListener("connected", (e) => { - connectionState = "connected"; - reconnectDelay = 1000; - _updateBadge(); - }); - - eventSource.addEventListener("index_updated", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_updated", data); - _onIndexUpdated(data); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("index_reloaded", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_reloaded", data); - _onIndexReloaded(data); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("vault_added", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("vault_added", data); - showToast(`Vault "${data.vault}" ajouté (${data.stats.file_count} fichiers)`, "info"); - loadVaults(); - loadTags(); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("vault_removed", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("vault_removed", data); - showToast(`Vault "${data.vault}" supprimé`, "info"); - loadVaults(); - loadTags(); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("index_start", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_start", data); - connectionState = "syncing"; - _updateBadge(); - showToast(`Indexation démarrée (${data.total_vaults} vaults)`, "info"); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("index_progress", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_progress", data); - connectionState = "syncing"; - _updateBadge(); - loadVaults(); - loadTags(); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.addEventListener("index_complete", (e) => { - try { - const data = JSON.parse(e.data); - _addEvent("index_complete", data); - connectionState = "connected"; - _updateBadge(); - showToast(`Indexation terminée (${data.total_files} fichiers)`, "success"); - loadVaults(); - loadTags(); - } catch (err) { - console.error("SSE parse error:", err); - } - }); - - eventSource.onerror = () => { - connectionState = "disconnected"; - _updateBadge(); - eventSource.close(); - eventSource = null; - _scheduleReconnect(); - }; - } - - function _scheduleReconnect() { - if (reconnectTimer) clearTimeout(reconnectTimer); - reconnectTimer = setTimeout(() => { - reconnectDelay = Math.min(reconnectDelay * 2, MAX_RECONNECT_DELAY); - connect(); - }, reconnectDelay); - } - - function _addEvent(type, data) { - recentEvents.unshift({ - type, - data, - timestamp: new Date().toISOString(), - }); - if (recentEvents.length > MAX_RECENT_EVENTS) { - recentEvents = recentEvents.slice(0, MAX_RECENT_EVENTS); - } - } - - async function _onIndexUpdated(data) { - // Brief syncing state - connectionState = "syncing"; - _updateBadge(); - - const n = data.total_changes || 0; - const vaults = (data.vaults || []).join(", "); - // Toast removed: silent auto-indexing — no notification needed - - // Refresh sidebar and tags if affected vault matches current context - const affectsCurrentVault = state.selectedContextVault === "all" || (data.vaults || []).includes(state.selectedContextVault); - if (affectsCurrentVault) { - try { - await Promise.all([refreshSidebarTreePreservingState(), refreshTagsForContext()]); - // Refresh current file if it was updated - if (state.currentVault && state.currentPath) { - const changed = (data.changes || []).some((c) => c.vault === state.currentVault && c.path === state.currentPath); - if (changed) { - openFile(state.currentVault, state.currentPath); - } - } - } catch (err) { - console.error("Error refreshing after index update:", err); - } - } - - // Refresh recent tab if it is active - if (state.activeSidebarTab === "recent") { - const vaultFilter = document.getElementById("recent-vault-filter"); - loadRecentFiles(vaultFilter ? vaultFilter.value || null : null); - } - - setTimeout(() => { - connectionState = "connected"; - _updateBadge(); - }, 1500); - } - - async function _onIndexReloaded(data) { - connectionState = "syncing"; - _updateBadge(); - showToast(t("sync.index_reloaded"), "info"); - try { - await Promise.all([loadVaults(), loadTags()]); - } catch (err) { - console.error("Error refreshing after full reload:", err); - } - setTimeout(() => { - connectionState = "connected"; - _updateBadge(); - }, 1500); - } - - function _updateBadge() { - const badge = document.getElementById("sync-badge"); - if (!badge) return; - badge.className = "sync-badge sync-badge--" + connectionState; - const labels = { - disconnected: "Déconnecté", - connecting: "Connexion...", - connected: "Synchronisé", - syncing: t("viewer.syncing"), - }; - badge.title = labels[connectionState] || connectionState; - } - - function disconnect() { - if (eventSource) { - eventSource.close(); - eventSource = null; - } - if (reconnectTimer) { - clearTimeout(reconnectTimer); - reconnectTimer = null; - } - connectionState = "disconnected"; - _updateBadge(); - } - - function getState() { - return connectionState; - } - - function getRecentEvents() { - return recentEvents; - } - - return { connect, disconnect, getState, getRecentEvents }; -})(); - -function initSyncStatus() { - const badge = document.getElementById("sync-badge"); - if (!badge) return; - - badge.addEventListener("click", (e) => { - e.stopPropagation(); - toggleSyncPanel(); - }); - - IndexUpdateManager.connect(); -} - -function toggleSyncPanel() { - let panel = document.getElementById("sync-panel"); - if (panel) { - panel.remove(); - return; - } - // Auto reconnect if disconnected when user opens the panel - if (IndexUpdateManager.getState() === "disconnected") { - IndexUpdateManager.connect(); - } - panel = document.createElement("div"); - panel.id = "sync-panel"; - panel.className = "sync-panel"; - _renderSyncPanel(panel); - document.body.appendChild(panel); - - // Close on outside click - setTimeout(() => { - document.addEventListener("click", _closeSyncPanelOutside, { once: true }); - }, 0); -} - -function _closeSyncPanelOutside(e) { - const panel = document.getElementById("sync-panel"); - if (panel && !panel.contains(e.target) && e.target.id !== "sync-badge") { - panel.remove(); - } -} - -function _renderSyncPanel(panel) { - const state = IndexUpdateManager.getState(); - const events = IndexUpdateManager.getRecentEvents(); - - const stateLabels = { - disconnected: "Déconnecté", - connecting: "Connexion...", - connected: "Connecté", - syncing: "Synchronisation...", - }; - - let html = `
    - Synchronisation - ${stateLabels[state] || state} -
    `; - - if (events.length === 0) { - html += `
    Aucun événement récent
    `; - } else { - html += `
    `; - events.slice(0, 10).forEach((ev) => { - const time = new Date(ev.timestamp).toLocaleTimeString(); - const typeLabels = { - index_updated: t("viewer.index_updated"), - index_reloaded: "Rechargement", - vault_added: t("sync.vault_added_label"), - vault_removed: t("sync.vault_removed_label"), - index_start: t("viewer.index_start"), - index_progress: t("sync.vault_indexed_label"), - index_complete: "Indexation tech.", - }; - const label = typeLabels[ev.type] || ev.type; - let detail = ev.data.vaults ? ev.data.vaults.join(", ") : ev.data.vault || ""; - if (ev.type === "index_start") detail = `${ev.data.total_vaults} vaults à traiter`; - if (ev.type === "index_progress") detail = `${ev.data.vault} (${ev.data.files} fichiers)`; - if (ev.type === "index_complete" && ev.data.total_files !== undefined) detail = `${ev.data.total_files} fichiers total`; - html += `
    - ${label} - ${detail} - ${time} -
    `; - }); - html += `
    `; - } -} - -// ── Saved searches filter ── -var _savedFilterType = 'all'; -var _savedFilterInitDone = false; - -function _initSavedFilter() { - if (_savedFilterInitDone) return; - var bar = document.getElementById('saved-filter-bar'); - if (!bar) return; - bar.querySelectorAll('.saved-filter-pill').forEach(function(btn) { - btn.addEventListener('click', function() { - bar.querySelectorAll('.saved-filter-pill').forEach(function(b) { b.classList.remove('active'); }); - btn.classList.add('active'); - _savedFilterType = btn.dataset.filter; - _applySavedFilter(); - }); - }); - _savedFilterInitDone = true; -} - -function _applySavedFilter() { - var items = document.querySelectorAll('.saved-search-item'); - var hasVisible = false; - items.forEach(function(item) { - var type = item.dataset.type; - var show = _savedFilterType === 'all' || type === _savedFilterType; - item.style.display = show ? '' : 'none'; - if (show) hasVisible = true; - }); - // Show/hide empty state - var empty = document.getElementById('saved-searches-empty'); - if (empty) empty.style.display = hasVisible ? 'none' : ''; -} - - diff --git a/desktop/frontend-static/locales/en.json b/desktop/frontend-static/locales/en.json deleted file mode 100644 index 5e5fbeb..0000000 --- a/desktop/frontend-static/locales/en.json +++ /dev/null @@ -1,1499 +0,0 @@ -{ - "_meta": { - "locale": "en", - "name": "English" - }, - "about.api_version": "API version", - "about.backend": "Backend", - "about.browser": "Browser", - "about.built_with": "Built with", - "about.editor": "Editor", - "about.file_watcher": "File watching", - "about.files": "Files", - "about.files_indexed": "Indexed files", - "about.footer": "Made with ☕, 🍕 and a few accidental git push --force.", - "about.frontend": "Frontend", - "about.fun_quote": "\"No LLM was harmed during this development.\"", - "about.git": "Git : —", - "about.icons": "Icons", - "about.joke_0": "0 known bugs. The others are shy.", - "about.joke_1": "Compiles on the first try. (Except Monday mornings.)", - "about.joke_2": "Written by a human. Probably.", - "about.joke_3": "No LLMs were harmed during this development.", - "about.joke_4": "When it works, we call it a feature.", - "about.joke_5": "CSS: 90% of dev time, 10% of the code.", - "about.joke_6": "Dark mode active since the project's birth.", - "about.joke_7": "Works on my machine™", - "about.joke_8": "Technically, everything is an edge case.", - "about.joke_9": "The CSS for this panel took longer than the backend.", - "about.language": "Language", - "about.last_delivery": "Last delivery : June 2026", - "about.made_with": "Made with ☕, 🎧 and a few accidental git push --force.", - "about.markdown_renderer": "Markdown rendering", - "about.name": "Name", - "about.platform": "Platform", - "about.section_app": "Application", - "about.section_components": "Components", - "about.section_env": "Environment", - "about.status": "Status", - "about.subtitle": "Your Obsidian notes, simply accessible.", - "about.syntax_highlight": "Syntax highlighting", - "about.tagline": "Your Obsidian notes,
    simply accessible.", - "about.tests": "Tests", - "about.vaults_configured": "Configured vaults", - "about.version": "Version", - "admin.close": "Close", - "admin.col_actions": "Actions", - "admin.col_last_login": "Last login", - "admin.col_role": "Role", - "admin.col_status": "Status", - "admin.col_user": "User", - "admin.col_vaults": "Vaults", - "admin.new_user": "+ New user", - "admin.title": "Administration — Users", - "ai.casual": "Casual tone", - "ai.completion_added": "AI: completion added", - "ai.continue": "Continue", - "ai.custom_rewrite": "Custom rewrite", - "ai.done": "AI: text processed", - "ai.edit": "Edit", - "ai.error_invalid_key": "Invalid API key", - "ai.explain": "Explain", - "ai.fix_spelling": "Fix spelling", - "ai.frontmatter": "Generate frontmatter", - "ai.generate": "Generate", - "ai.hint_add_details": "Adds details", - "ai.hint_edit_selection": "Modifies the selected text", - "ai.hint_generate": "Generates content from the selection", - "ai.hint_improve": "Improves text quality", - "ai.hint_translate": "Translates the selected text", - "ai.improve": "Improve", - "ai.inline_completion_title": "AI Inline Completion (Ctrl+J) — Auto-complete text", - "ai.invalid_api_key": "AI: invalid API key. Check DEEPSEEK_API_KEY in .env", - "ai.longer": "Longer", - "ai.no_api_key": "No API key configured", - "ai.not_configured": "⚠️ AI not configured — add DEEPSEEK_API_KEY, OPENROUTER_API_KEY or GEMINI_API_KEY in .env", - "ai.processing": "⏳ AI: processing...", - "ai.professional": "Professional tone", - "ai.quota_exceeded": "AI: quota exceeded or payment required", - "ai.rewrite": "💬 Rewrite", - "ai.rewrite_done": "AI: text rewritten", - "ai.rewrite_prompt": "Rewrite instruction:", - "ai.rewrite_title": "Rewrite text according to your instructions", - "ai.select_text": "AI: select text to process", - "ai.shorter": "Shorter", - "ai.simplify": "Simplify", - "ai.summarize": "Summarize", - "ai.text_processed": "AI: text processed ✓", - "ai.text_rewritten": "AI: text rewritten", - "ai.to_canvas": "Convert to Canvas", - "ai.to_list": "Convert to list", - "ai.to_table": "Convert to table", - "ai.toolbar_edit": "Edit", - "ai.toolbar_generate": "Generate", - "ai.toolbar_rewrite": "Rewrite", - "ai.toolbar_tone": "Tone", - "ai.toolbar_toolbox": "Toolbox", - "ai.toolbar_translate": "Translate", - "ai.toolbox": "🧰 Toolbox", - "ai.translate_to": "Translate to {lang}", - "auth.cannot_delete_self": "Cannot delete your own account", - "auth.logged_out": "Signed out", - "auth.login_button": "Sign in", - "auth.login_error": "Invalid credentials", - "auth.login_title": "Secure access to your vaults", - "auth.logout_title": "Sign out", - "auth.network_error": "Network error — check your connection", - "auth.new_password": "New password (empty = unchanged)", - "auth.password": "Password", - "auth.password_min": "Min. 8 characters", - "auth.remember_me": "Remember me (30 days)", - "auth.session_expired": "Session expired, please sign in again", - "auth.user_deleted": "User deleted", - "auth.username": "Username", - "auto.0257e77f": "🧰 Toolbox ▾", - "auto.033a9ddf": "Default model", - "auto.03a6e5b1": "The operators used are displayed as", - "auto.13c3ee2c": "Search and autocomplete", - "auto.13eb7a51": "AI: invalid API key", - "auto.14c75ac6": "Select desired events", - "auto.195a8e44": "Create directory", - "auto.1a54bd69": "Combined example", - "auto.1a8a8118": "Drag and drop", - "auto.1abf6661": "The path displayed above the content is", - "auto.1d3330cc": "No automatic retry on failure", - "auto.1d46301c": "Line numbers", - "auto.1efbbc9a": "Editing with CodeMirror 6", - "auto.209c5490": "The top bar contains the essential elements:", - "auto.272dd29a": "Supported providers", - "auto.27a2f7c1": "ObsiGate supports opening multiple files simultaneously in tabs.", - "auto.28bf6aab": "Security: HMAC-SHA256 signature", - "auto.2a5af19b": "The workflow triggers automatically", - "auto.2bc24d2e": "All sensitive operations are logged", - "auto.2bc66bab": "Directory creation via API", - "auto.337d8626": "Light/dark theme", - "auto.37561472": "🛡️ Security", - "auto.396d0dd8": "The AI toolbar appears below the title", - "auto.3be698f6": "Favor operators", - "auto.404c8f1c": "Autocomplete helps you quickly find", - "auto.41d7c6af": "Dedicated directory", - "auto.460b8298": "Data", - "auto.4bc1f00a": "Use operators to refine your", - "auto.4c908ade": "Click a vault to open it and see its", - "auto.4d281c6c": "AI: text processed ✓", - "auto.4dfa6a25": "No vault filtering — a webhook listens to", - "auto.4fa5d7c2": "Quick editing", - "auto.559ef1da": "Recommended workflow", - "auto.598a0ca7": "Tracked events", - "auto.5a486420": "Delete directory", - "auto.5d4a2516": "Open a file in Edit mode (✏️ button", - "auto.5d936af6": "Generated regex", - "auto.62c3d50d": "💬 Rewrite", - "auto.678711b5": "Select a context", - "auto.695d9e47": "CodeMirror 6 Editor", - "auto.6c166d35": "ObsiGate is your web gateway to your Obsidian vaults. Access, browse, and search all your notes from any device via a modern and responsive interface.", - "auto.72e515fa": "Access control by vault", - "auto.753d30a8": "Open a file to see it", - "auto.774dbd63": "The Command Palette allows quick keyboard access to all ObsiGate functions. Use it to open files, execute commands, and navigate without touching the mouse.", - "auto.79f6e1dd": "Multi-window", - "auto.7c9cdc3c": "Check the events to listen to", - "auto.7e13c97a": "These settings apply immediately", - "auto.83a0efdf": "Reindexing", - "auto.9122fd5c": "Advanced configuration", - "auto.98c547ea": "do not trigger", - "auto.a05514cb": "Creation via API or palette", - "auto.a105a2d9": "Edit ▾", - "auto.a131dfab": "CodeMirror Editor", - "auto.a232672b": "Deployment", - "auto.a3319169": "📦 About", - "auto.aa8ca265": "The view uses the Barnes-Hut algorithm to calculate the layout in O(n log n), ensuring smooth performance even with hundreds of nodes.", - "auto.ab5e6155": "ObsiGate automatically creates backups before", - "auto.aedff644": "Create markdown file", - "auto.b114ed1c": "These settings are saved on the server. Some require a restart or reindexing.", - "auto.b419c2c2": "Python receiver (Flask)", - "auto.b86ba5ea": "Multi-criteria search", - "auto.b893650a": "Edit current file", - "auto.ba768f01": "Supported events", - "auto.c089d968": "Pin files to find them", - "auto.c14b5603": "🎨 Themes", - "auto.c4922a99": "🤖 Artificial Intelligence in the Editor", - "auto.caac40b9": "Choose a visual theme. Each theme offers", - "auto.cd7332c8": "Results include facets to refine", - "auto.ce4eb802": "Generate ▾", - "auto.d33601dc": "Real-time file monitoring via", - "auto.d4d28717": "Trigger", - "auto.e0b8a606": "Define tag patterns to hide from", - "auto.e61598c1": "Share a document to see it", - "auto.ec7260fa": "Supported file types", - "auto.edf89626": "The built-in editor offers:", - "auto.ef8c5f4d": "The built-in editor offers a complete editing experience:", - "auto.f346076a": "✏️ Advanced Editing", - "auto.f5a8c116": "Event", - "auto.f8ba6127": "🗂️ Hidden files", - "auto.fc694490": "Deletion via API or editor", - "backup.delete": "Delete", - "backup.diff": "Compare", - "backup.file_restored": "File restored successfully", - "backup.no_backups": "No backups", - "backup.preview": "Preview", - "backup.purge": "Purge", - "backup.restore": "Restore", - "backup.restore_failed": "Restore failed", - "backup.select_to_restore": "Select a backup to restore", - "backup.timestamp_not_found": "Cannot find backup timestamp", - "backup.title": "Backups", - "backup.version": "Version from {date}", - "backups.delete_confirm": "Delete this backup?", - "backups.empty": "No backups available for this file.", - "backups.hint": "Backups are created automatically before each modification.", - "backups.loading": "Loading backups...", - "backups.purge_file": "Delete ALL backups of", - "backups.purge_vault": "Delete ALL backups from vault", - "backups.restore_confirm": "to the selected backup version?\nThe current version will be saved.", - "backups.title": "Backups", - "button.cancel": "Cancel", - "common.actions": "Actions", - "common.all": "All", - "common.back": "Back", - "common.cancel": "Cancel", - "common.close": "Close", - "common.confirm": "Confirm", - "common.copied": "Copied!", - "common.copy": "Copy", - "common.create": "Create", - "common.delete": "Delete", - "common.download": "Download", - "common.edit": "Edit", - "common.error": "Error", - "common.loading": "Loading...", - "common.move": "Move", - "common.never": "Never", - "common.next": "Next", - "common.no": "No", - "common.none": "None", - "common.ok": "OK", - "common.previous": "Previous", - "common.refresh": "Refresh", - "common.rename": "Rename", - "common.root": "(root)", - "common.save": "Save", - "common.search": "Search", - "common.unknown": "Unknown", - "common.yes": "Yes", - "config.about": "About", - "config.about_error": "Loading error", - "config.about_loading": "Loading...", - "config.add_webhook": "Add", - "config.ai_deepseek_label": "DeepSeek API Key", - "config.ai_default_provider": "Default provider", - "config.ai_gemini_label": "Gemini API Key", - "config.ai_keys": "AI API keys", - "config.ai_keys_desc": "Configure API keys for the AI editor.", - "config.ai_model": "Model", - "config.ai_openrouter_label": "OpenRouter API Key", - "config.api_keys_saved": "API keys saved", - "config.backups": "Backups", - "config.backups_desc": "Manage automatic file backups.", - "config.client_config": "Client config", - "config.create_share": "Create share", - "config.debounce_label": "Debounce delay (ms)", - "config.diagnostics": "Diagnostics", - "config.diagnostics_desc": "Technical information about the server state.", - "config.display_name": "Display name", - "config.error_prefix": "Error", - "config.error_unknown": "Unknown error", - "config.force_reindex": "Force reindex", - "config.hidden_files": "Hidden files", - "config.hidden_files_desc": "Hide files/folders starting with a dot in the interface (they remain indexed and searchable)", - "config.hidden_files_toggle": "Hide hidden files/folders", - "config.hidden_include_label": "Include hidden files", - "config.hidden_whitelist_label": "Whitelist (comma-separated)", - "config.hint_activer_d_sactiver_la_surveillance_automatique_des": "Enable/disable automatic file monitoring", - "config.hint_annuler_la_recherche_apr_s_ce_d_lai_5000_120000_": "Cancel search after this delay (5000-120000)", - "config.hint_contenu_index_par_fichier_10k_1m_r_indexation_requ": "Max content size per file (bytes)", - "config.hint_d_lai_avant_ex_cution_de_la_recherche_100_2000_": "Delay before search execution (100-2000)", - "config.hint_d_lai_avant_traitement_des_changements_group_s_0_5": "Delay before processing grouped changes (0.5-10 seconds)", - "config.hint_entre_5_et_100_fichiers_sauvegarde_sur_le_serveur_": "Between 5 and 100 files (stored on server)", - "config.hint_forcer_le_mode_polling_au_lieu_de_inotify_natif_ut": "Forcer le mode polling au lieu de inotify natif (utile si le mode natif ne fonctionne pas)", - "config.hint_intervalle_de_scrutation_en_mode_polling_1_30_seco": "Intervalle de scrutation en mode polling (1-30 secondes)", - "config.hint_multiplicateur_de_pertinence_pour_les_correspondan": "Multiplicateur de pertinence pour les correspondances dans le titre", - "config.hint_nombre_de_r_sultats_affich_s_par_page_10_200_": "Number of results displayed per page (10-200)", - "config.hint_nombre_max_de_tokens_largis_par_pr_fixe_10_200_": "Max expanded tokens per prefix (10-200)", - "config.hint_nombre_maximum_de_versions_backup_conservees_par_f": "Maximum backup versions kept per file (1-50)", - "config.hint_nombre_minimum_de_caract_res_avant_recherche_1_5_": "Minimum characters before search triggers (1-5)", - "config.hint_threads_d_di_s_la_recherche_1_8_": "Dedicated search threads (1-8)", - "config.just_now": "just now", - "config.lang_hint": "Used by autocomplete and ghost text.", - "config.lang_label": "Preferred language", - "config.link_copied": "Link copied!", - "config.link_created": "Link created!", - "config.logout": "Sign out", - "config.max_backups": "Max backups per file", - "config.max_backups_desc": "Maximum backup versions kept per file (1-50)", - "config.max_backups_label": "Max backups per file", - "config.max_content_hint": "Indexed content per file (10K-1M). Reindex required.", - "config.max_content_label": "Max content size (bytes)", - "config.max_content_size": "Max content size (bytes)", - "config.max_prefix_expansions": "Max prefix expansions", - "config.min_query_label": "Min. query length", - "config.min_query_length": "Min query length", - "config.name_placeholder": "Your name", - "config.no_keys": "No keys to save", - "config.no_restart": "No restart needed", - "config.note": "Note:", - "config.open_new_window": "Open in new window", - "config.prefix_expansions_hint": "Max tokens expanded by prefix (10-200)", - "config.prefix_expansions_label": "Max prefix expansions", - "config.profile": "User profile", - "config.profile_desc": "Personal preferences to customize your ObsiGate experience.", - "config.project_repo": "project repository", - "config.recent_history_count": "Files in history", - "config.recent_history_count_desc": "Between 5 and 100 files (saved on server)", - "config.reindex": "Reindex", - "config.reindex_desc": "Rebuild the search index for all vaults.", - "config.reindex_error": "Reindex error", - "config.reindexing": "Reindexing...", - "config.reset": "Reset", - "config.restart_required": "Restart required", - "config.results_per_page": "Results per page", - "config.results_per_page_label": "Results per page", - "config.save": "Save", - "config.save_ai_keys": "Save keys", - "config.save_backend": "Save server configuration", - "config.save_error": "Save error", - "config.save_hidden": "Save", - "config.saved": "✓ Saved", - "config.saving": "Saving", - "config.search_timeout": "Search timeout (ms)", - "config.search_workers": "Search workers", - "config.search_workers_hint": "Dedicated search threads (1-8)", - "config.search_workers_label": "Search workers", - "config.section_a-propos": "📦 About", - "config.section_about": "About", - "config.section_actions-sur-fichiers": "File actions", - "config.section_activation": "Activation", - "config.section_affichage": "Affichage", - "config.section_ai": "AI API keys", - "config.section_arborescence-des-vaults": "Arborescence des vaults", - "config.section_astuces-et-bonnes-pratiques": "💡 Astuces et bonnes pratiques", - "config.section_audit-log": "Audit log", - "config.section_authentification": "Authentification", - "config.section_autocompletion": "Autocompletion", - "config.section_backend": "🖥️ Backend Settings", - "config.section_backup-automatique": "Backup automatique", - "config.section_backups": "Backups", - "config.section_barre-d-outils-ai": "Barre d'outils AI", - "config.section_breadcrumb-et-repositionnement": "Breadcrumb et repositionnement", - "config.section_cas-d-usage": "Cas d'usage", - "config.section_cas-d-usage-avances": "Advanced use cases", - "config.section_chips-de-filtres-actifs": "Chips de filtres actifs", - "config.section_cles-api-intelligence-artificielle": "🤖 Cles API Intelligence Artificielle", - "config.section_configuration": "Configuration", - "config.section_configuration-avancee": "Advanced configuration", - "config.section_construit-avec": "Construit avec", - "config.section_diag": "Diagnostics", - "config.section_diagnostics": "Diagnostics", - "config.section_editeur-codemirror": "CodeMirror Editor", - "config.section_editeur-codemirror-6": "CodeMirror 6 Editor", - "config.section_edition-avancee": "✏️ Advanced Editing", - "config.section_edition-avec-codemirror-6": "Editing with CodeMirror 6", - "config.section_en-tete": "Header", - "config.section_evenements-supportes": "Supported events", - "config.section_exemples-concrets": "Exemples concrets", - "config.section_facettes-et-tri": "Facettes et tri", - "config.section_fichiers": "📄 Files", - "config.section_filtrage-de-la-sidebar": "Filtrage de la sidebar", - "config.section_filtrage-de-tags": "Filtrage de tags", - "config.section_filtrage-de-tags-template": "Filtrage de tags template", - "config.section_fonctionnalites": "Features", - "config.section_format-du-payload": "Format du payload", - "config.section_gestion-des-onglets": "📑 Gestion des onglets", - "config.section_hidden": "Hidden files", - "config.section_historique-recent-redemarrage-non-requis": "📋 Recent History\n No restart required", - "config.section_indicateurs-visuels": "Indicateurs visuels", - "config.section_intelligence-artificielle-dans-l-editeur": "🤖 AI in the Editor", - "config.section_interaction": "Interaction", - "config.section_interface": "Interface", - "config.section_interface-utilisateur": "🧭 Interface utilisateur", - "config.section_limitations-actuelles": "Limitations actuelles", - "config.section_mode-commandes": "Mode commandes", - "config.section_mode-fichiers": "File mode", - "config.section_navigation": "Navigation", - "config.section_navigation-entre-onglets": "Navigation entre onglets", - "config.section_onglets": "Onglets", - "config.section_operateurs-avances": "Advanced operators", - "config.section_optimisations": "Optimisations", - "config.section_ouverture": "Ouverture", - "config.section_ouverture-d-onglets": "Ouverture d'onglets", - "config.section_palette-de-commandes": "⌨️ Palette de commandes", - "config.section_parametres-backend-redemarrage-requis": "Backend settings\n Restart required", - "config.section_parametres-de-recherche": "Search settings", - "config.section_partage-et-webhooks": "🔗 Partage et Webhooks", - "config.section_partages-publics": "📤 Partages publics", - "config.section_perf": "⚡ Performance", - "config.section_performance": "Performance", - "config.section_personnalisation": "🎨 Personnalisation", - "config.section_profil-utilisateur": "👤 Profil utilisateur", - "config.section_profile": "User profile", - "config.section_protection": "Protection", - "config.section_providers-supportes": "Supported providers", - "config.section_publication-publique": "Publication publique", - "config.section_raccourcis-clavier": "⌨️ Raccourcis clavier", - "config.section_recent": "📜 Recent History", - "config.section_recherche": "🔍 Recherche", - "config.section_recherche-et-autocompletion": "Search and autocompletion", - "config.section_recherche-simple": "Recherche simple", - "config.section_redimensionnement-de-la-sidebar": "Redimensionnement de la sidebar", - "config.section_sauvegarde-automatique": "Sauvegarde automatique", - "config.section_sauvegardes-et-audits": "💾 Sauvegardes et Audits", - "config.section_search": "Search settings", - "config.section_securite": "🛡️ Security", - "config.section_securite-signature-hmac-sha256": "Security: HMAC-SHA256 signature", - "config.section_selection-de-vault": "Vault selection", - "config.section_server": "Server", - "config.section_shares": "📤 Public Shares", - "config.section_sidebar-barre-laterale": "Sidebar", - "config.section_synchronisation-automatique": "Synchronisation automatique", - "config.section_tag-cloud": "Tag cloud", - "config.section_tags": "🏷️ Tag Filtering", - "config.section_tags-inline-vs-frontmatter": "Tags inline vs frontmatter", - "config.section_theme-clair-sombre": "Light/Dark theme", - "config.section_themes": "🎨 Themes", - "config.section_trucs-et-astuces": "Trucs et astuces", - "config.section_types-de-fichiers-supportes": "Supported file types", - "config.section_visualisation": "Visualisation", - "config.section_vue-graphe": "🗺️ Vue Graphe", - "config.section_watcher": "Auto sync", - "config.section_webhooks": "🔗 Webhooks", - "config.section_workflow-recommande": "Recommended workflow", - "config.section_zone-de-contenu": "Zone de contenu", - "config.server_config": "Server config", - "config.settings_saved": "✓ Settings saved", - "config.share_revoked": "Share revoked", - "config.shares": "Public shares", - "config.shares_desc": "Manage public share links for your documents.", - "config.shares_empty": "No active shares", - "config.tag_boost_hint": "Relevance multiplier for tag matches", - "config.tag_boost_label": "Tag boost", - "config.tag_filtering_label": "Tag filtering", - "config.test": "Test", - "config.timeout_label": "Search timeout (ms)", - "config.title": "Settings", - "config.title_boost": "Title boost", - "config.title_boost_hint": "Relevance multiplier for title matches", - "config.title_boost_label": "Title boost", - "config.url_required": "URL required", - "config.watcher_debounce_label": "Debounce (s)", - "config.watcher_enabled_label": "Enable watcher", - "config.watcher_interval_label": "Polling interval (s)", - "config.watcher_polling_label": "Polling mode (fallback)", - "config.webhook_name_placeholder": "Name", - "config.webhook_url_placeholder": "URL", - "config.webhooks": "Webhooks", - "config.webhooks_desc": "HTTP notifications to external services on file changes.", - "config.workers_label": "Search workers", - "confirm.delete_dir": "Delete this folder and all its contents?", - "confirm.delete_dir_named": "Delete \"{path}\" and ALL its contents?", - "confirm.delete_file": "Permanently delete this file?", - "confirm.delete_file_named": "Delete file \"{path}\"?", - "confirm.logout": "Are you sure you want to sign out?", - "conflict.no_conflicts": "No conflicts detected", - "conflict.resolve_conflict": "Keep conflict version", - "conflict.resolve_local": "Keep local version", - "conflict.resolved": "Conflict resolved", - "dashboard.all_vaults": "All vaults", - "dashboard.bookmark_add": "Add to bookmarks", - "dashboard.bookmark_remove": "Remove from bookmarks", - "dashboard.bookmarks": "Bookmarks", - "dashboard.conflict_date": "Conflict of ", - "dashboard.conflict_resolved": "Conflict resolved", - "dashboard.conflicts": "Conflicts", - "dashboard.conflicts_title": "Sync conflicts", - "dashboard.copy_btn": "Copy", - "dashboard.count_files": "file", - "dashboard.count_files_plural": "files", - "dashboard.ctrl_hover_tip": "Hover over a document with Ctrl for a quick preview. Click Forge in the toolbar for the advanced editor.", - "dashboard.day_ago": "{n} d ago", - "dashboard.error_prefix": "Error: ", - "dashboard.expires": "Expires {date}", - "dashboard.hide": "Hide", - "dashboard.hour_ago": "{n} h ago", - "dashboard.just_now": "just now", - "dashboard.keep_conflict": "Keep conflict", - "dashboard.keep_original": "Keep original", - "dashboard.load_error": "Loading error", - "dashboard.loading": "Loading...", - "dashboard.min_ago": "{n} min ago", - "dashboard.no_bookmarks": "No bookmarks", - "dashboard.no_conflicts": "No conflicts", - "dashboard.no_recent": "No recent files", - "dashboard.no_shares": "No shared documents", - "dashboard.open_btn": "Open", - "dashboard.pin_error": "Pin error", - "dashboard.pin_hint": "Pin files to find them here.", - "dashboard.quick_help": "Quick Help", - "dashboard.recent": "Recent", - "dashboard.recent_hint": "Open a file to see it appear here", - "dashboard.shared_hint": "Share a document to see it appear here", - "dashboard.shares": "Shares", - "dashboard.show": "Show", - "dashboard.size_bytes": " B", - "dashboard.size_gb": " GB", - "dashboard.size_kb": " KB", - "dashboard.size_mb": " MB", - "dashboard.stats": "Statistics", - "dashboard.stats_files": "Files", - "dashboard.stats_size": "Total size", - "dashboard.stats_tags": "Unique tags", - "dashboard.stats_vaults": "Vaults", - "dashboard.tab_recent": "Recent", - "dashboard.tab_shared": "Shared", - "dashboard.tab_stats": "Statistics", - "dashboard.total_files": "Total files", - "dashboard.total_size": "Total size", - "dashboard.total_tags": "Unique tags", - "dashboard.vaults_count": "Vaults", - "dashboard.views": "{count} view(s)", - "dashboard.welcome": "Welcome to ObsiGate", - "dashboard.zero_files": "0 files", - "dragdrop.cross_vault_unsupported": "Cross-vault moves are not supported", - "dragdrop.move_failed": "Move failed", - "editor.cancel": "Cancel", - "editor.close": "Close", - "editor.delete_error": "Delete error", - "editor.edit": "Edit current file", - "editor.edit_current_desc": "Open current file in editor", - "editor.find": "Find in file...", - "editor.find_case": "Case sensitive", - "editor.find_regex": "Regex", - "editor.find_whole": "Whole word", - "editor.forge_close_editor": "Close editor / modal", - "editor.forge_help": "Forge editor help", - "editor.no_results": "No results", - "editor.replace": "Replace", - "editor.save": "Save", - "editor.save_error": "Save error", - "editor.saved": "Saved ✓", - "editor.unsaved": "Unsaved changes", - "error.initialization": "Initialization error", - "file.copy_path": "Copy path", - "file.delete": "Delete", - "file.graph_view": "Graph view", - "file.new_file": "New file", - "file.new_folder": "New folder", - "file.properties": "Properties", - "file.rename": "Rename", - "forge.popout": "Open in new window", - "forge.popout_label": "pop-out", - "forge.title_placeholder": "Title...", - "graph.back": "Back", - "graph.btn_directory": "📁 Directory", - "graph.btn_full": "🌐 All", - "graph.cache_label": "(cached)", - "graph.category": "📂 Category", - "graph.click_to_open": "click to open", - "graph.ctrl_hover_preview": "Ctrl+hover = full preview", - "graph.ctrl_hover_preview_short": "Ctrl+hover = preview", - "graph.depth": "Depth", - "graph.depth_label": "depth={depth}", - "graph.edges_count": "{count} links", - "graph.error_loading": "Loading error", - "graph.export_png": "Export PNG", - "graph.favorites": "Favorites", - "graph.filter_tag": "Filter by tag", - "graph.filter_type": "Filter by type", - "graph.focus_mode": "Focus mode", - "graph.forward": "Forward", - "graph.fullscreen": "Full screen", - "graph.loading": "Building graph...", - "graph.nodes_count": "{count} nodes", - "graph.parent": "Parent", - "graph.published": "Published", - "graph.published_badge": "✅ published", - "graph.scope_directory": "Directory", - "graph.scope_full": "Full vault", - "graph.title": "Graph View — {vault}{path}", - "graph.type_directory": "Directory", - "graph.type_file": "File", - "graph.type_markdown": "Markdown", - "header.admin_panel": "Administration", - "header.config": "Settings", - "header.help": "Help", - "header.install_app": "Install app", - "header.logo": "ObsiGate", - "header.logout": "Sign out", - "header.menu_about": "About", - "header.menu_about_desc": "Version, credits & info", - "header.menu_admin": "Administration", - "header.menu_admin_desc": "Manage users", - "header.menu_config": "Settings", - "header.menu_config_desc": "Application settings", - "header.menu_help": "User guide", - "header.menu_help_desc": "Open help", - "header.menu_logout": "Sign out", - "header.menu_logout_desc": "End session", - "header.menu_profile": "Profile", - "header.menu_profile_desc": "Language & preferences", - "header.menu_theme": "Theme", - "header.menu_theme_light": "Light", - "header.menu_toggle": "Menu", - "header.profile": "Profile", - "header.quick_help": "Quick Help", - "header.refresh": "Refresh", - "header.search_placeholder": "Search all vaults...", - "header.sidebar_toggle": "Toggle sidebar", - "header.sync_status": "Sync", - "help.00b9572b": "Results ranked by TF-IDF relevance", - "help.04df1506": "Global search with autocomplete", - "help.065f53ee": "Silent auto-save after 2s of inactivity", - "help.085ec31f": "Quick select at the top of the Vault tab", - "help.096367af": "Visual indicators", - "help.170a6982": "Horizontal display with the file name", - "help.229fd3e2": "Discord notification", - "help.2507242f": "🏷️ Tags", - "help.29afa01d": "🪝 Webhooks", - "help.2a2e5b0f": "⌨️ Keyboard shortcuts", - "help.2a92203f": "Tips and tricks", - "help.2c03a7ba": "Inline vs frontmatter tags", - "help.2dad2bfd": "Automatic save", - "help.381abec7": "Current limitations", - "help.3cf370b1": "Type a file name to find it quickly. The search uses the /api/suggest API for instant suggestions. Press Enter to open the selected file.", - "help.40dd7e38": "Test with curl", - "help.4de7e318": "The 50 most recent searches (localStorage)", - "help.550b0240": "Concrete examples", - "help.5ab8c78d": "Stay open until manually closed", - "help.5d0fbb81": "Workers, TF-IDF boosts, prefix expansions", - "help.5f87ea79": "Tag cloud", - "help.61ee5a22": "Interaction", - "help.62308f96": "Ctrl+Shift+Space: File palette (search by title)", - "help.62549eca": "💾 Backups and Audits", - "help.63f024d4": "Template tag filtering", - "help.686f8313": "💡 Tips and best practices", - "help.6a5ddef2": "Tags adapt to the selected vault", - "help.6ae5342c": "Index stats, memory, search engine", - "help.6b88a375": "Debounce delay, results per page, timeout", - "help.6b8fc728": "↑/↓ to navigate, Enter to select", - "help.6d547397": "Tab: Toggle between file mode and command mode", - "help.6e940dac": "Click the sidebar icon in the header", - "help.733f0559": "🗺️ Navigation", - "help.77f4f06e": "Payload format", - "help.7bcbb2e3": "Sidebar resizing", - "help.7db70e27": "Copy, Source, Download, Edit, Open in new window", - "help.83f1d9ca": "Protection", - "help.86e3825d": "🎨 Customization", - "help.8717768b": "Node metadata (tags, links, path)", - "help.89bd3c4c": "Only shows nodes with a specific tag", - "help.8c5341e0": "📑 Tab management", - "help.8c65b2f2": "🔗 Sharing and Webhooks", - "help.8caed987": "Display", - "help.9c7a0a8d": "🗺️ Graph View", - "help.9edeaa11": "Controls exploration depth (0-3)", - "help.9f78b3ec": "Easier navigation in long files", - "help.a4a4e21b": "\"×\" button to reset the filter", - "help.a579cf4d": "Preview note content without navigating", - "help.a648c49e": "Facets and sorting", - "help.ab2c4150": "Files (squares) and folders (circles) with icons", - "help.about": "About", - "help.access": "Access", - "help.action_buttons": "Action buttons", - "help.actions_available": "Buttons available above the content:", - "help.actions_detail": "Buttons available above the content:", - "help.activation": "Activation", - "help.active_filter_chips": "Active filter chips", - "help.active_tab": "Active tab", - "help.add_remove": "Add/Remove", - "help.adf30d78": "🔍 Search", - "help.advanced_operators": "Advanced operators", - "help.advanced_use_cases": "Advanced use cases", - "help.ai_completes": "Completes", - "help.ai_features": "Edit, tone, translate, generate and tools via AI.", - "help.ai_flash_green": "flashes green", - "help.ai_tone_casual": "Casual tone", - "help.all_vaults": "All vaults", - "help.atomic_writes": "Atomic writes", - "help.audit_log": "Audit log", - "help.auto_save": "Automatic save", - "help.auto_scroll": "Auto-scroll", - "help.autocomplete": "Autocomplete", - "help.b6619ac9": "Ctrl+Alt+Space: Command palette (action list)", - "help.backlinks_panel": "Backlinks panel", - "help.backup_auto": "Auto backup", - "help.before_write": "Before write", - "help.breadcrumb": "Breadcrumb", - "help.breadcrumb_clickable": "Clickable breadcrumb", - "help.breadcrumb_reposition": "Breadcrumb and repositioning", - "help.c017944b": "📄 Files", - "help.c48fb18a": "Authentication", - "help.c8532869": "Completion, rewrite, translation (see", - "help.case_sensitive": "Case-sensitive", - "help.cf8615b1": "Visualization", - "help.ci_cd": "CI/CD automation", - "help.clear": "Clear", - "help.clear_search": "Clear", - "help.click_segment": "Click a segment", - "help.click_tab": "Click a tab", - "help.click_vault": "Click the vault", - "help.clickable": "Clickable", - "help.close_help": "Close help", - "help.close_tab_x": "✕ button", - "help.code_preview": "Code + Preview", - "help.command_palette": "Command palette", - "help.configuration": "Settings", - "help.content_area": "Content area", - "help.content_shows": "The main area displays:", - "help.context_actions": "File actions", - "help.context_menu": "Context menu (right click)", - "help.copy_path": "Copy path", - "help.d186a19e": "The \"Recent\" tab in the sidebar lists your", - "help.d1ea1dc6": "n8n / Make (no-code)", - "help.d5c977ac": "Code blocks adapt to the theme", - "help.dark": "Dark", - "help.dashboard": "Dashboard statistics", - "help.delete": "Delete", - "help.desc_00b9572b": ":\n Results ranked by TF-IDF relevance", - "help.desc_04493800": ": 64\n caractères hexadécimaux, impossible à\n deviner", - "help.desc_065f53ee": ": Silent auto-save after 2s of inactivity, green confirmation flash", - "help.desc_071da87a": "Lecture seule : La vue publique n'affiche que le contenu sans édition", - "help.desc_0739c6a9": "Images : Support complet des syntaxes Obsidian", - "help.desc_085ec31f": ":\n Quick select at the top of the Vault tabs", - "help.desc_0f9a1e5b": "Use the sidebar to navigate between vaults and folders.", - "help.desc_11cf9e8a": "Éditer ▾ — Menu de modification du texte sélectionné : 🪄 Improve writing : Améliore la qualité, la clarté et le flux du texte", - "help.desc_13d206d4": "Transforms textual data into a readable Markdown table — ideal for comparisons and structured information.", - "help.desc_13d90039": "ObsiGate generates a shareable, read-only link.", - "help.desc_1577912b": "Rate limiting : 10 tentatives / 15 min par IP + verrouillage compte", - "help.desc_170a6982": "Converts a sentence or paragraph into a structured bullet-point list.", - "help.desc_188bc423": "Pour plus d'informations, consultez le dépôt du projet.", - "help.desc_19cf5730": "Rotation", - "help.desc_19cfa369": "Documents are automatically saved after each modification. A status indicator in the editor header confirms: Saved or Saving….", - "help.desc_1a04ae18": "Use the sidebar to navigate between vaults and folders.", - "help.desc_1ba39cc4": "Update", - "help.desc_1c130d89": "Translate — translates selected text to target language", - "help.desc_1f11691c": "Atomic writes : Écriture via fichier temporaire + renommage atomique", - "help.desc_2349271d": "Automatisation CI/CD : Déclencher un build quand une note de procédure est mise à jour", - "help.desc_26f81732": "Édition rapide : Ouvrez l'éditeur, modifiez, sauvegardez", - "help.desc_287be69c": "Vault", - "help.desc_2c220763": "Edit config.yaml to customize behavior", - "help.desc_2f2c16b5": "Publish", - "help.desc_31e7253b": "Each backup", - "help.desc_32e3d66d": "En cas d'erreur de clé API : AI: clé API invalide", - "help.desc_39979e71": "Vault", - "help.desc_39e97b2f": "Note: the file_modified event is reserved for future use and is not currently emitted.", - "help.desc_3ace259e": "— Inline completion", - "help.desc_3c4711b8": "Edit config.yaml to customize behavior", - "help.desc_3d4e9189": "Simplifies the language for easier reading — replaces complex terms and shortens long sentences.", - "help.desc_3da1896a": "Each webhook receives a POST with event details", - "help.desc_3db2812f": "X-ObsiGate-Signature: sha256=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 Pour vérifier côté récepteur : calculez HMAC-SHA256(corps_brut, secret) et comparez. Le header X-ObsiGate-Event contient aussi le type d'événement pour un routage rapide.", - "help.desc_40c92863": "Exploration par tags : Cliquez sur un tag dans une note pour voir toutes les notes similaires", - "help.desc_42a81347": "Casual and friendly tone — ideal for informal communication or social media.", - "help.desc_443b76b5": "Wikilinks : Naviguez entre notes comme dans Obsidian", - "help.desc_47e1e10f": "Générer ▾ — Génère du contenu à partir de la sélection : ℹ️ Explain this : Explique le texte sélectionné de façon claire", - "help.desc_4de7e318": ": The 50 most recent searches (localStorage)", - "help.desc_50a33a05": "Generates YAML frontmatter for the current document (title, date, tags based on content).", - "help.desc_5374685a": "Mobile-friendly : Utilisez le bouton hamburger sur mobile", - "help.desc_5396ed9e": "Profitez de l'historique : Réutilisez vos recherches fréquentes", - "help.desc_53bfaeca": "Navigation", - "help.desc_5524e921": "Adapts the tone for a formal, business context — suitable for reports, emails, and official documents.", - "help.desc_555e0305": "Pour changer de provider par défaut : AI_DEFAULT_PROVIDER=openrouter", - "help.desc_56760d7f": "Each webhook receives a POST with a JSON body containing the event type, vault, path, and a timestamp.", - "help.desc_58d2326f": "Use the sidebar to navigate between vaults and folders.", - "help.desc_599f3242": "Log", - "help.desc_5a53de53": "📏 Make shorter : Rend le texte plus concis tout en préservant l'information", - "help.desc_5ab8c78d": ":\n Stay open until manually closed", - "help.desc_5d0fbb81": ":\n Workers, TF-IDF boosts, prefix expansions", - "help.desc_5e9a7fd9": "In the", - "help.desc_5fc28b7d": "Created", - "help.desc_625112fd": "Sélectionnez un contexte : Choisissez un vault pour réduire le bruit", - "help.desc_660051b0": "Audit externe : Logger toutes les modifications dans une base de données externe", - "help.desc_664b1d09": "Use the sidebar to navigate between vaults and folders.", - "help.desc_68c2b170": "Rotation : Rotation automatique à 10 Mo", - "help.desc_6902f20d": "Favorisez les opérateurs : tag: et vault: accélèrent la recherche", - "help.desc_698d92ec": "Gestion de l'espace : Réduisez les sections Vaults/Tags selon vos besoins", - "help.desc_6a5ddef2": "Explains the selected passage with an educational style — defines technical terms and adds context.", - "help.desc_6a80241e": "Width", - "help.desc_6ae5342c": "Index stats", - "help.desc_6b649b1e": ": Highlighted in accent color", - "help.desc_6b88a375": ":\n Debounce delay, results per page, timeout", - "help.desc_6b8fc728": "Select", - "help.desc_6bc48f59": "Each webhook receives a POST with event details", - "help.desc_6caffeed": " — Conversion tools:", - "help.desc_6d68fbc9": "Create markdown file: Create a new .md file", - "help.desc_6ebebdfd": ": Each operator type has its color", - "help.desc_6f7c5889": "Alert", - "help.desc_71eeb16a": ":\n Réutilisez vos recherches fréquentes", - "help.desc_723ed8db": "Non-root Docker : Conteneur tourne avec UID 1000", - "help.desc_752789ab": "File", - "help.desc_759926ee": "Relaxed and friendly tone — ideal for informal communication or social media.", - "help.desc_7671e56a": "Avant écriture : Sauvegarde du contenu original dans .obsigate-backup/", - "help.desc_7708f226": "ObsiGate uses JWT tokens signed with a secret key defined in the .env file.", - "help.desc_7819b56f": "Each webhook receives a POST with event details", - "help.desc_7ab5be50": "Translates the selected text into the target language.", - "help.desc_7b45490b": "Each webhook receives a POST with event details", - "help.desc_7e86626c": "ObsiGate generates a shareable, read-only link. Anyone with the link can view the file content.", - "help.desc_7f1d0512": "Path traversal : Validation des chemins contre les attaques ../", - "help.desc_7ff2fa21": "Pendant une requête AI, un toast ⏳ AI: traitement en cours... s'affiche", - "help.desc_803161e5": "The toolbar contains the following buttons:", - "help.desc_828db5da": ": Both types are combined", - "help.desc_858681a1": ":\n Durée de vie en heures", - "help.desc_85effb89": "Each webhook receives a POST with event details", - "help.desc_8717768b": ": Node metadata (tags, links, path)", - "help.desc_87b348c3": "Recherche multi-critères : tag:docker tag:linux vault:IT nginx", - "help.desc_89a8f5de": "Example: publish a blog post when a file is marked publish: true.", - "help.desc_89bd3c4c": ": Only shows nodes with a specific tag", - "help.desc_8f0bffe3": "JWT tokens", - "help.desc_9186a3a3": "Explorez l'arborescence : Naviguez dans les dossiers", - "help.desc_93902d18": "Utilisez les tags : Filtrez par tags pour affiner", - "help.desc_9846fc07": "In the", - "help.desc_985d759b": "Token unique : 64 caractères hexadécimaux, impossible à deviner", - "help.desc_991307d6": " — Generate content from the selection:", - "help.desc_995a711f": ": Opens the CodeMirror editor", - "help.desc_99c6f0ec": "Share files with a read-only link", - "help.desc_9cb5974c": ": Ouvrez\n plusieurs notes dans des onglets séparés", - "help.desc_9d0e39d0": "Headers CSP : Content-Security-Policy, X-Frame-Options, XSS-Protection", - "help.desc_9edeaa11": ": Controls exploration depth (0-3)", - "help.desc_9f321d1e": "Backup", - "help.desc_9f78b3ec": ":\n Easier navigation in long files", - "help.desc_9fec424d": "Adapts the tone for a professional context — reports, emails, official documents.", - "help.desc_a0ec890a": " — Selected text modification menu:", - "help.desc_a13f7f2c": "Une fois terminé, AI: texte traité ✓ confirme le succès", - "help.desc_a4a4e21b": ": \"×\" button to reset the filter", - "help.desc_a52fc3b1": ": Downloads the file", - "help.desc_a579cf4d": ": Preview note content without navigating", - "help.desc_a601f22e": "Each webhook receives a POST with event details", - "help.desc_a69804cd": "Répertoire dédié : .obsigate-backup/ dans le répertoire de la vault", - "help.desc_a6cb3b26": "🔤 Fix spelling & grammar : Corrige les fautes d'orthographe et de grammaire", - "help.desc_a974f7a6": "Journal : Fichier data/audit.log au format JSON lines", - "help.desc_a9c2c520": "Webhooks automatically notify external services when files or directories change. Configure a URL to receive HTTP POST requests.", - "help.desc_a9db82b5": ": Centers the view on a specific node", - "help.desc_ab2c4150": ": Files (squares) and folders (circles) with icons", - "help.desc_action_buttons": "Copy, Source, Download, Edit, Open in new window", - "help.desc_adv_syntax": ": Python, JS, HTML, CSS, Java, C++, Rust, Go and many more", - "help.desc_ae213f54": ":\n Combinez opérateurs et texte libre", - "help.desc_aec0ad2c": "💬 Réécrire — Réécrit le texte selon vos instructions personnalisées. Une boîte de dialogue vous demande votre instruction.", - "help.desc_all_tags": ": Extracted from YAML frontmatters and inline (#tag)", - "help.desc_all_vaults": ": Global view of all your content", - "help.desc_autoscroll": ": The sidebar positions itself automatically", - "help.desc_b54c21ef": "Contrôle d'accès par vault : Chaque utilisateur voit uniquement ses vaults", - "help.desc_b5f89b3b": "ObsiGate integrates an AI assistant directly into the text editor. To activate it, configure at least one AI provider in the .env file (DeepSeek, OpenRouter, or Gemini).", - "help.desc_b6169f2e": "Each webhook receives a POST with event details", - "help.desc_b9c94994": ": Preview of the applied regex", - "help.desc_ba4578ae": "Restart the container:", - "help.desc_bc08f215": "ObsiGate uses JWT tokens signed with a secret key defined in the .env file.", - "help.desc_beed5686": "Click on", - "help.desc_breadcrumb": "File path (clickable to reposition sidebar)", - "help.desc_c1f72521": "Edit config.yaml to customize behavior", - "help.desc_c63f02cc": "Rewrites the text according to your custom instructions. A dialog prompts for your instruction.", - "help.desc_c8532869": ": Completion, rewrite, translation (see", - "help.desc_c992f2e5": "Remplissez : Nom (descriptif), URL (endpoint cible), Secret (optionnel)", - "help.desc_case_sensitive": ": \"Aa\" button to respect case", - "help.desc_cb6f0bfd": "Backup", - "help.desc_cc8e35ba": "Notifications : Alerter un canal Slack/Discord quand un document est créé", - "help.desc_cdf7bb46": "Recherchez intelligemment : Combinez opérateurs et texte libre", - "help.desc_cf5ccd40": "Simplifies the language for easier reading — replaces complex terms and shortens long sentences.", - "help.desc_cfe362a7": "Export PDF : Téléchargement du document partagé en PDF via/s/{token}/pdf", - "help.desc_check_btn": ": Manual save", - "help.desc_chip_remove": ": Click \"×\" to remove a filter", - "help.desc_chip_view": ": See active filters at a glance", - "help.desc_click_segment": ": Navigate to that folder", - "help.desc_click_tab": ": Activates the tab", - "help.desc_click_vault": ": Focus on the vault in the sidebar", - "help.desc_close_btn": ": Closes the tab (unless it's the only one)", - "help.desc_cm_autocomplete": ": Contextual suggestions", - "help.desc_cm_lines": ": Easy navigation", - "help.desc_cm_search": ": Ctrl+F to search in the file", - "help.desc_cm_syntax": ": Supports many languages", - "help.desc_combined": "searches \"web server\" in Markdown files of the IT vault with the linux tag.", - "help.desc_context_menu": ": Right-click on a vault or folder → Graph View", - "help.desc_copy_btn": ": Copies source content to clipboard", - "help.desc_ctrl_tab": ": Next tab", - "help.desc_ctrl_w": ": Close the active tab", - "help.desc_d186a19e": ": The Recent tab in the sidebar lists your latest files", - "help.desc_d3a71d97": "file_modified n'est pas encore dispatché (réservé pour version future)", - "help.desc_d5c977ac": "Code blocks", - "help.desc_d646b709": "Compte admin : Créé automatiquement au premier démarrage", - "help.desc_d66e911c": "In the", - "help.desc_d915c72b": "Synchronisation : Copier les nouveaux fichiers vers un autre système (SharePoint, Google Drive)", - "help.desc_d9cdaa89": "Copy", - "help.desc_d9e8ab0b": "🧰 Boîte ▾ — Outils de conversion : 📋 Convert to list : Transforme le texte en liste Markdown", - "help.desc_dc4d7186": "Each webhook receives a POST with event details", - "help.desc_delete_btn_new": ": Trash button to delete", - "help.desc_double_click": ": Opens the file in a persistent tab", - "help.desc_e0525213": "Inline completion (Ctrl+J). Automatically completes the text where the cursor is located.", - "help.desc_e23c94dd": ": In the toolbar (when available)", - "help.desc_e36f3eaa": "📐 Make longer : Ajoute des détails, exemples ou explications", - "help.desc_e3fce7a3": ": Opens the file in a temporary tab (preview, italic)", - "help.desc_e47d2328": "Preview", - "help.desc_e5246734": ": Previous tab", - "help.desc_e5b67e3d": "Your choice", - "help.desc_e5cf90b2": "Creates a concise summary of the selected text — bullet points capturing the essentials.", - "help.desc_e6129268": "Use the sidebar to navigate between vaults and folders.", - "help.desc_e7e3157a": "Timestamp : Chaque backup est horodaté", - "help.desc_e93517a5": "Download", - "help.desc_ec5f7a26": "Edit config.yaml to customize behavior", - "help.desc_ecf302ae": "Multi-fenêtres : Ouvrez plusieurs notes dans des onglets séparés", - "help.desc_edges": ": Outgoing wikilinks (blue) and incoming backlinks (green)", - "help.desc_eebf177f": "ObsiGate v1.7.0 - Porte d'entrée web pour vos vaults Obsidian", - "help.desc_ef1531ce": ": A temporary tab (italic) is replaced by the next click", - "help.desc_ef3f8158": ": Manage your filtering patterns", - "help.desc_examples": "Examples: ext:sh searches in bash scripts, ext:py in Python scripts, ext:md in Markdown files.", - "help.desc_expand": ": Click on a folder", - "help.desc_export_png": ": Save the graph as an image", - "help.desc_f0adf67a": ": Scroll wheel to zoom, click-drag to move", - "help.desc_f2d4e369": "✏️ Continue writing : Continue l'écriture à partir du texte", - "help.desc_f53badcd": "Add your API key in .env:", - "help.desc_f58da6e1": "Cliquez Ajouter", - "help.desc_f9083ce5": "File", - "help.desc_f952db17": "Refresh tokens : Cookies HttpOnly avec rotation automatique", - "help.desc_fa126609": "Converts the document structure into an Obsidian Canvas (visual cards).", - "help.desc_facet_vaults": ": Counters by vault", - "help.desc_fc9391f3": "ObsiGate sends an HTTP POST to your webhook URL with event details.", - "help.desc_fdeaf803": ": Each file type has its icon (markdown, code, etc.)", - "help.desc_file_suggest": ": File title suggestions", - "help.desc_filter_type": ": Include/exclude files, folders, markdown, other", - "help.desc_filter_usage": "Use the filter bar at the top of the sidebar to search quickly:", - "help.desc_filtering": "Search bar to filter files/tags", - "help.desc_find_in_page": ": Ctrl+F to search in the file (case, regex, whole word)", - "help.desc_frontmatter": ": tags: [docker, linux] or tags: docker, linux", - "help.desc_fullscreen": ": Button to expand the view", - "help.desc_graph_intro": "The graph view offers an interactive visualization of connections between your notes via wikilinks.", - "help.desc_graph_nav": ": Navigation history between nodes", - "help.desc_grouped_results": ": Display by vault with full paths", - "help.desc_hamburger": "(mobile) : Show/hide the sidebar", - "help.desc_hide": "Click the sidebar icon in the header", - "help.desc_images": ": Supports ![[image.png]]", - "help.desc_inline_tags": ": #docker in markdown content", - "help.desc_instant_filter": ": Type to filter files and folders", - "help.desc_logo": "Return to home", - "help.desc_markdown_all": ": Full markdown rendering", - "help.desc_md_render": "Markdown files are rendered with:", - "help.desc_menu_header": ": \"Vault\" dropdown in the Options menu", - "help.desc_menu_options": ": Access to settings, theme, help", - "help.desc_op_ext": ": Filter by file type", - "help.desc_op_path": ": Filter by path", - "help.desc_op_phrase": ": Exact phrase search", - "help.desc_op_tag": ": Filter by tag", - "help.desc_op_title": ": Search in titles only", - "help.desc_op_vault": ": Search in a specific vault", - "help.desc_open_file": ": Click on the file name", - "help.desc_open_new": ": Opens the file in a new tab", - "help.desc_patterns": ": Ex: #<% ... %> or #{{ ... }}", - "help.desc_quick_select": "Dropdown to change vault", - "help.desc_rendered_content": "Markdown with wikilinks and images", - "help.desc_resize": "Drag the right edge to adjust width", - "help.desc_save_btn_new": ": ✓ button to save", - "help.desc_search_all": ": Title, content, tags, paths", - "help.desc_search_bar": "Global search with autocomplete", - "help.desc_search_intro": "Type in the top search bar to start a fulltext search:", - "help.desc_sidebar_toggle": "Hide the sidebar for more space", - "help.desc_snippets": ": Excerpts with highlighted terms", - "help.desc_source_btn": ": Shows/hides raw markdown", - "help.desc_specific_vault": ": Focus on a single vault", - "help.desc_syntax_hl": ": Code block highlighting", - "help.desc_tag_cloud_intro": "The Tags tab in the sidebar displays a tag cloud:", - "help.desc_tag_filter_use": ": Use the filter bar to search for a tag", - "help.desc_tag_suggest": ": Tag suggestions with counters", - "help.desc_tags_tab": "Clickable tag cloud", - "help.desc_template_intro": "In the Configurations, you can hide template tags:", - "help.desc_title_tags": "File metadata", - "help.desc_trash_btn": ": Delete file", - "help.desc_two_tag_types": "ObsiGate supports two types of tags:", - "help.desc_vault_context": "Change context to filter the display:", - "help.desc_vault_indicator": "Shows the active context (All, vault1, etc.)", - "help.desc_vaults_tab": "File and folder tree", - "help.desc_visual_search": ": Search bar to highlight nodes", - "help.desc_wikilinks": ": [[link]] and [[link|text]]", - "help.double_click": "Double click", - "help.drag_drop_tabs": "Drag & drop tabs", - "help.e23c94dd": "In the toolbar (when available)", - "help.e3fce7a3": "Opens the file in a temporary tab (preview,", - "help.e5b67e3d": "Your choice is saved in localStorage", - "help.editor_section": "Editor", - "help.ef1531ce": "A temporary tab (italic) is replaced", - "help.experience": "Experience", - "help.export": "Export", - "help.external_audit": "External audit", - "help.f0adf67a": "Scroll wheel to zoom, click-drag to move", - "help.fallback_editor": "Fallback editor", - "help.fdeaf803": "Each file type has its icon (markdown, code, etc.)", - "help.fe388b67": "Optimizations", - "help.file_actions": "Actions on the open file:", - "help.file_viewer": "File viewer", - "help.filter_toggles": "Toggles Aa, wd, .*", - "help.filtering": "Filtering", - "help.find_capabilities": "Regex, whole word, case-sensitive search in the displayed document with DOM TreeWalker.", - "help.find_in_page": "Find in page", - "help.footer": "© 2026 — Made with ☕, 🎧 and a few", - "help.graph_context": "Context menu", - "help.graph_depth": "Depth slider", - "help.graph_export": "Export PNG", - "help.graph_filter_depth": "Filters & depth", - "help.graph_focus": "Focus mode", - "help.graph_fullscreen": "Full screen & PNG export", - "help.graph_info": "Info panel", - "help.graph_nav_arrows": "Navigation ← → ↑", - "help.graph_navigation": "History navigation ← → ↑", - "help.graph_nodes": "Nodes", - "help.graph_preview": "Ctrl+hover", - "help.graph_sticky": "Sticky panels", - "help.graph_tag_filter": "Filter by tag", - "help.graph_type_filter": "Filter by type", - "help.graph_view": "Graph view", - "help.graph_visual": "Visual search", - "help.graph_zoom": "Zoom/Pan", - "help.graph_zoom_pan": "Scroll wheel zoom & pan", - "help.guide_official": "Official guide", - "help.hamburger_btn": "Hamburger menu button", - "help.header_section": "Header", - "help.help_title": "Help", - "help.hide": "Hide", - "help.hide_help": "Hide help", - "help.highlighted_snippets": "Highlighted snippets", - "help.indexes": "ObsiGate indexes and displays:", - "help.instant": "Instant", - "help.light": "Light", - "help.logo": "ObsiGate logo", - "help.markdown": "Markdown syntax", - "help.menu_header": "Header menu", - "help.menu_options": "Options menu", - "help.mermaid_section": "Mermaid diagrams", - "help.mermaid_templates": "Templates", - "help.mobile": "Floating results bar", - "help.modal_title": "ObsiGate User Guide", - "help.multi_vault": "Multi-vault", - "help.nav_ai": "🤖 AI Editor", - "help.nav_backups": "💾 Backups", - "help.nav_customization": "🎨 Customization", - "help.nav_editing": "✏️ Editing", - "help.nav_files": "📁 Files", - "help.nav_graph": "🗺️ Graph", - "help.nav_interface": "🧭 Interface", - "help.nav_intro": "📘 Introduction", - "help.nav_navigation": "🗺️ Navigation", - "help.nav_palette": "⌨️ Palette", - "help.nav_search": "🔍 Search", - "help.nav_security": "🛡️ Security", - "help.nav_sharing": "🔗 Sharing", - "help.nav_shortcuts": "⌨️ Shortcuts", - "help.nav_tabs": "📑 Tabs", - "help.nav_tags": "🏷️ Tags", - "help.nav_tips": "💡 Tips", - "help.nav_webhooks": "🪝 Webhooks", - "help.new_file": "New file", - "help.new_folder": "New folder", - "help.nights": "sleepless nights 😅", - "help.nodes_edges": "Edges", - "help.other": "Other", - "help.outline_panel": "Outline panel (right)", - "help.pagination": "Pagination", - "help.pal_close_the_palette": "Close the palette", - "help.pal_delete_a_folder_and_its_contents": "Delete a folder and its contents", - "help.pal_delete_the_file_from_the_active_tab": "Delete the file from the active tab", - "help.pal_move_desc": "Navigate the list", - "help.pal_open___select": "Open / select", - "help.pal_open_the_editor_on_the_active_tab": "Open the editor on the active tab", - "help.pal_open_this_guide": "Open this guide", - "help.pal_popout_desc": "Open the document in a detached window", - "help.pal_toggle_light_dark": "Toggle light/dark", - "help.pdf_export": "PDF export", - "help.persistent_display": "Persistent display in bar", - "help.persistent_tabs": "Persistent tabs", - "help.popout_button": "Dedicated button", - "help.powered_by": "Powered by Python, FastAPI, vanilla JS, CodeMirror, Mermaid, Lucide Icons and ❤️ for Obsidian.", - "help.preview_tab": "Preview", - "help.properties": "Properties", - "help.public_shares": "Public sharing", - "help.pwa_section": "PWA", - "help.quick_help": "Quick Help", - "help.quick_select": "Quick select", - "help.rate_limiting": "Rate limiting", - "help.recent_nav": "Recent navigation", - "help.rename": "Rename", - "help.rendered_content": "Rendered content", - "help.rendering_images": "Image rendering", - "help.rendering_md": "Rendering in Markdown", - "help.resize": "Resize", - "help.results_counter": "Results counter", - "help.results_grouped": "Grouped results", - "help.search_bar": "Search bar", - "help.search_dropdown": "Search dropdown", - "help.search_everywhere": "Search everywhere", - "help.search_facets": "Facets", - "help.search_filters": "Search filters", - "help.search_history": "Search history", - "help.search_operators": "Search operators", - "help.search_placeholder": "Search help...", - "help.search_save": "Saved searches", - "help.secret_redaction": "Secret redaction", - "help.security_section": "Security", - "help.share_button": "Share button", - "help.shortcut_ai_completion": "Inline AI completion (in editor)", - "help.shortcut_close": "Close editor / modal", - "help.shortcut_close_editor": "Close editor / modal", - "help.shortcut_close_palette": "Close palette", - "help.shortcut_close_tab": "Close tab", - "help.shortcut_command_palette": "Command palette", - "help.shortcut_file_palette": "File palette (quick nav.)", - "help.shortcut_focus_search": "Focus search bar", - "help.shortcut_forge_help": "Forge editor help", - "help.shortcut_next_tab": "Next tab", - "help.shortcut_palette": "Command palette", - "help.shortcut_palette_cmd": "Command palette (command mode)", - "help.shortcut_prev_tab": "Previous tab", - "help.shortcut_quick_insert": "Quick insert (Forge editor)", - "help.shortcut_quick_search": "Quick search (outside text field)", - "help.shortcut_redo": "Redo", - "help.shortcut_save": "Save", - "help.shortcut_save_file": "Save open file", - "help.shortcut_search_doc": "Search in document", - "help.shortcut_select": "Open/select", - "help.shortcut_tip": "Hover over a document with Ctrl for a quick preview. Click Forge in the toolbar for the advanced editor.", - "help.shortcut_undo": "Undo", - "help.shortcuts": "Keyboard shortcuts", - "help.shortcuts_title": "Shortcuts & Tips", - "help.sidebar_dropdown": "Sidebar dropdown", - "help.sidebar_features": "Sidebar features:", - "help.sidebar_filtering": "Sidebar filtering", - "help.sidebar_section": "Sidebar", - "help.sidebar_tabs": "The sidebar has two tabs:", - "help.sidebar_toggle_btn": "Sidebar toggle button", - "help.simple": "Simple", - "help.simple_search": "Simple search", - "help.single_click": "Single click", - "help.smart_scoring": "Smart scoring", - "help.sort_options": "Sort options", - "help.supported_languages": "Many languages supported", - "help.syncthing": "Syncthing conflicts", - "help.syncthing_conflicts": "Syncthing conflicts", - "help.tab_bar": "Tab bar", - "help.tab_features": "Features", - "help.tab_nav": "Tab navigation", - "help.tabs_section": "Opening tabs", - "help.theme_section": "Theme", - "help.theme_sync": "Synced theme", - "help.theme_toggle": "Toggle between themes:", - "help.themes": "Themes", - "help.tip_hide_sidebar": "Hide the sidebar", - "help.tip_sidebar_filter": "Use sidebar filtering", - "help.tip_use_tags": "Use tags to organize", - "help.title": "ObsiGate Help", - "help.title_tags": "Title and tags", - "help.toc_title": "CONTENTS", - "help.toolbar_section": "AI toolbar", - "help.tree_section": "Vault tree", - "help.use_cases": "Use cases", - "help.vault_indicator": "Vault indicator", - "help.vault_selector": "Vault selector", - "help.vault_specific": "Specific vault", - "help.webhook_blog_post": "blog post when a file is marked", - "help.webhook_note": "Note: the event", - "help.webhook_notify": "automatically notify services", - "help.webhook_post": "HTTP POST to your", - "help.webhooks": "Webhooks", - "help.welcome_desc": "ObsiGate is your web gateway to your Obsidian vaults. Access, browse, and search all your notes from any device via a modern and responsive interface.", - "help.welcome_tag1": "⚡ Fast navigation", - "help.welcome_tag2": "🗂️ Multi-vault", - "help.welcome_tag3": "🏷️ Smart tags", - "help.welcome_tag4": "📝 Reading & editing", - "help.welcome_tag5": "🔍 TF-IDF search", - "help.welcome_title": "Welcome to ObsiGate", - "help.wikilinks": "Wikilinks", - "help.zoom_pan": "Zoom & Pan", - "mermaid.code": "Code", - "mermaid.copy_svg": "Copy SVG", - "mermaid.download_png": "Download PNG", - "mermaid.preview": "Preview", - "mermaid.zoom_in": "Zoom in", - "mermaid.zoom_out": "Zoom out", - "mobile.all_vaults": "📂 All vaults", - "modal.create_btn": "Create", - "modal.create_file": "Create a file", - "modal.creating": "Creating...", - "modal.delete_dir": "Delete folder", - "modal.delete_dir_warning": "All files and subfolders will be permanently deleted.", - "modal.delete_file": "Delete file", - "modal.delete_irreversible": "This action is irreversible.", - "modal.delete_permanently": "Delete permanently", - "modal.delete_warning": "Warning!", - "modal.dir_to_delete": "Folder to delete:", - "modal.file_name": "File name", - "modal.file_to_delete": "File to delete:", - "modal.file_type": "File type", - "modal.in_folder": "In: {path}", - "month.april": "April", - "month.august": "August", - "month.december": "December", - "month.february": "February", - "month.january": "January", - "month.july": "July", - "month.june": "June", - "month.march": "March", - "month.may": "May", - "month.november": "November", - "month.october": "October", - "month.september": "September", - "offline.all_synced": "All changes synced", - "offline.conflict_title": "Sync conflict", - "offline.keep_local": "Keep local version", - "offline.keep_server": "Keep server version", - "offline.mode_offline": "Offline mode — changes will sync when back online", - "offline.pending": "{count} pending change(s)", - "offline.reconnected": "Connection restored — synchronizing...", - "offline.status": "Offline", - "offline.sync_now": "Sync now", - "palette.browse_dirs": "📂 Browse directories...", - "palette.browse_hint": "Navigate vaults to find a file", - "palette.browse_in": "In {path}", - "palette.browse_no_results": "No results — browse manually", - "palette.browse_open_file": "📂 Open a file in this directory", - "palette.browse_root": "root", - "palette.close_current": "Close current file", - "palette.close_current_desc": "Close active tab without deleting", - "palette.cmd_back_home": "🏠 Home", - "palette.cmd_back_home_desc": "Back to home", - "palette.cmd_config": "⚙️ Settings", - "palette.cmd_config_desc": "Open settings", - "palette.cmd_create_dir": "📁 Create directory", - "palette.cmd_create_dir_desc": "Choose vault, navigate, then name the directory", - "palette.cmd_create_file": "📄 Create markdown file", - "palette.cmd_create_file_desc": "Choose vault, navigate, then name the file", - "palette.cmd_delete_dir": "🗑️ Delete directory", - "palette.cmd_delete_dir_desc": "Choose vault, navigate and delete", - "palette.cmd_theme": "🌓 Toggle theme", - "palette.cmd_theme_desc": "Toggle light/dark", - "palette.del_all_content": "All content will be deleted", - "palette.delete_current": "Delete current file", - "palette.delete_current_desc": "Delete file from active tab", - "palette.delete_file_desc": "Search for a file to delete", - "palette.dir_delete_confirm": "All content will be deleted", - "palette.dir_name": "Directory name", - "palette.empty_dir": "📂 Empty directory", - "palette.error_loading": "Loading error", - "palette.error_prefix": "Error: {msg}", - "palette.file_name": "File name", - "palette.help_desc": "Open the guide", - "palette.md_hint": "(.md added if needed)", - "palette.mode_commands": "Commands", - "palette.mode_files": "Files", - "palette.no_results": "No results for \"{query}\"", - "palette.no_vaults": "No vaults found", - "palette.popout_desc": "Open document in a window", - "palette.reindex_desc": "Force full reindex", - "palette.search_commands": "Type a command...", - "palette.search_error": "Search error", - "palette.search_files": "Search files...", - "palette.type_command": "Type a command...", - "palette.type_search": "Search files... (+include -exclude)", - "palette.vault_count": "{count} files", - "pwa.dismiss": "Later", - "pwa.install_button": "Install", - "pwa.install_desc": "Install this app on your device for quick access.", - "pwa.install_title": "Install ObsiGate", - "search.advanced_operators": "Advanced operators", - "search.aria_label": "Search suggestions", - "search.case_sensitive": "Case sensitive", - "search.clear": "Clear", - "search.dropdown_clear_history": "Clear history", - "search.dropdown_files": "Files", - "search.dropdown_history": "History", - "search.error": "Search error", - "search.exclude_placeholder": "Exclude: vendor/*, *.lock", - "search.facet_tags": "Tags", - "search.facet_vaults": "Vaults", - "search.files_filtered": "{count} file(s) with filters", - "search.filter_path_title": "Path filters (Alt-F)", - "search.filters": "Filters", - "search.full_text": "Search everywhere", - "search.highlighted_snippets": "Highlighted snippets", - "search.include_placeholder": "Include: **/*.md, notes/**", - "search.loading": "Searching...", - "search.no_results": "No results found", - "search.operators_help": "Operators: tag:word, vault:name, title:word, path:word, ext:md", - "search.pagination": "Pagination", - "search.previous": "← Previous", - "search.query_time": "({time} ms)", - "search.regex": "Regular expression", - "search.results_count": "{count} result(s)", - "search.results_filtered": "{count} result(s) for \"{query}\" with filters", - "search.results_for": "{count} result(s) for \"{query}\"", - "search.save_search": "Save search", - "search.saved": "Search saved", - "search.sections_all_vaults": "All vaults", - "search.simple_search": "Simple search", - "search.smart_scoring": "Smart scoring", - "search.sort_date": "Date", - "search.sort_relevance": "Relevance", - "search.sort_title": "Title", - "search.whole_word": "Whole word", - "settings.about": "📦 About", - "settings.ai": "🤖 AI", - "settings.backend": "⚙️ Backend", - "settings.backend_hint": "These settings are saved on the server. Some require a restart or reindexing.", - "settings.backend_section": "Backend Settings", - "settings.client_label": "These settings apply immediately on the client side.", - "settings.diagnostics": "🩺 Diagnostics", - "settings.history_count_desc": "Between 5 and 100 files (saved on server)", - "settings.history_count_label": "Files in history", - "settings.history_section": "Recent History", - "settings.no_restart_badge": "No restart needed", - "settings.profile": "👤 Profile", - "settings.reindex": "Force reindex", - "settings.restart_badge": "Restart required", - "settings.save": "Save", - "settings.search": "Search", - "settings.tabs": "Tabs", - "settings.search_placeholder": "Search...", - "settings.sync": "🔄 Sync", - "settings.themes": "🎨 Themes", - "share.copied": "Link copied!", - "share.copy_link": "Copy link", - "share.create": "Create share link", - "share.expires": "Expires on", - "share.never": "Never", - "share.revoke": "Revoke", - "share.title": "Public share", - "shortcut.ai_completion": "AI inline completion (in editor)", - "shortcut.close_editor": "Close editor / modal", - "shortcut.command_palette": "Command palette", - "shortcut.editor_help": "Forge editor help", - "shortcut.file_palette": "File palette (quick nav)", - "shortcut.focus_search": "Focus search bar", - "shortcut.quick_insert": "Quick insert (Forge editor)", - "shortcut.quick_search": "Quick search (outside text field)", - "shortcut.save_file": "Save open file", - "shortcut.search_in_doc": "Search in document", - "shortcut.tip_preview": "Hover a document with **Ctrl** for a quick preview. Click **Forge** in the toolbar for the advanced editor.", - "sidebar.all_vaults": "All vaults", - "sidebar.case_sensitive": "Case sensitive", - "sidebar.clear_filter": "Clear", - "sidebar.expand_collapse": "Expand/Collapse", - "sidebar.file_icons": "Icons", - "sidebar.filter_instant": "Instant search", - "sidebar.filter_path": "Path filters", - "sidebar.filter_placeholder": "Filter files...", - "sidebar.filter_results_grouped": "Grouped results", - "sidebar.loading": "Loading...", - "sidebar.no_recent_files": "No recent files", - "sidebar.no_results": "No matching directory or file.", - "sidebar.no_saved_searches": "No saved searches", - "sidebar.open_file": "Open file", - "sidebar.saved_dirs_tab": "Folders", - "sidebar.saved_searches_tab": "Searches", - "sidebar.sidebar_dropdown": "Vault context menu", - "sidebar.sidebar_filtering": "Sidebar filtering", - "sidebar.tab_backups": "Backups", - "sidebar.tab_recent": "Recent", - "sidebar.tab_saved": "Searches", - "sidebar.tab_tags": "Tags", - "sidebar.tab_vaults": "Vaults", - "sidebar.vault_context_all": "All vaults", - "sidebar.vault_specific": "Specific vault", - "sync.autocomplete": "Autocomplete", - "sync.autocomplete_active": "Autocomplete active", - "sync.connected": "Synchronized", - "sync.connected_short": "Connected", - "sync.disconnected": "Disconnected", - "sync.event_index_progress": "Vault indexed", - "sync.event_index_start": "Index starting", - "sync.event_index_updated": "Update", - "sync.event_vault_added": "Vault added", - "sync.event_vault_removed": "Vault removed", - "sync.index_complete": "Indexing complete ({count} files)", - "sync.index_reloaded": "Full index reloaded", - "sync.index_started": "Indexing started ({count} vaults)", - "sync.install_success": "ObsiGate installed successfully!", - "sync.model_not_loaded": "Model not loaded", - "sync.no_provider": "No provider", - "sync.no_recent_events": "No recent events", - "sync.not_configured": "Not configured", - "sync.processing": "Processing…", - "sync.update": "Update", - "sync.updating": "Updating...", - "sync.vault_added": "Vault \"{vault}\" added ({count} files)", - "sync.vault_added_label": "Vault added", - "sync.vault_files": "{vault} ({files} files)", - "sync.vault_indexed_label": "Vault indexed", - "sync.vault_removed": "Vault \"{vault}\" removed", - "sync.vault_removed_label": "Vault removed", - "sync.verifying": "Verifying…", - "theme.change": "Change theme", - "theme.dark": "Dark", - "theme.light": "Light", - "theme.title": "Theme", - "themes.name_gradients": "Subtle gradients", - "themes.name_terminal": "Pure black & green", - "toast.ai_keys_saved": "API keys saved", - "toast.ai_no_key": "No keys to save", - "toast.bookmark_added": "Added to bookmarks", - "toast.bookmark_removed": "Removed from bookmarks", - "toast.cannot_delete_self": "Cannot delete your own account", - "toast.config_client_saved": "Client settings saved", - "toast.config_reset": "Configuration reset", - "toast.config_saved": "Configuration saved", - "toast.conflict_resolved": "Conflict resolved", - "toast.copied": "Copied!", - "toast.copy_error": "Copy error", - "toast.create_error": "Creation error", - "toast.created": "Created", - "toast.delete_error": "Deletion error", - "toast.deleted": "Deleted", - "toast.dir_created": "Folder \"{name}\" created", - "toast.dir_deleted": "Folder deleted ({count} files)", - "toast.dir_renamed": "Directory renamed", - "toast.dir_saved_search": "Folder saved to searches", - "toast.error_delete": "Delete error", - "toast.error_init": "Initialization error", - "toast.error_load": "Loading error", - "toast.error_network": "Network error", - "toast.error_rename": "Cannot rename this item", - "toast.file_created": "File \"{name}\" created", - "toast.file_deleted": "File deleted", - "toast.file_renamed": "File renamed", - "toast.hidden_saved": "✓ Settings saved", - "toast.index_reloaded": "Full index reloaded", - "toast.installed": "ObsiGate installed successfully!", - "toast.link_created": "Link created!", - "toast.moved": "Moved", - "toast.no_open_file": "No file open", - "toast.not_found_tree": "Item not found in tree", - "toast.path_copied": "Path copied: {path}", - "toast.reindex_done": "Reindexing complete", - "toast.reindex_started": "Reindexing...", - "toast.rename_error": "Rename error", - "toast.renamed": "Renamed", - "toast.saved": "Saved", - "toast.search_saved": "Search saved", - "toast.share_revoked": "Share revoked", - "toast.url_required": "URL required", - "toast.user_created": "User created", - "toast.user_deleted": "User deleted", - "toast.user_modified": "User modified", - "toast.viewer_error": "Viewer loading error", - "toc.hide_panel": "Hide panel", - "toc.no_headings": "No headings in this document", - "toc.title": "ON THIS PAGE", - "tree.new_file": "New file", - "tree.new_folder": "New folder", - "tree.vault_home": "Vault home", - "ui.backups_versions": "Backups / Versions", - "ui.cannot_rename": "Cannot rename this item", - "ui.delete_name_empty": "Name cannot be empty", - "ui.element_not_found": "Element not found in tree", - "ui.vault_readonly": "Read-only vault", - "vault.add_dynamic": "Add vault", - "vault.reindex": "Reindex vault", - "vault.remove_dynamic": "Remove vault", - "vaulthome.empty": "No files in this directory", - "vaulthome.error_loading": "Loading error:", - "vaulthome.file_count": "{count} file", - "vaulthome.file_count_plural": "{count} files", - "vaulthome.loading": "Loading files...", - "vaulthome.size_bytes": "B", - "vaulthome.size_kb": "KB", - "vaulthome.size_mb": "MB", - "viewer.backlinks": "Backlinks", - "viewer.binary_download": "Download file", - "viewer.binary_unsupported": "Unsupported binary file", - "viewer.bookmark_add": "Add to bookmarks", - "viewer.bookmark_remove": "Remove bookmarks", - "viewer.bookmark_toggle": "Add/Remove bookmarks", - "viewer.breadcrumb_home": "Home", - "viewer.click_to_download": "Click to download", - "viewer.copied": "Copied!", - "viewer.copy": "Copy", - "viewer.copy_error": "Copy error", - "viewer.download": "Download", - "viewer.download_md": "Download as .md", - "viewer.download_pdf": "Download as PDF", - "viewer.edit": "Edit", - "viewer.error": "Loading error", - "viewer.forge_brand": "Forge", - "viewer.forge_title": "Forge (new editor)", - "viewer.index_start": "Starting index...", - "viewer.index_updated": "Updated", - "viewer.loaded_from_cache": "File loaded from offline cache", - "viewer.loading": "Loading file...", - "viewer.markdown": "Markdown", - "viewer.metadata_created": "Created", - "viewer.metadata_modified": "Modified", - "viewer.metadata_path": "Path", - "viewer.metadata_size": "Size", - "viewer.metadata_tags": "Tags", - "viewer.metadata_vault": "Vault", - "viewer.no_headings": "No headings in this document", - "viewer.on_this_page": "ON THIS PAGE", - "viewer.outline": "Outline", - "viewer.pdf_pages": "{count} pages", - "viewer.popout": "Open in popup", - "viewer.raw": "Raw", - "viewer.share": "Share", - "viewer.shared_doc_title": "Shared document — click to manage", - "viewer.source": "Source", - "viewer.syncing": "Updating...", - "viewer.toc": "Table of contents", - "viewer.unsupported_file": "This file is binary and cannot be displayed", - "webhook.trigger_create": "Creation via API or palette", - "webhook.trigger_delete": "Deletion via API or editor", - "webhook.trigger_dir_create": "Directory creation via API", - "webhook.trigger_dir_delete": "Directory deletion via API", - "webhook.trigger_dir_rename": "Directory rename via API", - "webhook.trigger_rename": "Rename via API" -} diff --git a/desktop/frontend-static/locales/fr.json b/desktop/frontend-static/locales/fr.json deleted file mode 100644 index 0e2e44e..0000000 --- a/desktop/frontend-static/locales/fr.json +++ /dev/null @@ -1,1499 +0,0 @@ -{ - "_meta": { - "locale": "fr", - "name": "Français" - }, - "about.api_version": "Version API", - "about.backend": "Backend", - "about.browser": "Navigateur", - "about.built_with": "Construit avec", - "about.editor": "Éditeur", - "about.file_watcher": "Surveillance fichiers", - "about.files": "Fichiers", - "about.files_indexed": "Fichiers indexés", - "about.footer": "Fait avec ☕, 🍕 et quelques git push --force accidentels.", - "about.frontend": "Frontend", - "about.fun_quote": "« Aucun LLM n'a été blessé durant ce développement. »", - "about.git": "Git : —", - "about.icons": "Icônes", - "about.joke_0": "0 bug connu. Les autres sont timides.", - "about.joke_1": "Compile du premier coup. (Sauf le lundi matin.)", - "about.joke_2": "Écrit par un humain. Probablement.", - "about.joke_3": "Aucun LLM n'a été blessé durant ce développement.", - "about.joke_4": "Quand ça marche, on appelle ça une feature.", - "about.joke_5": "CSS: 90% du temps de dev, 10% du code.", - "about.joke_6": "Dark mode activé depuis la naissance du projet.", - "about.joke_7": "Ça marche sur ma machine™", - "about.joke_8": "Techniquement, tout est un edge case.", - "about.joke_9": "Le CSS de ce panneau a pris plus de temps que le backend.", - "about.language": "Langue", - "about.last_delivery": "Dernière livraison : Juin 2026", - "about.made_with": "Fait avec ☕, 🎧 et quelques git push --force accidentels.", - "about.markdown_renderer": "Rendu Markdown", - "about.name": "Nom", - "about.platform": "Plateforme", - "about.section_app": "Application", - "about.section_components": "Composants", - "about.section_env": "Environnement", - "about.status": "Statut", - "about.subtitle": "Vos notes Obsidian, simplement accessibles.", - "about.syntax_highlight": "Coloration syntaxe", - "about.tagline": "Vos notes Obsidian,
    simplement accessibles.", - "about.tests": "Tests", - "about.vaults_configured": "Vaults configurés", - "about.version": "Version", - "admin.close": "Fermer", - "admin.col_actions": "Actions", - "admin.col_last_login": "Dernière connexion", - "admin.col_role": "Rôle", - "admin.col_status": "Statut", - "admin.col_user": "Utilisateur", - "admin.col_vaults": "Vaults", - "admin.new_user": "+ Nouvel utilisateur", - "admin.title": "Administration — Utilisateurs", - "ai.casual": "Ton décontracté", - "ai.completion_added": "AI: complétion ajoutée", - "ai.continue": "Continuer", - "ai.custom_rewrite": "Réécriture personnalisée", - "ai.done": "AI: texte traité", - "ai.edit": "Éditer", - "ai.error_invalid_key": "clé API invalide", - "ai.explain": "Expliquer", - "ai.fix_spelling": "Corriger l'orthographe", - "ai.frontmatter": "Générer frontmatter", - "ai.generate": "Générer", - "ai.hint_add_details": "Ajoute des détails", - "ai.hint_edit_selection": "Modifie le texte sélectionné", - "ai.hint_generate": "Génère du contenu à partir de la sélection", - "ai.hint_improve": "Améliore la qualité du texte", - "ai.hint_translate": "Traduit le texte sélectionné", - "ai.improve": "Améliorer", - "ai.inline_completion_title": "AI Inline Completion (Ctrl+J) — Complète le texte automatiquement", - "ai.invalid_api_key": "AI: clé API invalide. Vérifiez DEEPSEEK_API_KEY dans .env", - "ai.longer": "Allonger", - "ai.no_api_key": "Aucune clé API configurée", - "ai.not_configured": "⚠️ AI non configuré — ajouter DEEPSEEK_API_KEY, OPENROUTER_API_KEY ou GEMINI_API_KEY dans .env", - "ai.processing": "⏳ AI: traitement en cours...", - "ai.professional": "Ton professionnel", - "ai.quota_exceeded": "AI: quota dépassé ou paiement requis", - "ai.rewrite": "💬 Réécrire", - "ai.rewrite_done": "AI: texte réécrit", - "ai.rewrite_prompt": "Instruction de réécriture :", - "ai.rewrite_title": "Réécrit le texte selon vos instructions", - "ai.select_text": "AI: sélectionnez du texte à traiter", - "ai.shorter": "Raccourcir", - "ai.simplify": "Simplifier", - "ai.summarize": "Résumer", - "ai.text_processed": "AI: texte traité ✓", - "ai.text_rewritten": "AI: texte réécrit", - "ai.to_canvas": "Convertir en Canvas", - "ai.to_list": "Convertir en liste", - "ai.to_table": "Convertir en tableau", - "ai.toolbar_edit": "Éditer", - "ai.toolbar_generate": "Générer", - "ai.toolbar_rewrite": "Réécrire", - "ai.toolbar_tone": "Ton", - "ai.toolbar_toolbox": "Toolbox", - "ai.toolbar_translate": "Traduire", - "ai.toolbox": "🧰 Boîte", - "ai.translate_to": "Traduire en {lang}", - "auth.cannot_delete_self": "Impossible de supprimer son propre compte", - "auth.logged_out": "Déconnecté", - "auth.login_button": "Se connecter", - "auth.login_error": "Identifiants invalides", - "auth.login_title": "Accès sécurisé à vos vaults", - "auth.logout_title": "Déconnexion", - "auth.network_error": "Erreur réseau — vérifiez votre connexion", - "auth.new_password": "Nouveau mot de passe (vide = inchangé)", - "auth.password": "Mot de passe", - "auth.password_min": "Min. 8 caracteres", - "auth.remember_me": "Se souvenir de moi (30 jours)", - "auth.session_expired": "Session expirée, veuillez vous reconnecter", - "auth.user_deleted": "Utilisateur supprimé", - "auth.username": "Nom d'utilisateur", - "auto.0257e77f": "🧰 Boîte ▾", - "auto.033a9ddf": "Modèle par défaut", - "auto.03a6e5b1": "Les opérateurs utilisés s'affichent sous forme\n de chips colorés :", - "auto.13c3ee2c": "Recherche et autocomplétion", - "auto.13eb7a51": "AI: clé API invalide", - "auto.14c75ac6": "Sélectionnez les événements souhaités", - "auto.195a8e44": "Créer répertoire", - "auto.1a54bd69": "Exemple combiné", - "auto.1a8a8118": "Glisser-déposer", - "auto.1abf6661": "Le chemin affiché au-dessus du contenu est\n interactif :", - "auto.1d3330cc": "Pas de retry automatique en cas d'échec", - "auto.1d46301c": "Numéros de ligne", - "auto.1efbbc9a": "Édition avec CodeMirror 6", - "auto.209c5490": "La barre supérieure contient les éléments\n essentiels :", - "auto.272dd29a": "Providers supportés", - "auto.27a2f7c1": "ObsiGate supporte l'ouverture de plusieurs\n fichiers simultanément dans des onglets.", - "auto.28bf6aab": "Sécurité : signature HMAC-SHA256", - "auto.2a5af19b": "Le workflow se déclenche automatiquement à\n chaque événement", - "auto.2bc24d2e": "Toutes les opérations sensibles sont tracées\n dans un journal.", - "auto.2bc66bab": "Création de dossier via l'API", - "auto.337d8626": "Thème clair/sombre", - "auto.37561472": "🛡️ Sécurité", - "auto.396d0dd8": "La barre d'outils AI apparaît sous le titre\n de l'éditeur", - "auto.3be698f6": "Favorisez les opérateurs", - "auto.404c8f1c": "L'autocomplétion vous aide à trouver rapidement\n :", - "auto.41d7c6af": "Répertoire dédié", - "auto.460b8298": "Données", - "auto.4bc1f00a": "Utilisez des opérateurs pour affiner votre\n recherche :", - "auto.4c908ade": "Cliquez sur un vault pour l'ouvrir et voir son\n contenu. Les dossiers affichent un chevron et un\n badge avec le nombre d'éléments.", - "auto.4d281c6c": "AI: texte traité ✓", - "auto.4dfa6a25": "Pas de filtrage par vault — un webhook\n écoute toutes les vaults", - "auto.4fa5d7c2": "Édition rapide", - "auto.559ef1da": "Workflow recommandé", - "auto.598a0ca7": "Événements tracés", - "auto.5a486420": "Supprimer répertoire", - "auto.5d4a2516": "Ouvrez un fichier en mode Édition (bouton ✏️\n Éditer)", - "auto.5d936af6": "Regex générée", - "auto.62c3d50d": "💬 Réécrire", - "auto.678711b5": "Sélectionnez un contexte", - "auto.695d9e47": "Éditeur CodeMirror 6", - "auto.6c166d35": "ObsiGate est votre porte d'entrée web vers\n vos vaults Obsidian. Accédez, naviguez et\n recherchez dans toutes vos notes depuis\n n'importe quel appareil via une interface\n moderne et responsive.", - "auto.72e515fa": "Contrôle d'accès par vault", - "auto.753d30a8": "Ouvrez un fichier pour le voir\n apparaître ici", - "auto.774dbd63": "La palette de commandes permet d'accéder\n rapidement aux fichiers et aux actions sans\n utiliser la souris.", - "auto.79f6e1dd": "Multi-fenêtres", - "auto.7c9cdc3c": "Cochez les événements à écouter", - "auto.7e13c97a": "Ces paramètres s'appliquent immédiatement\n côté client.", - "auto.83a0efdf": "Réindexation", - "auto.9122fd5c": "Configuration avancée", - "auto.98c547ea": "ne déclenchent pas", - "auto.a05514cb": "Création via l'API ou la palette", - "auto.a105a2d9": "Éditer ▾", - "auto.a131dfab": "Éditeur CodeMirror", - "auto.a232672b": "Déploiement", - "auto.a3319169": "📦 À propos", - "auto.aa8ca265": "La vue utilise l'algorithme Barnes-Hut pour\n calculer la disposition en O(n log n),\n garantissant des performances fluides même avec\n des centaines de nœuds.", - "auto.ab5e6155": "ObsiGate crée automatiquement des sauvegardes\n avant chaque modification destructive.", - "auto.aedff644": "Créer fichier markdown", - "auto.b114ed1c": "Ces paramètres sont sauvegardés sur le\n serveur. Certains nécessitent un redémarrage\n ou une réindexation.", - "auto.b419c2c2": "Récepteur Python (Flask)", - "auto.b86ba5ea": "Recherche multi-critères", - "auto.b893650a": "Éditer fichier courant", - "auto.ba768f01": "Événements supportés", - "auto.c089d968": "Épinglez des fichiers pour les retrouver\n ici.", - "auto.c14b5603": "🎨 Thèmes", - "auto.c4922a99": "🤖 Intelligence Artificielle dans l'Éditeur", - "auto.caac40b9": "Choisissez un thème visuel. Chaque thème\n offre un mode sombre et clair.", - "auto.cd7332c8": "Les résultats incluent des facettes pour affiner\n :", - "auto.ce4eb802": "Générer ▾", - "auto.d33601dc": "Surveillance des fichiers en temps réel via\n watchdog. Les modifications sont détectées\n automatiquement et l'index est mis à jour\n sans redémarrage.", - "auto.d4d28717": "Déclencheur", - "auto.e0b8a606": "Définissez les patterns de tags à masquer\n dans la sidebar. Vous pouvez utiliser des\n wildcards pour cibler les tags de template.", - "auto.e61598c1": "Partagez un document pour le voir\n apparaître ici", - "auto.ec7260fa": "Types de fichiers supportés", - "auto.edf89626": "L'éditeur intégré offre :", - "auto.ef8c5f4d": "L'éditeur intégré offre une expérience complète\n d'édition :", - "auto.f346076a": "✏️ Édition avancée", - "auto.f5a8c116": "Événement", - "auto.f8ba6127": "🗂️ Fichiers cachés", - "auto.fc694490": "Suppression via l'API ou l'éditeur", - "backup.delete": "Supprimer", - "backup.diff": "Comparer", - "backup.file_restored": "Fichier restauré avec succès", - "backup.no_backups": "Aucune sauvegarde", - "backup.preview": "Aperçu", - "backup.purge": "Purger", - "backup.restore": "Restaurer", - "backup.restore_failed": "Échec de la restauration", - "backup.select_to_restore": "Sélectionnez un backup à restaurer", - "backup.timestamp_not_found": "Impossible de trouver le timestamp du backup", - "backup.title": "Sauvegardes", - "backup.version": "Version du {date}", - "backups.delete_confirm": "Supprimer ce backup ?", - "backups.empty": "Aucun backup disponible pour ce fichier.", - "backups.hint": "Les backups sont crees automatiquement avant chaque modification.", - "backups.loading": "Chargement des backups...", - "backups.purge_file": "Supprimer TOUS les backups de", - "backups.purge_vault": "Supprimer TOUS les backups du vault", - "backups.restore_confirm": "a la version du backup selectionne ?\nLa version actuelle sera sauvegardee.", - "backups.title": "Backups", - "button.cancel": "Annuler", - "common.actions": "Actions", - "common.all": "Tous", - "common.back": "Retour", - "common.cancel": "Annuler", - "common.close": "Fermer", - "common.confirm": "Confirmer", - "common.copied": "Copié !", - "common.copy": "Copier", - "common.create": "Créer", - "common.delete": "Supprimer", - "common.download": "Télécharger", - "common.edit": "Éditer", - "common.error": "Erreur", - "common.loading": "Chargement...", - "common.move": "Déplacer", - "common.never": "Jamais", - "common.next": "Suivant", - "common.no": "Non", - "common.none": "Aucun", - "common.ok": "OK", - "common.previous": "Précédent", - "common.refresh": "Rafraîchir", - "common.rename": "Renommer", - "common.root": "(racine)", - "common.save": "Enregistrer", - "common.search": "Rechercher", - "common.unknown": "Inconnue", - "common.yes": "Oui", - "config.about": "À propos", - "config.about_error": "Erreur de chargement", - "config.about_loading": "Chargement...", - "config.add_webhook": "Ajouter", - "config.ai_deepseek_label": "DeepSeek API Key", - "config.ai_default_provider": "Fournisseur par défaut", - "config.ai_gemini_label": "Gemini API Key", - "config.ai_keys": "Clés API IA", - "config.ai_keys_desc": "Configurez les clés API pour l'éditeur IA.", - "config.ai_model": "Modèle", - "config.ai_openrouter_label": "OpenRouter API Key", - "config.api_keys_saved": "Clés API sauvegardées", - "config.backups": "Sauvegardes", - "config.backups_desc": "Gérez les sauvegardes automatiques de vos fichiers.", - "config.client_config": "Configuration client", - "config.create_share": "Créer un partage", - "config.debounce_label": "Délai debounce (ms)", - "config.diagnostics": "Diagnostics", - "config.diagnostics_desc": "Informations techniques sur l'état du serveur.", - "config.display_name": "Nom d'affichage", - "config.error_prefix": "Erreur", - "config.error_unknown": "Erreur inconnue", - "config.force_reindex": "Forcer réindexation", - "config.hidden_files": "Fichiers cachés", - "config.hidden_files_desc": "Masquer les fichiers/dossiers commencant par un point dans l'interface (ils restent indexes et cherchables)", - "config.hidden_files_toggle": "Masquer les fichiers/dossiers caches", - "config.hidden_include_label": "Inclure les fichiers cachés", - "config.hidden_whitelist_label": "Whitelist (séparés par des virgules)", - "config.hint_activer_d_sactiver_la_surveillance_automatique_des": "Activer/désactiver la surveillance automatique des fichiers", - "config.hint_annuler_la_recherche_apr_s_ce_d_lai_5000_120000_": "Annuler la recherche après ce délai (5000-120000)", - "config.hint_contenu_index_par_fichier_10k_1m_r_indexation_requ": "Contenu indexé par fichier (10K-1M). Réindexation requise.", - "config.hint_d_lai_avant_ex_cution_de_la_recherche_100_2000_": "Délai avant exécution de la recherche (100-2000)", - "config.hint_d_lai_avant_traitement_des_changements_group_s_0_5": "Délai avant traitement des changements groupés (0.5-10 secondes)", - "config.hint_entre_5_et_100_fichiers_sauvegarde_sur_le_serveur_": "Entre 5 et 100 fichiers (sauvegarde sur le serveur)", - "config.hint_forcer_le_mode_polling_au_lieu_de_inotify_natif_ut": "Forcer le mode polling au lieu de inotify natif (utile si le mode natif ne fonctionne pas)", - "config.hint_intervalle_de_scrutation_en_mode_polling_1_30_seco": "Intervalle de scrutation en mode polling (1-30 secondes)", - "config.hint_multiplicateur_de_pertinence_pour_les_correspondan": "Multiplicateur de pertinence pour les correspondances dans le titre", - "config.hint_nombre_de_r_sultats_affich_s_par_page_10_200_": "Nombre de résultats affichés par page (10-200)", - "config.hint_nombre_max_de_tokens_largis_par_pr_fixe_10_200_": "Nombre max de tokens élargis par préfixe (10-200)", - "config.hint_nombre_maximum_de_versions_backup_conservees_par_f": "Nombre maximum de versions backup conservees par fichier (1-50)", - "config.hint_nombre_minimum_de_caract_res_avant_recherche_1_5_": "Nombre minimum de caractères avant recherche (1-5)", - "config.hint_threads_d_di_s_la_recherche_1_8_": "Threads dédiés à la recherche (1-8)", - "config.just_now": "a l'instant", - "config.lang_hint": "Utilisée par l'autocomplétion et le ghost text.", - "config.lang_label": "Langue préférée", - "config.link_copied": "Lien copié !", - "config.link_created": "Lien créé !", - "config.logout": "Déconnexion", - "config.max_backups": "Max backups par fichier", - "config.max_backups_desc": "Nombre maximum de versions backup conservées par fichier (1-50)", - "config.max_backups_label": "Max backups par fichier", - "config.max_content_hint": "Contenu indexé par fichier (10K-1M). Réindexation requise.", - "config.max_content_label": "Taille max contenu (octets)", - "config.max_content_size": "Taille max contenu (octets)", - "config.max_prefix_expansions": "Expansions préfixe max", - "config.min_query_label": "Longueur min. requête", - "config.min_query_length": "Longueur min. requête", - "config.name_placeholder": "Votre nom", - "config.no_keys": "Aucune clé à sauvegarder", - "config.no_restart": "Redémarrage non requis", - "config.note": "Note :", - "config.open_new_window": "Ouvrir dans nouvelle fenêtre", - "config.prefix_expansions_hint": "Nombre max de tokens élargis par préfixe (10-200)", - "config.prefix_expansions_label": "Expansions préfixe max", - "config.profile": "Profil utilisateur", - "config.profile_desc": "Préférences personnelles pour personnaliser l'expérience ObsiGate.", - "config.project_repo": "dépôt du projet", - "config.recent_history_count": "Nombre de fichiers dans l'historique", - "config.recent_history_count_desc": "Entre 5 et 100 fichiers (sauvegarde sur le serveur)", - "config.reindex": "Réindexer", - "config.reindex_desc": "Reconstruire l'index de recherche pour toutes les vaults.", - "config.reindex_error": "Erreur de réindexation", - "config.reindexing": "Réindexation...", - "config.reset": "Réinitialiser", - "config.restart_required": "Redémarrage requis", - "config.results_per_page": "Résultats par page", - "config.results_per_page_label": "Résultats par page", - "config.save": "Enregistrer", - "config.save_ai_keys": "Enregistrer les clés", - "config.save_backend": "Sauvegarder la configuration serveur", - "config.save_error": "Erreur de sauvegarde", - "config.save_hidden": "Enregistrer", - "config.saved": "✓ Sauvegardé", - "config.saving": "Sauvegarde", - "config.search_timeout": "Timeout recherche (ms)", - "config.search_workers": "Workers de recherche", - "config.search_workers_hint": "Threads dédiés à la recherche (1-8)", - "config.search_workers_label": "Workers de recherche", - "config.section_a-propos": "📦 À propos", - "config.section_about": "À propos", - "config.section_actions-sur-fichiers": "Actions sur fichiers", - "config.section_activation": "Activation", - "config.section_affichage": "Affichage", - "config.section_ai": "Clés API IA", - "config.section_arborescence-des-vaults": "Arborescence des vaults", - "config.section_astuces-et-bonnes-pratiques": "💡 Astuces et bonnes pratiques", - "config.section_audit-log": "Audit log", - "config.section_authentification": "Authentification", - "config.section_autocompletion": "Autocomplétion", - "config.section_backend": "🖥️ Paramètres backend", - "config.section_backup-automatique": "Backup automatique", - "config.section_backups": "Sauvegardes", - "config.section_barre-d-outils-ai": "Barre d'outils AI", - "config.section_breadcrumb-et-repositionnement": "Breadcrumb et repositionnement", - "config.section_cas-d-usage": "Cas d'usage", - "config.section_cas-d-usage-avances": "Cas d'usage avancés", - "config.section_chips-de-filtres-actifs": "Chips de filtres actifs", - "config.section_cles-api-intelligence-artificielle": "🤖 Cles API Intelligence Artificielle", - "config.section_configuration": "Configuration", - "config.section_configuration-avancee": "Configuration avancée", - "config.section_construit-avec": "Construit avec", - "config.section_diag": "Diagnostics", - "config.section_diagnostics": "Diagnostics", - "config.section_editeur-codemirror": "Éditeur CodeMirror", - "config.section_editeur-codemirror-6": "Éditeur CodeMirror 6", - "config.section_edition-avancee": "✏️ Édition avancée", - "config.section_edition-avec-codemirror-6": "Édition avec CodeMirror 6", - "config.section_en-tete": "En-tête", - "config.section_evenements-supportes": "Événements supportés", - "config.section_exemples-concrets": "Exemples concrets", - "config.section_facettes-et-tri": "Facettes et tri", - "config.section_fichiers": "📄 Fichiers", - "config.section_filtrage-de-la-sidebar": "Filtrage de la sidebar", - "config.section_filtrage-de-tags": "Filtrage de tags", - "config.section_filtrage-de-tags-template": "Filtrage de tags template", - "config.section_fonctionnalites": "Fonctionnalités", - "config.section_format-du-payload": "Format du payload", - "config.section_gestion-des-onglets": "📑 Gestion des onglets", - "config.section_hidden": "Fichiers cachés", - "config.section_historique-recent-redemarrage-non-requis": "📋 Historique récent\n Redémarrage non requis", - "config.section_indicateurs-visuels": "Indicateurs visuels", - "config.section_intelligence-artificielle-dans-l-editeur": "🤖 Intelligence Artificielle dans l'Éditeur", - "config.section_interaction": "Interaction", - "config.section_interface": "Interface", - "config.section_interface-utilisateur": "🧭 Interface utilisateur", - "config.section_limitations-actuelles": "Limitations actuelles", - "config.section_mode-commandes": "Mode commandes", - "config.section_mode-fichiers": "Mode fichiers", - "config.section_navigation": "Navigation", - "config.section_navigation-entre-onglets": "Navigation entre onglets", - "config.section_onglets": "Onglets", - "config.section_operateurs-avances": "Opérateurs avancés", - "config.section_optimisations": "Optimisations", - "config.section_ouverture": "Ouverture", - "config.section_ouverture-d-onglets": "Ouverture d'onglets", - "config.section_palette-de-commandes": "⌨️ Palette de commandes", - "config.section_parametres-backend-redemarrage-requis": "Paramètres backend\n Redémarrage requis", - "config.section_parametres-de-recherche": "Paramètres de recherche", - "config.section_partage-et-webhooks": "🔗 Partage et Webhooks", - "config.section_partages-publics": "📤 Partages publics", - "config.section_perf": "Performance", - "config.section_performance": "Performance", - "config.section_personnalisation": "🎨 Personnalisation", - "config.section_profil-utilisateur": "👤 Profil utilisateur", - "config.section_profile": "Profil utilisateur", - "config.section_protection": "Protection", - "config.section_providers-supportes": "Providers supportés", - "config.section_publication-publique": "Publication publique", - "config.section_raccourcis-clavier": "⌨️ Raccourcis clavier", - "config.section_recent": "📜 Historique récent", - "config.section_recherche": "🔍 Recherche", - "config.section_recherche-et-autocompletion": "Recherche et autocomplétion", - "config.section_recherche-simple": "Recherche simple", - "config.section_redimensionnement-de-la-sidebar": "Redimensionnement de la sidebar", - "config.section_sauvegarde-automatique": "Sauvegarde automatique", - "config.section_sauvegardes-et-audits": "💾 Sauvegardes et Audits", - "config.section_search": "Paramètres de recherche", - "config.section_securite": "🛡️ Sécurité", - "config.section_securite-signature-hmac-sha256": "Sécurité : signature HMAC-SHA256", - "config.section_selection-de-vault": "Sélection de vault", - "config.section_server": "Serveur", - "config.section_shares": "Partages publics", - "config.section_sidebar-barre-laterale": "Sidebar (barre latérale)", - "config.section_synchronisation-automatique": "Synchronisation automatique", - "config.section_tag-cloud": "Tag cloud", - "config.section_tags": "🏷️ Tags", - "config.section_tags-inline-vs-frontmatter": "Tags inline vs frontmatter", - "config.section_theme-clair-sombre": "Thème clair/sombre", - "config.section_themes": "🎨 Thèmes", - "config.section_trucs-et-astuces": "Trucs et astuces", - "config.section_types-de-fichiers-supportes": "Types de fichiers supportés", - "config.section_visualisation": "Visualisation", - "config.section_vue-graphe": "🗺️ Vue Graphe", - "config.section_watcher": "Synchronisation automatique", - "config.section_webhooks": "🪝 Webhooks", - "config.section_workflow-recommande": "Workflow recommandé", - "config.section_zone-de-contenu": "Zone de contenu", - "config.server_config": "Configuration serveur", - "config.settings_saved": "✓ Paramètres sauvegardés", - "config.share_revoked": "Partage révoqué", - "config.shares": "Partages publics", - "config.shares_desc": "Gérez les liens de partage public de vos documents.", - "config.shares_empty": "Aucun partage actif", - "config.tag_boost_hint": "Multiplicateur de pertinence pour les correspondances dans les tags", - "config.tag_boost_label": "Boost tags", - "config.tag_filtering_label": "Filtrage de tags", - "config.test": "Tester", - "config.timeout_label": "Timeout recherche (ms)", - "config.title": "Configuration", - "config.title_boost": "Boost titre", - "config.title_boost_hint": "Multiplicateur de pertinence pour les correspondances dans le titre", - "config.title_boost_label": "Boost titre", - "config.url_required": "URL requise", - "config.watcher_debounce_label": "Debounce (s)", - "config.watcher_enabled_label": "Activer la surveillance", - "config.watcher_interval_label": "Intervalle polling (s)", - "config.watcher_polling_label": "Mode polling (fallback)", - "config.webhook_name_placeholder": "Nom", - "config.webhook_url_placeholder": "URL", - "config.webhooks": "Webhooks", - "config.webhooks_desc": "Notifications HTTP vers des services externes lors des changements de fichiers.", - "config.workers_label": "Workers de recherche", - "confirm.delete_dir": "Supprimer ce dossier et tout son contenu ?", - "confirm.delete_dir_named": "Supprimer \"{path}\" et TOUT son contenu ?", - "confirm.delete_file": "Supprimer définitivement ce fichier ?", - "confirm.delete_file_named": "Supprimer le fichier \"{path}\" ?", - "confirm.logout": "Voulez-vous vraiment vous déconnecter ?", - "conflict.no_conflicts": "Aucun conflit détecté", - "conflict.resolve_conflict": "Garder version conflit", - "conflict.resolve_local": "Garder version locale", - "conflict.resolved": "Conflit résolu", - "dashboard.all_vaults": "Tous les vaults", - "dashboard.bookmark_add": "Ajouter aux bookmarks", - "dashboard.bookmark_remove": "Retirer des bookmarks", - "dashboard.bookmarks": "Favoris", - "dashboard.conflict_date": "Conflit du ", - "dashboard.conflict_resolved": "Conflit résolu", - "dashboard.conflicts": "Conflits", - "dashboard.conflicts_title": "Conflits de synchronisation", - "dashboard.copy_btn": "Copier", - "dashboard.count_files": "fichier", - "dashboard.count_files_plural": "fichiers", - "dashboard.ctrl_hover_tip": "Survolez un document avec Ctrl pour un aperçu rapide. Cliquez sur Forge dans la barre d'outils pour l'éditeur avancé.", - "dashboard.day_ago": "il y a {n} j", - "dashboard.error_prefix": "Erreur: ", - "dashboard.expires": "Expire le {date}", - "dashboard.hide": "Masquer", - "dashboard.hour_ago": "il y a {n} h", - "dashboard.just_now": "à l'instant", - "dashboard.keep_conflict": "Garder le conflit", - "dashboard.keep_original": "Garder l'original", - "dashboard.load_error": "Erreur de chargement", - "dashboard.loading": "Chargement...", - "dashboard.min_ago": "il y a {n} min", - "dashboard.no_bookmarks": "Aucun favori", - "dashboard.no_conflicts": "Aucun conflit", - "dashboard.no_recent": "Aucun fichier récent", - "dashboard.no_shares": "Aucun document partagé", - "dashboard.open_btn": "Ouvrir", - "dashboard.pin_error": "Erreur lors de l'épinglage", - "dashboard.pin_hint": "Épinglez des fichiers pour les retrouver ici.", - "dashboard.quick_help": "Raccourcis & Astuces", - "dashboard.recent": "Récents", - "dashboard.recent_hint": "Ouvrez un fichier pour le voir apparaître ici", - "dashboard.shared_hint": "Partagez un document pour le voir apparaître ici", - "dashboard.shares": "Partages", - "dashboard.show": "Afficher", - "dashboard.size_bytes": " o", - "dashboard.size_gb": " Go", - "dashboard.size_kb": " Ko", - "dashboard.size_mb": " Mo", - "dashboard.stats": "Statistiques", - "dashboard.stats_files": "Fichiers", - "dashboard.stats_size": "Taille totale", - "dashboard.stats_tags": "Tags uniques", - "dashboard.stats_vaults": "Vaults", - "dashboard.tab_recent": "Récents", - "dashboard.tab_shared": "Partagés", - "dashboard.tab_stats": "Statistiques", - "dashboard.total_files": "Fichiers totaux", - "dashboard.total_size": "Taille totale", - "dashboard.total_tags": "Tags uniques", - "dashboard.vaults_count": "Vaults", - "dashboard.views": "{count} vue(s)", - "dashboard.welcome": "Bienvenue dans ObsiGate", - "dashboard.zero_files": "0 fichiers", - "dragdrop.cross_vault_unsupported": "Cross-vault moves are not supported", - "dragdrop.move_failed": "Move failed", - "editor.cancel": "Annuler", - "editor.close": "Fermer", - "editor.delete_error": "Erreur de suppression", - "editor.edit": "Éditer fichier courant", - "editor.edit_current_desc": "Ouvrir le fichier actif dans l'éditeur", - "editor.find": "Rechercher dans le fichier...", - "editor.find_case": "Respecter la casse", - "editor.find_regex": "Regex", - "editor.find_whole": "Mot entier", - "editor.forge_close_editor": "Fermer l'éditeur / modale", - "editor.forge_help": "Aide de l'éditeur Forge", - "editor.no_results": "Aucun résultat", - "editor.replace": "Remplacer", - "editor.save": "Enregistrer", - "editor.save_error": "Erreur de sauvegarde", - "editor.saved": "Sauvegardé ✓", - "editor.unsaved": "Modifications non sauvegardées", - "error.initialization": "Erreur lors de l'initialisation", - "file.copy_path": "Copier le chemin", - "file.delete": "Supprimer", - "file.graph_view": "Vue graphe", - "file.new_file": "Nouveau fichier", - "file.new_folder": "Nouveau dossier", - "file.properties": "Propriétés", - "file.rename": "Renommer", - "forge.popout": "Ouvrir dans une nouvelle fenêtre", - "forge.popout_label": "pop-out", - "forge.title_placeholder": "Titre...", - "graph.back": "Retour", - "graph.btn_directory": "📁 Dossier", - "graph.btn_full": "🌐 Tout", - "graph.cache_label": "(cache)", - "graph.category": "📂 Catégorie", - "graph.click_to_open": "cliquer pour ouvrir", - "graph.ctrl_hover_preview": "Ctrl+survol = aperçu complet", - "graph.ctrl_hover_preview_short": "Ctrl+survol = aperçu", - "graph.depth": "Profondeur", - "graph.depth_label": "prof={depth}", - "graph.edges_count": "{count} liens", - "graph.error_loading": "Erreur de chargement", - "graph.export_png": "Exporter PNG", - "graph.favorites": "Favoris", - "graph.filter_tag": "Filtrer par tag", - "graph.filter_type": "Filtrer par type", - "graph.focus_mode": "Mode focus", - "graph.forward": "Avancer", - "graph.fullscreen": "Plein écran", - "graph.loading": "Construction du graphe...", - "graph.nodes_count": "{count} nœuds", - "graph.parent": "Parent", - "graph.published": "Publié", - "graph.published_badge": "✅ publié", - "graph.scope_directory": "Dossier", - "graph.scope_full": "Vault complet", - "graph.title": "Vue Graphique — {vault}{path}", - "graph.type_directory": "Dossier", - "graph.type_file": "Fichier", - "graph.type_markdown": "Markdown", - "header.admin_panel": "Administration", - "header.config": "Configuration", - "header.help": "Aide", - "header.install_app": "Installer l'application", - "header.logo": "ObsiGate", - "header.logout": "Déconnexion", - "header.menu_about": "À propos", - "header.menu_about_desc": "Version, crédits & info", - "header.menu_admin": "Administration", - "header.menu_admin_desc": "Gérer les utilisateurs", - "header.menu_config": "Configurations", - "header.menu_config_desc": "Paramètres de l'application", - "header.menu_help": "Guide d'utilisation", - "header.menu_help_desc": "Ouvrir l'aide", - "header.menu_logout": "Déconnexion", - "header.menu_logout_desc": "Quitter la session", - "header.menu_profile": "Profil", - "header.menu_profile_desc": "Langue & préférences", - "header.menu_theme": "Thème", - "header.menu_theme_light": "Clair", - "header.menu_toggle": "Menu", - "header.profile": "Profil", - "header.quick_help": "Raccourcis & Astuces", - "header.refresh": "Rafraîchir", - "header.search_placeholder": "Rechercher dans toutes les vaults...", - "header.sidebar_toggle": "Afficher/Masquer la sidebar", - "header.sync_status": "Synchronisation", - "help.00b9572b": ":\n Résultats classés par pertinence TF-IDF", - "help.04df1506": ":\n Recherche globale avec autocomplétion", - "help.065f53ee": ":\n Auto-save silencieux après 2s d'inactivité,\n flash vert de confirmation", - "help.085ec31f": ":\n Sélection rapide en haut de l'onglet Vaults", - "help.096367af": "Indicateurs visuels", - "help.170a6982": ": Affichage\n horizontal avec le nom du fichier et son\n icône", - "help.229fd3e2": "Notification Discord", - "help.2507242f": "🏷️ Tags", - "help.29afa01d": "🪝 Webhooks", - "help.2a2e5b0f": "⌨️ Raccourcis clavier", - "help.2a92203f": "Trucs et astuces", - "help.2c03a7ba": "Tags inline vs frontmatter", - "help.2dad2bfd": "Sauvegarde automatique", - "help.381abec7": "Limitations actuelles", - "help.3cf370b1": "Mode commandes", - "help.40dd7e38": "Tester avec curl", - "help.4de7e318": ": Les 50\n dernières recherches (localStorage)", - "help.550b0240": "Exemples concrets", - "help.5ab8c78d": ":\n Restent ouverts jusqu'à fermeture manuelle", - "help.5d0fbb81": ":\n Workers, boosts TF-IDF, expansions préfixe", - "help.5f87ea79": "Tag cloud", - "help.61ee5a22": "Interaction", - "help.62308f96": "⌨️ Palette de commandes", - "help.62549eca": "💾 Sauvegardes et Audits", - "help.63f024d4": "Filtrage de tags template", - "help.686f8313": "💡 Astuces et bonnes pratiques", - "help.6a5ddef2": ": Les tags\n s'adaptent au vault sélectionné", - "help.6ae5342c": ": Stats index,\n mémoire, moteur de recherche", - "help.6b88a375": ":\n Délai debounce, résultats par page, timeout", - "help.6b8fc728": ": ↑/↓\n pour naviguer, Enter pour sélectionner", - "help.6d547397": "Mode fichiers", - "help.6e940dac": ": Cliquez sur\n l'icône sidebar dans le header", - "help.733f0559": "🗺️ Navigation", - "help.77f4f06e": "Format du payload", - "help.7bcbb2e3": "Redimensionnement de la sidebar", - "help.7db70e27": ": Copier,\n Source, Télécharger, Éditer, Ouvrir dans\n nouvelle fenêtre", - "help.83f1d9ca": "Protection", - "help.86e3825d": "🎨 Personnalisation", - "help.8717768b": ":\n Métadonnées du nœud (tags, liens, chemin)", - "help.89bd3c4c": ": N'affiche\n que les nœuds avec un tag spécifique", - "help.8c5341e0": "📑 Gestion des onglets", - "help.8c65b2f2": "🔗 Partage et Webhooks", - "help.8caed987": "Affichage", - "help.9c7a0a8d": "🗺️ Vue Graphe", - "help.9edeaa11": ":\n Contrôle la profondeur d'exploration (0-3)", - "help.9f78b3ec": ":\n Navigation facilitée dans les fichiers longs", - "help.a4a4e21b": ": Bouton \"×\" pour\n réinitialiser le filtre", - "help.a579cf4d": ": Aperçu du\n contenu de la note sans naviguer", - "help.a648c49e": "Facettes et tri", - "help.ab2c4150": ": Fichiers (carrés)\n et dossiers (cercles) avec icônes", - "help.about": "À propos", - "help.access": "Accès", - "help.action_buttons": "Boutons d'action", - "help.actions_available": "Boutons disponibles au-dessus du contenu :", - "help.actions_detail": "Boutons disponibles au-dessus du contenu :", - "help.activation": "Activation", - "help.active_filter_chips": "Chips de filtres actifs", - "help.active_tab": "Onglet actif", - "help.add_remove": "Ajout/Suppression", - "help.adf30d78": "🔍 Recherche", - "help.advanced_operators": "Opérateurs avancés", - "help.advanced_use_cases": "Cas d'usage avancés", - "help.ai_completes": "Complète", - "help.ai_features": "Édition, ton, traduction, génération et outils via AI.", - "help.ai_flash_green": "flashe en vert", - "help.ai_tone_casual": "Ton décontracté", - "help.all_vaults": "Tous les vaults", - "help.atomic_writes": "Atomic writes", - "help.audit_log": "Audit log", - "help.auto_save": "Sauvegarde automatique", - "help.auto_scroll": "Auto-scroll", - "help.autocomplete": "Autocomplétion", - "help.b6619ac9": "Ouverture", - "help.backlinks_panel": "Panneau Backlinks", - "help.backup_auto": "Backup automatique", - "help.before_write": "Avant écriture", - "help.breadcrumb": "Breadcrumb", - "help.breadcrumb_clickable": "Breadcrumb cliquable", - "help.breadcrumb_reposition": "Breadcrumb et repositionnement", - "help.c017944b": "📄 Fichiers", - "help.c48fb18a": "Authentification", - "help.c8532869": ":\n Complétion, réécriture, traduction (voir\n section", - "help.case_sensitive": "Case-sensitive", - "help.cf8615b1": "Visualisation", - "help.ci_cd": "Automatisation CI/CD", - "help.clear": "Effacer", - "help.clear_search": "Effacer", - "help.click_segment": "Cliquez sur un segment", - "help.click_tab": "Clic sur un onglet", - "help.click_vault": "Cliquez sur le vault", - "help.clickable": "Cliquable", - "help.close_help": "Fermer l'aide", - "help.close_tab_x": "Bouton ✕", - "help.code_preview": "Code + Prévisualisation", - "help.command_palette": "Palette de commande", - "help.configuration": "Configuration", - "help.content_area": "Zone de contenu", - "help.content_shows": "La zone centrale affiche :", - "help.context_actions": "Actions sur fichiers", - "help.context_menu": "Menu contextuel (clic droit)", - "help.copy_path": "Copier le chemin", - "help.d186a19e": ":\n L'onglet \"Récent\" dans la sidebar liste vos\n derniers fichiers", - "help.d1ea1dc6": "n8n / Make (no-code)", - "help.d5c977ac": ": Les blocs de\n code s'adaptent au thème", - "help.dark": "Sombre", - "help.dashboard": "Dashboard statistiques", - "help.delete": "Supprimer", - "help.desc_00b9572b": ":\n Résultats classés par pertinence TF-IDF", - "help.desc_04493800": ": 64\n caractères hexadécimaux, impossible à\n deviner", - "help.desc_065f53ee": ":\n Auto-save silencieux après 2s d'inactivité,\n flash vert de confirmation", - "help.desc_071da87a": "Lecture seule : La vue\n publique n'affiche que le contenu sans\n édition", - "help.desc_0739c6a9": "Images : Support complet\n des syntaxes Obsidian", - "help.desc_085ec31f": ":\n Sélection rapide en haut de l'onglet Vaults", - "help.desc_0f9a1e5b": "Utilisez le filtrage sidebar\n : Plus rapide que la recherche globale pour\n trouver un fichier", - "help.desc_11cf9e8a": "Éditer ▾ — Menu de\n modification du texte sélectionné :\n \n 🪄\n Improve writing :\n Améliore la qualité, la clarté et le\n flux du texte", - "help.desc_13d206d4": "📊\n Convert to table :\n Transforme en tableau Markdown", - "help.desc_13d90039": "ObsiGate permet de partager des documents via un\n lien public temporaire.", - "help.desc_1577912b": "Rate limiting : 10\n tentatives / 15 min par IP + verrouillage\n compte", - "help.desc_170a6982": ": Affichage\n horizontal avec le nom du fichier et son\n icône", - "help.desc_188bc423": "Pour plus d'informations, consultez le\n dépôt du projet.", - "help.desc_19cf5730": ": Rotation\n automatique à 10 Mo", - "help.desc_19cfa369": "L'éditeur sauvegarde automatiquement après 2\n secondes d'inactivité. Le bouton de sauvegarde\n flashe en vert brièvement pour\n confirmer.", - "help.desc_1a04ae18": "Masquez la sidebar : Plus\n d'espace pour le contenu", - "help.desc_1ba39cc4": ":\n Déclencher un build quand une note de\n procédure est mise à jour", - "help.desc_1c130d89": "— Traduit le\n texte sélectionné vers une autre langue :", - "help.desc_1f11691c": "Atomic writes : Écriture\n via fichier temporaire + renommage atomique", - "help.desc_2349271d": "Automatisation CI/CD :\n Déclencher un build quand une note de\n procédure est mise à jour", - "help.desc_26f81732": "Édition rapide : Ouvrez\n l'éditeur, modifiez, sauvegardez", - "help.desc_287be69c": ":\n Réduisez les sections Vaults/Tags selon vos\n besoins", - "help.desc_2c220763": "Gestion des liens : Liste\n et révocation dans les Configurations", - "help.desc_2f2c16b5": ": Publier un\n article de blog quand un fichier est marqué", - "help.desc_31e7253b": ": Chaque backup\n est horodaté", - "help.desc_32e3d66d": "En cas d'erreur de clé API :\n AI: clé API invalide", - "help.desc_39979e71": ":\n Choisissez un vault pour réduire le bruit", - "help.desc_39e97b2f": "Note : l'événement\n file_modified est réservé pour\n usage futur. Les modifications de contenu\n via l'éditeur ne déclenchent pas encore de\n webhook.", - "help.desc_3ace259e": "— Complétion inline\n (", - "help.desc_3c4711b8": "Événements tracés :\n Écritures, suppressions, changements de\n configuration", - "help.desc_3d4e9189": "📋\n Simplify language :\n Simplifie le langage, évite le\n jargon", - "help.desc_3da1896a": "Les webhooks peuvent être activés/désactivés,\n modifiés ou supprimés à tout moment. Le\n last_fired_at indique la dernière\n exécution.", - "help.desc_3db2812f": "X-ObsiGate-Signature: sha256=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08\n \n Pour vérifier côté récepteur : calculez\n HMAC-SHA256(corps_brut, secret) et\n comparez. Le header\n X-ObsiGate-Event contient aussi le\n type d'événement pour un routage rapide.", - "help.desc_40c92863": "Exploration par tags :\n Cliquez sur un tag dans une note pour voir\n toutes les notes similaires", - "help.desc_42a81347": ": Dernière\n modification", - "help.desc_443b76b5": "Wikilinks : Naviguez entre\n notes comme dans Obsidian", - "help.desc_47e1e10f": "Générer ▾ — Génère du\n contenu à partir de la sélection :\n \n ℹ️ Explain this :\n Explique le texte sélectionné de\n façon claire", - "help.desc_4de7e318": ": Les 50\n dernières recherches (localStorage)", - "help.desc_50a33a05": "⚙️\n Generate frontmatter\n : Génère un bloc YAML frontmatter", - "help.desc_5374685a": "Mobile-friendly : Utilisez\n le bouton hamburger sur mobile", - "help.desc_5396ed9e": "Profitez de l'historique :\n Réutilisez vos recherches fréquentes", - "help.desc_53bfaeca": ": Navigation par\n pages de 50 résultats", - "help.desc_5524e921": "Ton ▾ — Change le ton du\n texte :\n \n \n 💼 Professional :\n Ton formel et professionnel", - "help.desc_555e0305": "Pour changer de provider par défaut :\n AI_DEFAULT_PROVIDER=openrouter", - "help.desc_56760d7f": "Chaque webhook reçoit un POST avec\n Content-Type: application/json :", - "help.desc_58d2326f": "Navigation visuelle : Le\n breadcrumb repositionne automatiquement la\n sidebar", - "help.desc_599f3242": ": Logger\n toutes les modifications dans une base de\n données externe", - "help.desc_5a53de53": "📏 Make shorter :\n Rend le texte plus concis tout en\n préservant l'information", - "help.desc_5ab8c78d": ":\n Restent ouverts jusqu'à fermeture manuelle", - "help.desc_5d0fbb81": ":\n Workers, boosts TF-IDF, expansions préfixe", - "help.desc_5e9a7fd9": ": Liste\n et révocation dans les Configurations", - "help.desc_5fc28b7d": ": Créé\n automatiquement au premier démarrage", - "help.desc_625112fd": "Sélectionnez un contexte :\n Choisissez un vault pour réduire le bruit", - "help.desc_660051b0": "Audit externe : Logger\n toutes les modifications dans une base de\n données externe", - "help.desc_664b1d09": "Breadcrumb cliquable :\n Repositionnez rapidement la sidebar", - "help.desc_68c2b170": "Rotation : Rotation\n automatique à 10 Mo", - "help.desc_6902f20d": "Favorisez les opérateurs :\n tag: et\n vault: accélèrent la recherche", - "help.desc_698d92ec": "Gestion de l'espace :\n Réduisez les sections Vaults/Tags selon vos\n besoins", - "help.desc_6a5ddef2": ": Les tags\n s'adaptent au vault sélectionné", - "help.desc_6a80241e": ": La largeur\n est sauvegardée", - "help.desc_6ae5342c": ": Stats index,\n mémoire, moteur de recherche", - "help.desc_6b649b1e": ": Surligné en\n couleur d'accentuation", - "help.desc_6b88a375": ":\n Délai debounce, résultats par page, timeout", - "help.desc_6b8fc728": ": ↑/↓\n pour naviguer, Enter pour sélectionner", - "help.desc_6bc48f59": "Créez un\n Webhook Trigger dans n8n ou\n Make", - "help.desc_6caffeed": ": Cliquez pour\n filtrer les résultats", - "help.desc_6d68fbc9": "from flask import Flask, request\\nimport hmac, hashlib\\n\\napp = Flask(__name__)\\nWEBHOOK_SECRET = \"mon-secret\" # même que dans ObsiGate\\n\\n@app.route(\"/webhook\", methods=[\"POST\"])\\ndef webhook():\\n # Vérifier la signature\\n signature = request.headers.get(\"X-ObsiGate-Signature\", \"\")\\n body = request.get_data()\\n expected = \"sha256=\" + hmac.new(\\n WEBHOOK_SECRET.encode(), body, hashlib.sha256\\n ).hexdigest()\\n if not hmac.compare_digest(signature, expected):\\n return \"Invalid signature\", 403\\n\\n payload = request.get_json()\\n print(f\"Événement: {payload['event']}\")\\n print(f\"Fichier: {payload['data']['vault']}/{payload['data']['path']}\")\\n return \"OK\", 200\\n\\napp.run(port=5000)\n\n n8n / Make (no-code)\n \n \n Créez un\n Webhook Trigger dans n8n ou\n Make\n \n \n Copiez l'URL générée (ex:\n https://n8n.monserveur.com/webhook/abc123)\n \n \n Dans ObsiGate, ajoutez un webhook pointant\n vers cette URL\n \n Sélectionnez les événements souhaités\n \n Le workflow se déclenche automatiquement à\n chaque événement\n \n \n\n Notification Discord\n \n Utilisez un webhook relais (n8n, Make, ou un\n script) pour transformer le payload ObsiGate en\n message Discord :", - "help.desc_6ebebdfd": ": Chaque type\n d'opérateur a sa couleur", - "help.desc_6f7c5889": ": Alerter un\n canal Slack/Discord quand un document est\n créé", - "help.desc_71eeb16a": ":\n Réutilisez vos recherches fréquentes", - "help.desc_723ed8db": "Non-root Docker : Conteneur\n tourne avec UID 1000", - "help.desc_752789ab": ": Écriture\n via fichier temporaire + renommage atomique", - "help.desc_759926ee": "💬 Casual : Ton\n décontracté et conversationnel", - "help.desc_7671e56a": "Avant écriture : Sauvegarde\n du contenu original dans\n .obsigate-backup/", - "help.desc_7708f226": "JWT + Argon2id : Tokens JWT\n avec mots de passe hachés Argon2id", - "help.desc_7819b56f": "Copiez l'URL générée (ex:\n https://n8n.monserveur.com/webhook/abc123)", - "help.desc_7ab5be50": "Traduire ▾ — Traduit le\n texte sélectionné vers une autre langue :\n \n 🇬🇧 English · 🇨🇳 Chinese · 🇯🇵\n Japanese · 🇩🇪 German · 🇫🇷 French ·\n 🇪🇸 Spanish", - "help.desc_7b45490b": "Dans ObsiGate, ajoutez un webhook pointant\n vers cette URL", - "help.desc_7e86626c": "Bouton Partager : Dans les\n actions du fichier, génère un lien unique", - "help.desc_7f1d0512": "Path traversal : Validation\n des chemins contre les attaques\n ../", - "help.desc_7ff2fa21": "Pendant une requête AI, un toast\n ⏳ AI: traitement en cours...\n s'affiche", - "help.desc_803161e5": "La barre d'outils contient les boutons suivants\n :", - "help.desc_828db5da": ": Les\n deux types sont combinés", - "help.desc_858681a1": ":\n Durée de vie en heures", - "help.desc_85effb89": "Timeout de 5 secondes par\n requête — les webhooks sont \"fire and\n forget\" (pas de retry)", - "help.desc_8717768b": ":\n Métadonnées du nœud (tags, liens, chemin)", - "help.desc_87b348c3": "Recherche multi-critères :\n tag:docker tag:linux vault:IT\n nginx", - "help.desc_89a8f5de": "Déploiement : Publier un\n article de blog quand un fichier est marquépublish: true", - "help.desc_89bd3c4c": ": N'affiche\n que les nœuds avec un tag spécifique", - "help.desc_8f0bffe3": ": Tokens JWT\n avec mots de passe hachés Argon2id", - "help.desc_9186a3a3": "Explorez l'arborescence :\n Naviguez dans les dossiers", - "help.desc_93902d18": "Utilisez les tags : Filtrez\n par tags pour affiner", - "help.desc_9846fc07": ": Masque\n JWT, clés API, tokens GitHub dans les\n aperçus", - "help.desc_985d759b": "Token unique : 64\n caractères hexadécimaux, impossible à\n deviner", - "help.desc_991307d6": "— Génère du\n contenu à partir de la sélection :", - "help.desc_995a711f": ": Ouvre l'éditeur\n CodeMirror", - "help.desc_99c6f0ec": "Export : Téléchargez des\n fichiers pour backup ou partage", - "help.desc_9cb5974c": ": Ouvrez\n plusieurs notes dans des onglets séparés", - "help.desc_9d0e39d0": "Headers CSP :\n Content-Security-Policy, X-Frame-Options,\n XSS-Protection", - "help.desc_9edeaa11": ":\n Contrôle la profondeur d'exploration (0-3)", - "help.desc_9f321d1e": ":\n Écritures, suppressions, changements de\n configuration", - "help.desc_9f78b3ec": ":\n Navigation facilitée dans les fichiers longs", - "help.desc_9fec424d": ": Score\n TF-IDF (défaut)", - "help.desc_a0ec890a": "— Menu de\n modification du texte sélectionné :", - "help.desc_a13f7f2c": "Une fois terminé,\n AI: texte traité ✓ confirme\n le succès", - "help.desc_a4a4e21b": ": Bouton \"×\" pour\n réinitialiser le filtre", - "help.desc_a52fc3b1": ": Télécharge le\n fichier", - "help.desc_a579cf4d": ": Aperçu du\n contenu de la note sans naviguer", - "help.desc_a601f22e": "Allez dans ⚙️ Configurations → onglet\n Webhooks", - "help.desc_a69804cd": "Répertoire dédié :\n .obsigate-backup/ dans le\n répertoire de la vault", - "help.desc_a6cb3b26": "🔤\n Fix spelling & grammar\n : Corrige les fautes d'orthographe\n et de grammaire", - "help.desc_a974f7a6": "Journal : Fichier\n data/audit.log au format JSON\n lines", - "help.desc_a9c2c520": "Les webhooks permettent à ObsiGate de\n notifier automatiquement des services\n externes\n lorsque des fichiers ou dossiers sont modifiés.\n Chaque événement déclenche un\n POST HTTP vers l'URL de votre\n choix, avec un payload JSON détaillé.", - "help.desc_a9db82b5": ": Centre la vue\n sur un nœud spécifique", - "help.desc_ab2c4150": ": Fichiers (carrés)\n et dossiers (cercles) avec icônes", - "help.desc_action_buttons": "Copier, Source, Télécharger, Éditer, Ouvrir dans nouvelle fenêtre", - "help.desc_adv_syntax": ":\n Python, JS, HTML, CSS, Java, C++, Rust, Go\n et bien d'autres", - "help.desc_ae213f54": ":\n Combinez opérateurs et texte libre", - "help.desc_aec0ad2c": "💬 Réécrire — Réécrit le\n texte selon vos instructions personnalisées.\n Une boîte de dialogue vous demande votre\n instruction.", - "help.desc_all_tags": ": Extraits des frontmatters YAML et inline (#tag)", - "help.desc_all_vaults": ": Vue globale de tous vos contenus", - "help.desc_autoscroll": ": La sidebar se positionne automatiquement", - "help.desc_b54c21ef": "Contrôle d'accès par vault\n : Chaque utilisateur voit uniquement ses\n vaults", - "help.desc_b5f89b3b": "ObsiGate intègre un assistant IA directement\n dans l'éditeur de texte. Pour l'activer,\n configurez au moins un provider AI dans le\n fichier .env (DeepSeek, OpenRouter\n ou Gemini).", - "help.desc_b6169f2e": "Les webhooks se gèrent dans le modal\n Configurations (⚙️ menu\n Options), section Webhooks. Réservé aux\n administrateurs.", - "help.desc_b9c94994": ": Aperçu de\n la regex appliquée", - "help.desc_ba4578ae": "Redémarrez le conteneur :\n docker compose down && docker compose\n up -d --build", - "help.desc_bc08f215": "Secret redactor : Masque\n JWT, clés API, tokens GitHub dans les\n aperçus", - "help.desc_beed5686": ": Cliquez sur\n \"Thème\" dans le menu", - "help.desc_breadcrumb": "Chemin du fichier (cliquable pour repositionner la sidebar)", - "help.desc_c1f72521": "{\n \"event\": \"file_created\",\n \"timestamp\": \"2026-06-03T14:30:00.123456+00:00\",\n \"data\": {\n \"vault\": \"IT\",\n \"path\": \"procedures/deploiement.md\"\n }\n}\n\n Sécurité : signature HMAC-SHA256\n \n Si vous configurez un secret, chaque requête\n inclut un header\n X-ObsiGate-Signature :", - "help.desc_c63f02cc": "— Réécrit le\n texte selon vos instructions personnalisées.\n Une boîte de dialogue vous demande votre\n instruction.", - "help.desc_c8532869": ":\n Complétion, réécriture, traduction (voir\n section", - "help.desc_c992f2e5": "Remplissez :\n Nom (descriptif),\n URL (endpoint cible),\n Secret (optionnel)", - "help.desc_case_sensitive": ": Bouton \"Aa\" pour respecter la casse", - "help.desc_cb6f0bfd": ": Ouvrez\n l'éditeur, modifiez, sauvegardez", - "help.desc_cc8e35ba": "Notifications : Alerter un\n canal Slack/Discord quand un document est\n créé", - "help.desc_cdf7bb46": "Recherchez intelligemment :\n Combinez opérateurs et texte libre", - "help.desc_cf5ccd40": ": Compteurs\n par tag dans les résultats", - "help.desc_cfe362a7": "Export PDF : Téléchargement\n du document partagé en PDF via/s/{token}/pdf", - "help.desc_check_btn": ": Sauvegarde\n manuelle", - "help.desc_chip_remove": ": Cliquez sur \"×\" pour retirer un filtre", - "help.desc_chip_view": ": Voir d'un coup d'œil les filtres actifs", - "help.desc_click_segment": ": Navigation vers ce dossier", - "help.desc_click_tab": ": Active l'onglet", - "help.desc_click_vault": ": Focus sur le vault dans la sidebar", - "help.desc_close_btn": ": Ferme l'onglet (sauf s'il est seul)", - "help.desc_cm_autocomplete": ":\n Suggestions contextuelles", - "help.desc_cm_lines": ":\n Navigation facile", - "help.desc_cm_search": ": Ctrl+F pour\n chercher dans le fichier", - "help.desc_cm_syntax": ":\n Support de nombreux langages", - "help.desc_combined": "recherche \"serveur web\" dans les fichiers\n Markdown du vault IT avec le tag linux.", - "help.desc_context_menu": ": Clic\n droit sur un vault ou dossier → Vue\n Graphique", - "help.desc_copy_btn": ": Copie le contenu\n source dans le presse-papiers", - "help.desc_ctrl_tab": ": Onglet suivant", - "help.desc_ctrl_w": ": Fermer l'onglet actif", - "help.desc_d186a19e": ":\n L'onglet \"Récent\" dans la sidebar liste vos\n derniers fichiers", - "help.desc_d3a71d97": "file_modified n'est pas encore\n dispatché (réservé pour version future)", - "help.desc_d5c977ac": ": Les blocs de\n code s'adaptent au thème", - "help.desc_d646b709": "Compte admin : Créé\n automatiquement au premier démarrage", - "help.desc_d66e911c": ": Dans les\n actions du fichier, génère un lien unique", - "help.desc_d915c72b": "Synchronisation : Copier\n les nouveaux fichiers vers un autre système\n (SharePoint, Google Drive)", - "help.desc_d9cdaa89": ": Copier\n les nouveaux fichiers vers un autre système\n (SharePoint, Google Drive)", - "help.desc_d9e8ab0b": "🧰 Boîte ▾ — Outils de\n conversion :\n \n \n 📋\n Convert to list :\n Transforme le texte en liste\n Markdown", - "help.desc_dc4d7186": "Les modifications détectées par le watcher\n filesystem (watchdog)\n ne déclenchent pas de\n webhooks — seules les opérations via l'API\n REST sont prises en compte", - "help.desc_delete_btn_new": ": Bouton\n corbeille pour supprimer", - "help.desc_double_click": ": Ouvre le fichier dans un onglet persistant", - "help.desc_e0525213": "✦ AI — Complétion inline\n (Ctrl+J). Complète\n automatiquement le texte là où se trouve le\n curseur.", - "help.desc_e23c94dd": ": Dans la\n barre d'outils (le cas échéant)", - "help.desc_e36f3eaa": "📐 Make longer :\n Ajoute des détails, exemples ou\n explications", - "help.desc_e3fce7a3": ": Ouvre le\n fichier dans un onglet temporaire (aperçu,\n italique)", - "help.desc_e47d2328": ": La vue\n publique n'affiche que le contenu sans\n édition", - "help.desc_e5246734": ": Onglet\n précédent", - "help.desc_e5b67e3d": ": Votre choix\n est sauvegardé en localStorage", - "help.desc_e5cf90b2": "📝 Summarize :\n Résume le texte de façon concise", - "help.desc_e6129268": "Confort de lecture :\n Ajustez la largeur de la sidebar", - "help.desc_e7e3157a": "Timestamp : Chaque backup\n est horodaté", - "help.desc_e93517a5": ": Téléchargement\n du document partagé en PDF via", - "help.desc_ec5f7a26": "Expiration configurable :\n Durée de vie en heures", - "help.desc_ecf302ae": "Multi-fenêtres : Ouvrez\n plusieurs notes dans des onglets séparés", - "help.desc_edges": ": Wikilinks sortants\n (bleu) et backlinks entrants (vert)", - "help.desc_eebf177f": "ObsiGate v1.7.0 - Porte\n d'entrée web pour vos vaults Obsidian", - "help.desc_ef1531ce": ": Un\n onglet temporaire (italique) est remplacé\n par le prochain clic", - "help.desc_ef3f8158": ": Gérez\n vos patterns de filtrage", - "help.desc_examples": ":\n ext:sh recherche dans les scripts\n bash, ext:py dans les scripts\n Python, ext:md dans les fichiers\n Markdown.\n

    ", - "help.desc_expand": ": Cliquez sur un dossier", - "help.desc_export_png": ": Sauvegardez le\n graphe en image", - "help.desc_f0adf67a": ": Molette pour\n zoomer, cliquer-glisser pour se déplacer", - "help.desc_f2d4e369": "✏️\n Continue writing :\n Continue l'écriture à partir du\n texte", - "help.desc_f53badcd": "Ajoutez votre clé API dans\n .env :\n DEEPSEEK_API_KEY=sk-...", - "help.desc_f58da6e1": "Cliquez Ajouter", - "help.desc_f9083ce5": ": Téléchargez des\n fichiers pour backup ou partage", - "help.desc_f952db17": "Refresh tokens : Cookies\n HttpOnly avec rotation automatique", - "help.desc_fa126609": "🔷\n Convert to canvas :\n Convertit en diagramme Mermaid.js", - "help.desc_facet_vaults": ": Compteurs par vault", - "help.desc_fc9391f3": "# Exemple avec curl + jq dans un script bash\nWEBHOOK_URL=\"https://discord.com/api/webhooks/...\"\nOBSIGATE_SECRET=\"mon-secret\"\n\n# Lire le payload depuis stdin\nread -r payload\nevent=$(echo \"$payload\" | jq -r '.event')\npath=$(echo \"$payload\" | jq -r '.data.path')\n\ncurl -H \"Content-Type: application/json\" -d \"{\n \\\"content\\\": \\\"📝 **$event** — $path\\\"\n}\" \"$WEBHOOK_URL\"\n\n Tester avec curl\n # Simuler ce qu'ObsiGate envoie (pour tester votre endpoint)\ncurl -X POST https://votre-serveur.com/webhook \\\n -H \"Content-Type: application/json\" \\\n -H \"X-ObsiGate-Event: file_created\" \\\n -H \"X-ObsiGate-Signature: sha256=$(echo -n '{\"event\":\"file_created\",...}' | openssl dgst -sha256 -hmac 'mon-secret' | cut -d' ' -f2)\" \\\n -d '{\"event\":\"file_created\",\"timestamp\":\"2026-06-03T14:30:00Z\",\"data\":{\"vault\":\"IT\",\"path\":\"notes/test.md\"}}'\n\n Limitations actuelles\n \n \n Timeout de 5 secondes par\n requête — les webhooks sont \"fire and\n forget\" (pas de retry)\n \n \n Les modifications détectées par le watcher\n filesystem (watchdog)\n ne déclenchent pas de\n webhooks — seules les opérations via l'API\n REST sont prises en compte\n \n \n file_modified n'est pas encore\n dispatché (réservé pour version future)\n \n Pas de retry automatique en cas d'échec\n \n Pas de filtrage par vault — un webhook\n écoute toutes les vaults\n \n \n \n \n 💾 Sauvegardes et Audits\n\n Backup automatique\n \n ObsiGate crée automatiquement des sauvegardes\n avant chaque modification destructive.", - "help.desc_fdeaf803": ": Chaque type de\n fichier a son icône (markdown, code, etc.)", - "help.desc_file_suggest": ": Suggestions de titres de fichiers", - "help.desc_filter_type": ":\n Inclut/exclut fichiers, dossiers, markdown,\n autres", - "help.desc_filter_usage": "Utilisez la barre de filtrage en haut de la sidebar pour rechercher rapidement :", - "help.desc_filtering": "Barre de recherche pour filtrer fichiers/tags", - "help.desc_find_in_page": ": Ctrl+F pour\n chercher dans le fichier (casse, regex, mot\n entier)", - "help.desc_frontmatter": ": tags: [docker, linux] ou tags: docker, linux", - "help.desc_fullscreen": ": Bouton pour\n agrandir la vue", - "help.desc_graph_intro": "La vue graphe offre une visualisation\n interactive des connexions entre vos notes via\n les wikilinks.", - "help.desc_graph_nav": ":\n Historique de navigation entre les nœuds", - "help.desc_grouped_results": ": Affichage par vault avec chemins complets", - "help.desc_hamburger": "(mobile) : Affiche/masque la sidebar", - "help.desc_hide": "Cliquez sur l'icône sidebar dans le header", - "help.desc_images": ": Support\n de ![[image.png]]", - "help.desc_inline_tags": ": #docker dans le contenu markdown", - "help.desc_instant_filter": ": Tapez pour filtrer fichiers et dossiers", - "help.desc_logo": "Retour à l'accueil", - "help.desc_markdown_all": ":\n Rendu complet du markdown", - "help.desc_md_render": "Les fichiers markdown sont rendus avec :", - "help.desc_menu_header": ": Dropdown \"Vault\" dans le menu Options", - "help.desc_menu_options": ": Accès aux\n paramètres, thème, aide", - "help.desc_op_ext": ": Filtrer par type de fichier", - "help.desc_op_path": ": Filtrer par chemin", - "help.desc_op_phrase": ": Recherche de phrase entre guillemets", - "help.desc_op_tag": ": Filtrer par tag", - "help.desc_op_title": ": Chercher dans les titres uniquement", - "help.desc_op_vault": ": Rechercher dans un vault spécifique", - "help.desc_open_file": ": Cliquez sur le nom du fichier", - "help.desc_open_new": ": Ouvre le fichier dans un nouvel onglet", - "help.desc_patterns": ": Ex: #<% ... %> ou #{{ ... }}", - "help.desc_quick_select": "Dropdown pour changer de vault", - "help.desc_rendered_content": "Markdown avec wikilinks et images", - "help.desc_resize": "Glissez le bord droit pour ajuster la largeur", - "help.desc_save_btn_new": ": Bouton ✓ pour\n enregistrer", - "help.desc_search_all": ": Titre, contenu, tags, chemins", - "help.desc_search_bar": "Recherche globale avec autocomplétion", - "help.desc_search_intro": "

    \n Tapez dans la barre de recherche en haut pour\n lancer une recherche fulltext :\n

    ", - "help.desc_sidebar_toggle": "Masque la sidebar pour plus d'espace", - "help.desc_snippets": ": Extraits avec termes en surbrillance", - "help.desc_source_btn": ": Affiche/masque le\n markdown brut", - "help.desc_specific_vault": ": Focus sur un seul vault", - "help.desc_syntax_hl": ":\n Coloration des blocs de code", - "help.desc_tag_cloud_intro": "

    \n L'onglet Tags de la sidebar affiche un nuage de\n tags :\n

    ", - "help.desc_tag_filter_use": ": Utilisez la barre de filtrage pour chercher un tag", - "help.desc_tag_suggest": ": Suggestions de tags avec compteurs", - "help.desc_tags_tab": "Nuage de tags cliquables", - "help.desc_template_intro": "

    \n Dans les Configurations, vous pouvez masquer les\n tags de template :\n

    ", - "help.desc_title_tags": "Métadonnées du fichier", - "help.desc_trash_btn": ": Suppression du\n fichier", - "help.desc_two_tag_types": "

    ObsiGate supporte deux types de tags :

    ", - "help.desc_vault_context": "Changez de contexte pour filtrer l'affichage :", - "help.desc_vault_indicator": "Affiche le contexte actif (All, vault1, etc.)", - "help.desc_vaults_tab": "Arborescence des fichiers et dossiers", - "help.desc_visual_search": ": Barre\n de recherche pour surligner des nœuds", - "help.desc_wikilinks": ":\n [[lien]] et\n [[lien|texte]]", - "help.double_click": "Double clic", - "help.drag_drop_tabs": "Drag & drop des onglets", - "help.e23c94dd": ": Dans la\n barre d'outils (le cas échéant)", - "help.e3fce7a3": ": Ouvre le\n fichier dans un onglet temporaire (aperçu,\n italique)", - "help.e5b67e3d": ": Votre choix\n est sauvegardé en localStorage", - "help.editor_section": "Éditeur", - "help.ef1531ce": ": Un\n onglet temporaire (italique) est remplacé\n par le prochain clic", - "help.experience": "Expérience", - "help.export": "Export", - "help.external_audit": "Audit externe", - "help.f0adf67a": ": Molette pour\n zoomer, cliquer-glisser pour se déplacer", - "help.fallback_editor": "Éditeur de fallback", - "help.fdeaf803": ": Chaque type de\n fichier a son icône (markdown, code, etc.)", - "help.fe388b67": "Optimisations", - "help.file_actions": "Actions sur le fichier ouvert :", - "help.file_viewer": "Visionneur de fichier", - "help.filter_toggles": "Toggles Aa, wd, .*", - "help.filtering": "Filtrage", - "help.find_capabilities": "Recherche regex, mot entier, case-sensitive dans le document affiché avec TreeWalker DOM.", - "help.find_in_page": "Recherche dans la page", - "help.footer": "© 2026 — Fait avec ☕, 🎧 et quelques", - "help.graph_context": "Menu contextuel", - "help.graph_depth": "Slider de profondeur", - "help.graph_export": "Export PNG", - "help.graph_filter_depth": "Filtres & profondeur", - "help.graph_focus": "Mode focus", - "help.graph_fullscreen": "Plein écran & export PNG", - "help.graph_info": "Panneau d'info", - "help.graph_nav_arrows": "Navigation ← → ↑", - "help.graph_navigation": "Navigation historique ← → ↑", - "help.graph_nodes": "Nœuds", - "help.graph_preview": "Ctrl+survol", - "help.graph_sticky": "Sticky panels", - "help.graph_tag_filter": "Filtre par tag", - "help.graph_type_filter": "Filtre par type", - "help.graph_view": "Vue graphe", - "help.graph_visual": "Recherche visuelle", - "help.graph_zoom": "Zoom/Pan", - "help.graph_zoom_pan": "Zoom & pan molette", - "help.guide_official": "Guide officiel", - "help.hamburger_btn": "Bouton menu hamburger", - "help.header_section": "En-tête", - "help.help_title": "Aide", - "help.hide": "Masquage", - "help.hide_help": "Masquer l'aide", - "help.highlighted_snippets": "Snippets surlignés", - "help.indexes": "ObsiGate indexe et affiche :", - "help.instant": "Instantanée", - "help.light": "Clair", - "help.logo": "Logo ObsiGate", - "help.markdown": "Syntaxe Markdown", - "help.menu_header": "Menu header", - "help.menu_options": "Menu Options", - "help.mermaid_section": "Diagrammes Mermaid", - "help.mermaid_templates": "Templates", - "help.mobile": "Barre flottante résultats", - "help.modal_title": "Guide d'utilisation ObsiGate", - "help.multi_vault": "Multi-vault", - "help.nav_ai": "🤖 IA Éditeur", - "help.nav_backups": "💾 Sauvegardes", - "help.nav_customization": "🎨 Personnalisation", - "help.nav_editing": "✏️ Édition", - "help.nav_files": "📁 Fichiers", - "help.nav_graph": "🗺️ Graphe", - "help.nav_interface": "🧭 Interface", - "help.nav_intro": "📘 Introduction", - "help.nav_navigation": "🗺️ Navigation", - "help.nav_palette": "⌨️ Palette", - "help.nav_search": "🔍 Recherche", - "help.nav_security": "🛡️ Sécurité", - "help.nav_sharing": "🔗 Partage", - "help.nav_shortcuts": "⌨️ Raccourcis", - "help.nav_tabs": "📑 Onglets", - "help.nav_tags": "🏷️ Tags", - "help.nav_tips": "💡 Astuces", - "help.nav_webhooks": "🪝 Webhooks", - "help.new_file": "Nouveau fichier", - "help.new_folder": "Nouveau dossier", - "help.nights": "nuits blanches 😅", - "help.nodes_edges": "Arêtes", - "help.other": "Autres", - "help.outline_panel": "Panneau Plan (droite)", - "help.pagination": "Pagination", - "help.pal_close_the_palette": "Fermer la palette", - "help.pal_delete_a_folder_and_its_contents": "Supprime un dossier et son contenu", - "help.pal_delete_the_file_from_the_active_tab": "Supprime le fichier de l'onglet actif", - "help.pal_move_desc": "Se déplacer dans la liste", - "help.pal_open___select": "Ouvrir/sélectionner", - "help.pal_open_the_editor_on_the_active_tab": "Ouvre l'éditeur sur l'onglet actif", - "help.pal_open_this_guide": "Ouvre ce guide", - "help.pal_popout_desc": "Ouvre le document dans une fenêtre détachée", - "help.pal_toggle_light_dark": "Bascule clair/sombre", - "help.pdf_export": "Export PDF", - "help.persistent_display": "Affichage persistant dans la barre", - "help.persistent_tabs": "Onglets persistants", - "help.popout_button": "Bouton dédié", - "help.powered_by": "Propulsé par Python, FastAPI, vanilla JS, CodeMirror, Mermaid, Lucide Icons et ❤️ pour Obsidian.", - "help.preview_tab": "Prévisualisation", - "help.properties": "Propriétés", - "help.public_shares": "Publication publique", - "help.pwa_section": "PWA", - "help.quick_help": "Raccourcis & Astuces", - "help.quick_select": "Sélection rapide", - "help.rate_limiting": "Rate limiting", - "help.recent_nav": "Navigation récente", - "help.rename": "Renommer", - "help.rendered_content": "Contenu rendu", - "help.rendering_images": "Rendu d'images", - "help.rendering_md": "Rendu dans le Markdown", - "help.resize": "Redimensionnement", - "help.results_counter": "Compteur de résultats", - "help.results_grouped": "Résultats groupés", - "help.search_bar": "Barre de recherche", - "help.search_dropdown": "Dropdown de recherche", - "help.search_everywhere": "Recherche dans tout", - "help.search_facets": "Facettes", - "help.search_filters": "Filtres de recherche", - "help.search_history": "Historique de recherche", - "help.search_operators": "Opérateurs de recherche", - "help.search_placeholder": "Rechercher dans l'aide...", - "help.search_save": "Recherches sauvegardées", - "help.secret_redaction": "Redaction de secrets", - "help.security_section": "Sécurité", - "help.share_button": "Bouton Partager", - "help.shortcut_ai_completion": "Completion IA inline (dans l'éditeur)", - "help.shortcut_close": "Fermer l'éditeur / modale", - "help.shortcut_close_editor": "Fermer l'éditeur / modale", - "help.shortcut_close_palette": "Fermer la palette", - "help.shortcut_close_tab": "Fermer l'onglet", - "help.shortcut_command_palette": "Palette de commandes", - "help.shortcut_file_palette": "Palette de fichiers (nav. rapide)", - "help.shortcut_focus_search": "Focus barre de recherche", - "help.shortcut_forge_help": "Aide de l'éditeur Forge", - "help.shortcut_next_tab": "Onglet suivant", - "help.shortcut_palette": "Palette de commandes", - "help.shortcut_palette_cmd": "Palette de commandes (mode commande)", - "help.shortcut_prev_tab": "Onglet précédent", - "help.shortcut_quick_insert": "Insertion rapide (éditeur Forge)", - "help.shortcut_quick_search": "Recherche rapide (hors champ texte)", - "help.shortcut_redo": "Refaire", - "help.shortcut_save": "Sauvegarder", - "help.shortcut_save_file": "Sauvegarder le fichier ouvert", - "help.shortcut_search_doc": "Rechercher dans le document", - "help.shortcut_select": "Ouvrir/sélectionner", - "help.shortcut_tip": "Survolez un document avec Ctrl pour un aperçu rapide. Cliquez sur Forge dans la barre d'outils pour l'éditeur avancé.", - "help.shortcut_undo": "Annuler", - "help.shortcuts": "Raccourcis clavier", - "help.shortcuts_title": "Raccourcis & Astuces", - "help.sidebar_dropdown": "Sidebar dropdown", - "help.sidebar_features": "Fonctionnalités de la sidebar :", - "help.sidebar_filtering": "Filtrage de la sidebar", - "help.sidebar_section": "Sidebar (barre latérale)", - "help.sidebar_tabs": "La sidebar est divisée en deux onglets :", - "help.sidebar_toggle_btn": "Bouton toggle sidebar", - "help.simple": "Simple", - "help.simple_search": "Recherche simple", - "help.single_click": "Simple clic", - "help.smart_scoring": "Scoring intelligent", - "help.sort_options": "Options de tri", - "help.supported_languages": "Support de nombreux langages", - "help.syncthing": "Conflits Syncthing", - "help.syncthing_conflicts": "Conflits Syncthing", - "help.tab_bar": "Barre d'onglets", - "help.tab_features": "Fonctionnalités", - "help.tab_nav": "Navigation entre onglets", - "help.tabs_section": "Ouverture d'onglets", - "help.theme_section": "Thème", - "help.theme_sync": "Thème synchronisé", - "help.theme_toggle": "Basculez entre les thèmes :", - "help.themes": "Thèmes", - "help.tip_hide_sidebar": "Masquez la sidebar", - "help.tip_sidebar_filter": "Utilisez le filtrage sidebar", - "help.tip_use_tags": "Utilisez les tags", - "help.title": "Aide ObsiGate", - "help.title_tags": "Titre et tags", - "help.toc_title": "SOMMAIRE", - "help.toolbar_section": "Barre d'outils AI", - "help.tree_section": "Arborescence des vaults", - "help.use_cases": "Cas d'usage", - "help.vault_indicator": "Indicateur de vault", - "help.vault_selector": "Sélection de vault", - "help.vault_specific": "Vault spécifique", - "help.webhook_blog_post": "article de blog quand un fichier est marqué", - "help.webhook_note": "Note : l'événement", - "help.webhook_notify": "notifier automatiquement des services", - "help.webhook_post": "HTTP vers l'URL de votre", - "help.webhooks": "Webhooks", - "help.welcome_desc": "ObsiGate est votre porte d'entrée web vers vos vaults Obsidian. Accédez, naviguez et recherchez dans toutes vos notes depuis n'importe quel appareil via une interface moderne et responsive.", - "help.welcome_tag1": "⚡ Navigation rapide", - "help.welcome_tag2": "📁 Multi-vault", - "help.welcome_tag3": "🏷️ Tags intelligents", - "help.welcome_tag4": "📖 Lecture et édition", - "help.welcome_tag5": "🔍 Recherche TF-IDF", - "help.welcome_title": "Bienvenue dans ObsiGate", - "help.wikilinks": "Wikilinks", - "help.zoom_pan": "Zoom & Pan", - "mermaid.code": "Code", - "mermaid.copy_svg": "Copier SVG", - "mermaid.download_png": "Télécharger PNG", - "mermaid.preview": "Aperçu", - "mermaid.zoom_in": "Zoom avant", - "mermaid.zoom_out": "Zoom arrière", - "mobile.all_vaults": "📂 Toutes les vaults", - "modal.create_btn": "Créer", - "modal.create_file": "Créer un fichier", - "modal.creating": "Création...", - "modal.delete_dir": "Supprimer le dossier", - "modal.delete_dir_warning": "Tous les fichiers et sous-dossiers seront supprimés définitivement.", - "modal.delete_file": "Supprimer le fichier", - "modal.delete_irreversible": "Cette action est irréversible.", - "modal.delete_permanently": "Supprimer définitivement", - "modal.delete_warning": "Attention !", - "modal.dir_to_delete": "Dossier à supprimer:", - "modal.file_name": "Nom du fichier", - "modal.file_to_delete": "Fichier à supprimer:", - "modal.file_type": "Type de fichier", - "modal.in_folder": "Dans: {path}", - "month.april": "Avril", - "month.august": "Août", - "month.december": "Décembre", - "month.february": "Février", - "month.january": "Janvier", - "month.july": "Juillet", - "month.june": "Juin", - "month.march": "Mars", - "month.may": "Mai", - "month.november": "Novembre", - "month.october": "Octobre", - "month.september": "Septembre", - "offline.all_synced": "Toutes les modifications ont été synchronisées", - "offline.conflict_title": "Conflit de synchronisation", - "offline.keep_local": "Garder version locale", - "offline.keep_server": "Garder version serveur", - "offline.mode_offline": "Mode hors-ligne — vos modifications seront synchronisées au retour", - "offline.pending": "{count} modification(s) en attente", - "offline.reconnected": "Connexion rétablie — synchronisation en cours...", - "offline.status": "Hors-ligne", - "offline.sync_now": "Synchroniser maintenant", - "palette.browse_dirs": "📂 Parcourir les répertoires...", - "palette.browse_hint": "Naviguer dans les vaults pour trouver un fichier", - "palette.browse_in": "Dans {path}", - "palette.browse_no_results": "Aucun résultat — naviguer manuellement", - "palette.browse_open_file": "📂 Ouvrir un fichier dans ce dossier", - "palette.browse_root": "racine", - "palette.close_current": "Fermer fichier courant", - "palette.close_current_desc": "Fermer l'onglet actif sans supprimer", - "palette.cmd_back_home": "🏠 Accueil", - "palette.cmd_back_home_desc": "Retour à l'accueil", - "palette.cmd_config": "⚙️ Configuration", - "palette.cmd_config_desc": "Ouvrir les paramètres", - "palette.cmd_create_dir": "📁 Créer répertoire", - "palette.cmd_create_dir_desc": "Choisir la vault, naviguer, puis nommer le dossier", - "palette.cmd_create_file": "📄 Créer fichier markdown", - "palette.cmd_create_file_desc": "Choisir la vault, naviguer, puis nommer le fichier", - "palette.cmd_delete_dir": "🗑️ Supprimer répertoire", - "palette.cmd_delete_dir_desc": "Choisir la vault, naviguer et supprimer", - "palette.cmd_theme": "🌓 Changer le thème", - "palette.cmd_theme_desc": "Basculer clair/sombre", - "palette.del_all_content": "Tout le contenu sera supprimé", - "palette.delete_current": "Supprimer fichier courant", - "palette.delete_current_desc": "Supprimer le fichier de l'onglet actif", - "palette.delete_file_desc": "Rechercher un fichier à supprimer", - "palette.dir_delete_confirm": "Tout le contenu sera supprimé", - "palette.dir_name": "Nom du dossier", - "palette.empty_dir": "📂 Dossier vide", - "palette.error_loading": "Erreur de chargement", - "palette.error_prefix": "Erreur : {msg}", - "palette.file_name": "Nom du fichier", - "palette.help_desc": "Ouvrir le guide", - "palette.md_hint": "(.md ajouté si besoin)", - "palette.mode_commands": "Commandes", - "palette.mode_files": "Fichiers", - "palette.no_results": "Aucun résultat pour \"{query}\"", - "palette.no_vaults": "Aucune vault trouvée", - "palette.popout_desc": "Ouvrir le document dans une fenêtre", - "palette.reindex_desc": "Forcer la réindexation complète", - "palette.search_commands": "Tapez une commande...", - "palette.search_error": "Erreur de recherche", - "palette.search_files": "Rechercher un fichier...", - "palette.type_command": "Tapez une commande...", - "palette.type_search": "Rechercher un fichier... (+inclure -exclure)", - "palette.vault_count": "{count} fichiers", - "pwa.dismiss": "Plus tard", - "pwa.install_button": "Installer", - "pwa.install_desc": "Installez cette application sur votre appareil pour un accès rapide.", - "pwa.install_title": "Installer ObsiGate", - "search.advanced_operators": "Opérateurs avancés", - "search.aria_label": "Suggestions de recherche", - "search.case_sensitive": "Respecter la casse", - "search.clear": "Effacer", - "search.dropdown_clear_history": "Effacer l'historique", - "search.dropdown_files": "Fichiers", - "search.dropdown_history": "Historique", - "search.error": "Erreur de recherche", - "search.exclude_placeholder": "Exclure: vendor/*, *.lock", - "search.facet_tags": "Tags", - "search.facet_vaults": "Vaults", - "search.files_filtered": "{count} fichier(s) avec filtres", - "search.filter_path_title": "Filtres de chemin (Alt-F)", - "search.filters": "Filtres", - "search.full_text": "Recherche dans tout", - "search.highlighted_snippets": "Snippets surlignés", - "search.include_placeholder": "Inclure: **/*.md, notes/**", - "search.loading": "Recherche en cours...", - "search.no_results": "Aucun résultat trouvé", - "search.operators_help": "Opérateurs : tag:mot, vault:nom, title:mot, path:mot, ext:md", - "search.pagination": "Pagination", - "search.previous": "← Précédent", - "search.query_time": "({time} ms)", - "search.regex": "Expression régulière", - "search.results_count": "{count} résultat(s)", - "search.results_filtered": "{count} résultat(s) pour \"{query}\" avec filtres", - "search.results_for": "{count} résultat(s) pour \"{query}\"", - "search.save_search": "Sauvegarder la recherche", - "search.saved": "Recherche sauvegardée", - "search.sections_all_vaults": "Tous les vaults", - "search.simple_search": "Recherche simple", - "search.smart_scoring": "Scoring intelligent", - "search.sort_date": "Date", - "search.sort_relevance": "Pertinence", - "search.sort_title": "Titre", - "search.whole_word": "Mot entier", - "settings.about": "📦 À propos", - "settings.ai": "🤖 IA", - "settings.backend": "⚙️ Backend", - "settings.backend_hint": "Ces paramètres sont sauvegardés sur le serveur. Certains nécessitent un redémarrage ou une réindexation.", - "settings.backend_section": "Paramètres backend", - "settings.client_label": "Ces paramètres s'appliquent immédiatement côté client.", - "settings.diagnostics": "🩺 Diagnostics", - "settings.history_count_desc": "Entre 5 et 100 fichiers (sauvegarde sur le serveur)", - "settings.history_count_label": "Nombre de fichiers dans l'historique", - "settings.history_section": "Historique récent", - "settings.no_restart_badge": "Redémarrage non requis", - "settings.profile": "👤 Profil", - "settings.reindex": "Forcer réindexation", - "settings.restart_badge": "Redémarrage requis", - "settings.save": "Sauvegarder", - "settings.search": "Recherche", - "settings.tabs": "Tabs", - "settings.search_placeholder": "Rechercher...", - "settings.sync": "🔄 Synchronisation", - "settings.themes": "🎨 Thèmes", - "share.copied": "Lien copié !", - "share.copy_link": "Copier le lien", - "share.create": "Créer un lien de partage", - "share.expires": "Expire le", - "share.never": "Jamais", - "share.revoke": "Révoquer", - "share.title": "Partage public", - "shortcut.ai_completion": "Completion IA inline (dans l'éditeur)", - "shortcut.close_editor": "Fermer l'éditeur / modale", - "shortcut.command_palette": "Palette de commandes", - "shortcut.editor_help": "Aide de l'éditeur Forge", - "shortcut.file_palette": "Palette de fichiers (nav. rapide)", - "shortcut.focus_search": "Focus barre de recherche", - "shortcut.quick_insert": "Insertion rapide (éditeur Forge)", - "shortcut.quick_search": "Recherche rapide (hors champ texte)", - "shortcut.save_file": "Sauvegarder le fichier ouvert", - "shortcut.search_in_doc": "Rechercher dans le document", - "shortcut.tip_preview": "Survolez un document avec **Ctrl** pour un aperçu rapide. Cliquez sur **Forge** dans la barre d'outils pour l'éditeur avancé.", - "sidebar.all_vaults": "Tous les vaults", - "sidebar.case_sensitive": "Respecter la casse", - "sidebar.clear_filter": "Effacer", - "sidebar.expand_collapse": "Développer/Réduire", - "sidebar.file_icons": "Icônes", - "sidebar.filter_instant": "Recherche instantanée", - "sidebar.filter_path": "Filtres de chemin", - "sidebar.filter_placeholder": "Filtrer fichiers...", - "sidebar.filter_results_grouped": "Résultats groupés", - "sidebar.loading": "Chargement...", - "sidebar.no_recent_files": "Aucun fichier récent", - "sidebar.no_results": "Aucun repertoire ou fichier correspondant.", - "sidebar.no_saved_searches": "Aucune recherche sauvegardée", - "sidebar.open_file": "Ouvrir un fichier", - "sidebar.saved_dirs_tab": "Répertoires", - "sidebar.saved_searches_tab": "Recherches", - "sidebar.sidebar_dropdown": "Menu contextuel vault", - "sidebar.sidebar_filtering": "Filtrage de la sidebar", - "sidebar.tab_backups": "Sauvegardes", - "sidebar.tab_recent": "Récents", - "sidebar.tab_saved": "Recherches", - "sidebar.tab_tags": "Tags", - "sidebar.tab_vaults": "Vaults", - "sidebar.vault_context_all": "Toutes les vaults", - "sidebar.vault_specific": "Vault spécifique", - "sync.autocomplete": "Auto-complétion", - "sync.autocomplete_active": "Auto-complétion active", - "sync.connected": "Synchronisé", - "sync.connected_short": "Connecté", - "sync.disconnected": "Déconnecté", - "sync.event_index_progress": "Vault indexé", - "sync.event_index_start": "Démarrage index.", - "sync.event_index_updated": "Mise à jour", - "sync.event_vault_added": "Vault ajouté", - "sync.event_vault_removed": "Vault supprimé", - "sync.index_complete": "Indexation terminée ({count} fichiers)", - "sync.index_reloaded": "Index complet rechargé", - "sync.index_started": "Indexation démarrée ({count} vaults)", - "sync.install_success": "ObsiGate installé avec succès !", - "sync.model_not_loaded": "Modèle non chargé", - "sync.no_provider": "Aucun fournisseur", - "sync.no_recent_events": "Aucun événement récent", - "sync.not_configured": "Non configuré", - "sync.processing": "Traitement en cours…", - "sync.update": "Mettre à jour", - "sync.updating": "Mise à jour...", - "sync.vault_added": "Vault \"{vault}\" ajouté ({count} fichiers)", - "sync.vault_added_label": "Vault ajouté", - "sync.vault_files": "{vault} ({files} fichiers)", - "sync.vault_indexed_label": "Vault indexé", - "sync.vault_removed": "Vault \"{vault}\" supprimé", - "sync.vault_removed_label": "Vault supprimé", - "sync.verifying": "Vérification…", - "theme.change": "Changer le thème", - "theme.dark": "Sombre", - "theme.light": "Clair", - "theme.title": "Thème", - "themes.name_gradients": "Degrades subtils", - "themes.name_terminal": "Noir pur & vert", - "toast.ai_keys_saved": "Clés API sauvegardées", - "toast.ai_no_key": "Aucune clé à sauvegarder", - "toast.bookmark_added": "Ajouté aux favoris", - "toast.bookmark_removed": "Retiré des favoris", - "toast.cannot_delete_self": "Impossible de supprimer son propre compte", - "toast.config_client_saved": "Paramètres client sauvegardés", - "toast.config_reset": "Configuration réinitialisée", - "toast.config_saved": "Configuration sauvegardée", - "toast.conflict_resolved": "Conflit résolu", - "toast.copied": "Copié !", - "toast.copy_error": "Erreur lors de la copie", - "toast.create_error": "Erreur lors de la création", - "toast.created": "Créé", - "toast.delete_error": "Erreur lors de la suppression", - "toast.deleted": "Supprimé", - "toast.dir_created": "Dossier \"{name}\" créé", - "toast.dir_deleted": "Dossier supprimé ({count} fichiers)", - "toast.dir_renamed": "Dossier renommé", - "toast.dir_saved_search": "Répertoire sauvegardé dans les recherches", - "toast.error_delete": "Erreur de suppression", - "toast.error_init": "Erreur lors de l'initialisation", - "toast.error_load": "Erreur de chargement", - "toast.error_network": "Erreur réseau", - "toast.error_rename": "Impossible de renommer cet élément", - "toast.file_created": "Fichier \"{name}\" créé", - "toast.file_deleted": "Fichier supprimé", - "toast.file_renamed": "Fichier renommé", - "toast.hidden_saved": "✓ Paramètres sauvegardés", - "toast.index_reloaded": "Index complet rechargé", - "toast.installed": "ObsiGate installé avec succès !", - "toast.link_created": "Lien créé !", - "toast.moved": "Déplacé", - "toast.no_open_file": "Aucun fichier ouvert", - "toast.not_found_tree": "Élément introuvable dans l'arborescence", - "toast.path_copied": "Chemin copié : {path}", - "toast.reindex_done": "Réindexation terminée", - "toast.reindex_started": "Réindexation en cours...", - "toast.rename_error": "Erreur lors du renommage", - "toast.renamed": "Renommé", - "toast.saved": "Sauvegardé", - "toast.search_saved": "Recherche sauvegardée", - "toast.share_revoked": "Partage révoqué", - "toast.url_required": "URL requise", - "toast.user_created": "Utilisateur créé", - "toast.user_deleted": "Utilisateur supprimé", - "toast.user_modified": "Utilisateur modifié", - "toast.viewer_error": "Erreur lors du chargement du viewer", - "toc.hide_panel": "Masquer le panneau", - "toc.no_headings": "Aucun titre dans ce document", - "toc.title": "SUR CETTE PAGE", - "tree.new_file": "Nouveau fichier", - "tree.new_folder": "Nouveau dossier", - "tree.vault_home": "Accueil du vault", - "ui.backups_versions": "Backups / Versions", - "ui.cannot_rename": "Impossible de renommer cet élément", - "ui.delete_name_empty": "Le nom ne peut pas etre vide", - "ui.element_not_found": "Élément introuvable dans l'arborescence", - "ui.vault_readonly": "Vault en lecture seule", - "vault.add_dynamic": "Ajouter une vault", - "vault.reindex": "Réindexer la vault", - "vault.remove_dynamic": "Retirer la vault", - "vaulthome.empty": "Aucun fichier dans ce repertoire", - "vaulthome.error_loading": "Erreur de chargement:", - "vaulthome.file_count": "{count} fichier", - "vaulthome.file_count_plural": "{count} fichiers", - "vaulthome.loading": "Chargement des fichiers...", - "vaulthome.size_bytes": "o", - "vaulthome.size_kb": "Ko", - "vaulthome.size_mb": "Mo", - "viewer.backlinks": "Backlinks", - "viewer.binary_download": "Télécharger le fichier", - "viewer.binary_unsupported": "Fichier binaire non supporté", - "viewer.bookmark_add": "Ajouter aux bookmarks", - "viewer.bookmark_remove": "Retirer des bookmarks", - "viewer.bookmark_toggle": "Ajouter/Retirer des bookmarks", - "viewer.breadcrumb_home": "Accueil", - "viewer.click_to_download": "Cliquez pour le télécharger", - "viewer.copied": "Copié !", - "viewer.copy": "Copier", - "viewer.copy_error": "Erreur lors de la copie", - "viewer.download": "Télécharger", - "viewer.download_md": "Télécharger en .md", - "viewer.download_pdf": "Télécharger en PDF", - "viewer.edit": "Éditer", - "viewer.error": "Erreur de chargement", - "viewer.forge_brand": "Forge", - "viewer.forge_title": "Forge (nouvel éditeur)", - "viewer.index_start": "Démarrage index.", - "viewer.index_updated": "Mise à jour", - "viewer.loaded_from_cache": "Fichier chargé depuis le cache hors-ligne", - "viewer.loading": "Chargement du fichier...", - "viewer.markdown": "Markdown", - "viewer.metadata_created": "Créé", - "viewer.metadata_modified": "Modifié", - "viewer.metadata_path": "Chemin", - "viewer.metadata_size": "Taille", - "viewer.metadata_tags": "Tags", - "viewer.metadata_vault": "Vault", - "viewer.no_headings": "Aucun titre dans ce document", - "viewer.on_this_page": "SUR CETTE PAGE", - "viewer.outline": "Plan", - "viewer.pdf_pages": "{count} pages", - "viewer.popout": "Ouvrir dans une fenêtre", - "viewer.raw": "Brut", - "viewer.share": "Partager", - "viewer.shared_doc_title": "Document partagé — cliquer pour gérer", - "viewer.source": "Source", - "viewer.syncing": "Mise à jour...", - "viewer.toc": "Table des matières", - "viewer.unsupported_file": "Ce fichier est binaire et ne peut pas être affiché", - "webhook.trigger_create": "Création via API ou palette", - "webhook.trigger_delete": "Suppression via API ou éditeur", - "webhook.trigger_dir_create": "Création de dossier via API", - "webhook.trigger_dir_delete": "Suppression de dossier via l'API", - "webhook.trigger_dir_rename": "Renommage de dossier via l'API", - "webhook.trigger_rename": "Renommage via l'API" -} diff --git a/desktop/frontend-static/manifest.json b/desktop/frontend-static/manifest.json deleted file mode 100644 index 16513be..0000000 --- a/desktop/frontend-static/manifest.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "name": "ObsiGate", - "short_name": "ObsiGate", - "description": "Porte d'entree web pour vos vaults Obsidian - Accedez, naviguez et recherchez dans toutes vos notes", - "start_url": "/", - "scope": "/", - "display": "standalone", - "background_color": "#1a1a1a", - "theme_color": "#2563eb", - "orientation": "any", - "icons": [ - { - "src": "/static/icons/icon-72x72.svg", - "sizes": "72x72", - "type": "image/svg+xml", - "purpose": "any" - }, - { - "src": "/static/icons/icon-96x96.svg", - "sizes": "96x96", - "type": "image/svg+xml", - "purpose": "any" - }, - { - "src": "/static/icons/icon-128x128.svg", - "sizes": "128x128", - "type": "image/svg+xml", - "purpose": "any" - }, - { - "src": "/static/icons/icon-144x144.svg", - "sizes": "144x144", - "type": "image/svg+xml", - "purpose": "any" - }, - { - "src": "/static/icons/icon-152x152.svg", - "sizes": "152x152", - "type": "image/svg+xml", - "purpose": "any" - }, - { - "src": "/static/icons/icon-192x192.svg", - "sizes": "192x192", - "type": "image/svg+xml", - "purpose": "any" - }, - { - "src": "/static/icons/icon-384x384.svg", - "sizes": "384x384", - "type": "image/svg+xml", - "purpose": "any" - }, - { - "src": "/static/icons/icon-512x512.svg", - "sizes": "512x512", - "type": "image/svg+xml", - "purpose": "any" - }, - { - "src": "/static/icons/icon-192x192-maskable.svg", - "sizes": "192x192", - "type": "image/svg+xml", - "purpose": "maskable" - }, - { - "src": "/static/icons/icon-512x512-maskable.svg", - "sizes": "512x512", - "type": "image/svg+xml", - "purpose": "maskable" - } - ], - "categories": ["productivity", "utilities"], - "shortcuts": [ - { - "name": "Recherche", - "short_name": "Recherche", - "description": "Rechercher dans vos vaults", - "url": "/?action=search", - "icons": [ - { - "src": "/static/icons/search-96x96.svg", - "sizes": "96x96" - } - ] - } - ], - "prefer_related_applications": false -} diff --git a/desktop/frontend-static/popout.html b/desktop/frontend-static/popout.html deleted file mode 100644 index 93d4017..0000000 --- a/desktop/frontend-static/popout.html +++ /dev/null @@ -1,1635 +0,0 @@ - - - - - - ObsiGate - Popout - - - - - - - - - - - - -
    Chargement...
    -
    -
    -
    -
    Édition
    -
    - - -
    -
    -
    -
    -
    - -
    -
    - -
    - - -
    - - - - diff --git a/desktop/frontend-static/style.css b/desktop/frontend-static/style.css deleted file mode 100644 index 9b915c9..0000000 --- a/desktop/frontend-static/style.css +++ /dev/null @@ -1,8573 +0,0 @@ -@import url("https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Lora:ital,wght@0,400;0,600;1,400&display=swap"); - -/* ===== RESET ===== */ -*, -*::before, -*::after { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -/* ── Editor save dot state colors ── */ -:root { - --ok: #34d399; - --warn: #fbbf24; - --ai: #8b5cf6; - --err: #f87171; -} - -/* ===== THEME — DARK (fallback default, no data-theme) ===== */ -:root { - --bg-primary: #0f1117; - --bg-secondary: #161b22; - --bg-sidebar: #13161d; - --bg-hover: #1f2430; - --border: #21262d; - --text-primary: #e6edf3; - --text-secondary: #8b949e; - --text-muted: #484f58; - --accent: #58a6ff; - --accent-green: #3fb950; - --tag-bg: #1f2a3a; - --tag-text: #79c0ff; - --code-bg: #161b22; - --search-bg: #21262d; - --scrollbar: #30363d; - --resize-handle: #30363d; - --overlay-bg: rgba(0, 0, 0, 0.5); - --danger: #ff7b72; - --danger-bg: #3d1a18; - --success: #3fb950; - --success-bg: #1a3d1f; - --accent-card: #58a6ff; - --accent-bg: #1f2a3a; - --accent-text: #79c0ff; - --green: #3fb950; - --green-bg: #1a3d1f; - --purple: #a371f7; - --purple-bg: #2d1b4e; - --surface: #161b22; - --surface2: #0f1117; - --surface3: #0d0f14; - --border-md: #30363d; - --text: #e6edf3; - --text-2: #8b949e; - --text-3: #484f58; - --mono: "JetBrains Mono", monospace; - --radius: 6px; - --radius-lg: 10px; -} - -/* ===== THEME — DARK (explicit) ===== */ -:root[data-theme="dark"] { - --bg-primary: #0f1117; - --bg-secondary: #161b22; - --bg-sidebar: #13161d; - --bg-hover: #1f2430; - --border: #21262d; - --text-primary: #e6edf3; - --text-secondary: #8b949e; - --text-muted: #484f58; - --accent: #58a6ff; - --accent-green: #3fb950; - --tag-bg: #1f2a3a; - --tag-text: #79c0ff; - --code-bg: #161b22; - --search-bg: #21262d; - --scrollbar: #30363d; - --resize-handle: #30363d; - --overlay-bg: rgba(0, 0, 0, 0.5); - --danger: #ff7b72; - --danger-bg: #3d1a18; - --success: #3fb950; - --success-bg: #1a3d1f; - - /* Accent Card variables */ - --accent-card: #58a6ff; - --accent-bg: #1f2a3a; - --accent-text: #79c0ff; - --green: #3fb950; - --green-bg: #1a3d1f; - --purple: #a371f7; - --purple-bg: #2d1b4e; - --surface: #161b22; - --surface2: #0f1117; - --surface3: #0d0f14; - --border-md: #30363d; - --text: #e6edf3; - --text-2: #8b949e; - --text-3: #484f58; - --mono: "JetBrains Mono", monospace; - --radius: 6px; - --radius-lg: 10px; -} - -/* ===== THEME — LIGHT ===== */ -:root[data-theme="light"] { - --bg-primary: #ffffff; - --bg-secondary: #f6f8fa; - --bg-sidebar: #f0f2f5; - --bg-hover: #e8ecf0; - --border: #d0d7de; - --text-primary: #1f2328; - --text-secondary: #57606a; - --text-muted: #9198a1; - --accent: #0969da; - --accent-green: #1a7f37; - --tag-bg: #ddf4ff; - --tag-text: #0969da; - --code-bg: #f6f8fa; - --search-bg: #ffffff; - --scrollbar: #d0d7de; - --resize-handle: #d0d7de; - --overlay-bg: rgba(0, 0, 0, 0.3); - --danger: #cf222e; - --danger-bg: #ffebe9; - --success: #1a7f37; - --success-bg: #dafbe1; - - /* Accent Card variables */ - --accent-card: #4f6ef7; - --accent-bg: #eef1fe; - --accent-text: #2540c9; - --green: #1a7f50; - --green-bg: #eaf5ee; - --purple: #6b40c4; - --purple-bg: #f1ecfd; - --surface: #ffffff; - --surface2: #f2f1ef; - --surface3: #ebe9e6; - --border-md: rgba(0, 0, 0, 0.13); - --text: #1a1917; - --text-2: #6b6a67; - --text-3: #a09e9b; - --mono: "JetBrains Mono", monospace; - --radius: 6px; - --radius-lg: 10px; -} - -/* ===== BASE ===== */ -html { - font-size: 16px; - scroll-behavior: smooth; -} - -body { - font-family: "Lora", Georgia, serif; - background: var(--bg-primary); - color: var(--text-primary); - line-height: 1.7; - transition: - background 200ms ease, - color 200ms ease; - overflow: hidden; - height: 100vh; -} - -a { - color: var(--accent); - text-decoration: none; -} -a:hover { - text-decoration: underline; -} - -/* ===== LAYOUT ===== */ -.app-container { - display: flex; - flex-direction: column; - height: 100vh; -} - -/* --- Header --- */ -.header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 10px 20px; - background: var(--bg-secondary); - border-bottom: 1px solid var(--border); - flex-shrink: 0; - z-index: 100; - transition: background 200ms ease; -} - -.header-left { - display: flex; - align-items: center; - gap: 12px; - flex: 0 1 auto; -} - -.header-center { - display: flex; - justify-content: center; - flex: 1 1 auto; - max-width: 600px; -} - -.header-right { - display: flex; - align-items: center; - justify-content: flex-end; - gap: 12px; - flex: 0 1 auto; -} - -.vault-context-indicator { - display: flex; - align-items: center; - gap: 6px; - padding: 6px 12px; - border: 1px solid var(--border); - border-radius: 8px; - font-family: "JetBrains Mono", monospace; - font-size: 0.75rem; - font-weight: 600; - cursor: default; - transition: all 200ms ease; - /* Default: neutral (overridden by classes below) */ - background: var(--bg-tertiary); - color: var(--text-muted); -} -.vault-context-indicator:hover { - filter: brightness(1.15); -} -.vault-context-indicator i { - opacity: 0.8; -} - -/* ── Offline Indicator ── */ -.offline-indicator { - position: relative; - display: flex; - align-items: center; - justify-content: center; - margin-right: 8px; - cursor: default; -} -.offline-indicator.offline i { - color: var(--warning, #f59e0b); - opacity: 1; -} -.offline-pending { - position: absolute; - top: -4px; - right: -8px; - background: var(--danger, #ef4444); - color: #fff; - font-size: 0.6rem; - font-weight: 700; - min-width: 14px; - height: 14px; - line-height: 14px; - text-align: center; - border-radius: 7px; - padding: 0 3px; -} - -/* ── Offline Search Result Badge ── */ -.search-result-offline-badge { - display: inline-block; - background: var(--warning, #f59e0b); - color: #000; - font-size: 0.55rem; - font-weight: 700; - padding: 1px 5px; - border-radius: 3px; - margin-left: 6px; - vertical-align: middle; - text-transform: uppercase; -} - -/* ── Conflict Resolution Modal ── */ -.conflict-modal-overlay { - position: fixed; - inset: 0; - background: rgba(0,0,0,0.6); - z-index: 9999; - display: flex; - align-items: center; - justify-content: center; -} -.conflict-modal { - background: var(--bg-card, #1e1e2e); - border: 1px solid var(--border, #333); - border-radius: 8px; - padding: 24px; - max-width: 600px; - width: 90%; - max-height: 80vh; - overflow-y: auto; -} -.conflict-modal h3 { - margin: 0 0 8px; - font-size: 1.1rem; -} -.conflict-modal p { - color: var(--text-muted, #888); - font-size: 0.85rem; - margin: 0 0 16px; -} -.conflict-modal-actions { - display: flex; - gap: 8px; - justify-content: flex-end; -} -.conflict-modal-actions button { - padding: 8px 16px; - border-radius: 6px; - border: 1px solid var(--border, #333); - background: var(--bg-input, #2a2a3c); - color: var(--text, #ddd); - cursor: pointer; - font-size: 0.85rem; -} -.conflict-modal-actions .btn-primary { - background: var(--accent, #3b82f6); - border-color: var(--accent); - color: #fff; -} - -/* All vaults — blue */ -.vault-ctx-all { - background: color-mix(in srgb, #3b82f6 14%, transparent) !important; - border-color: color-mix(in srgb, #3b82f6 30%, var(--border)) !important; - color: #60a5fa !important; -} -.vault-ctx-all i { color: #60a5fa !important; } - -/* Specific vault — mauve/violet */ -.vault-ctx-vault { - background: color-mix(in srgb, #a855f7 14%, transparent) !important; - border-color: color-mix(in srgb, #a855f7 30%, var(--border)) !important; - color: #c084fc !important; -} -.vault-ctx-vault i { color: #c084fc !important; } - -/* Directory — amber/yellow */ -.vault-ctx-dir { - background: color-mix(in srgb, #f59e0b 14%, transparent) !important; - border-color: color-mix(in srgb, #f59e0b 30%, var(--border)) !important; - color: #fbbf24 !important; -} -.vault-ctx-dir i { color: #fbbf24 !important; } - -.hamburger-btn { - display: none; - background: none; - border: none; - color: var(--text-secondary); - cursor: pointer; - padding: 4px; - align-items: center; - justify-content: center; - flex-shrink: 0; -} -.hamburger-btn:hover { - color: var(--accent); -} - -.sidebar-toggle-btn { - display: flex; - background: none; - border: none; - color: var(--text-secondary); - cursor: pointer; - padding: 4px; - align-items: center; - justify-content: center; - flex-shrink: 0; - transition: color 200ms ease; -} -.sidebar-toggle-btn:hover { - color: var(--accent); -} -.sidebar-toggle-btn.active { - color: var(--accent); -} - -.header-logo { - font-family: "JetBrains Mono", monospace; - font-weight: 700; - font-size: 1.15rem; - color: var(--accent); - white-space: nowrap; - display: flex; - align-items: center; - gap: 8px; - cursor: pointer; - transition: opacity 200ms ease; - text-decoration: none; -} -.header-logo:hover { - opacity: 0.8; - text-decoration: none; -} - -.search-wrapper { - width: 100%; - max-width: 620px; - position: relative; - display: flex; - flex-direction: column; - gap: 4px; -} - -.search-wrapper .search-icon { - position: absolute; - left: 10px; - top: 14px; - color: var(--text-secondary); - pointer-events: none; - z-index: 1; -} - -.search-input-wrapper { - position: relative; - flex: 1; - display: flex; - align-items: center; -} - -.search-input-wrapper input { - flex: 1; - min-width: 0; - padding: 8px 14px 8px 38px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-secondary); - color: var(--text-primary); - font-family: "JetBrains Mono", monospace; - font-size: 0.9rem; - outline: none; - transition: - border-color 200ms ease, - background 200ms ease; -} - -.search-input-wrapper input:focus { - border-color: var(--accent); -} - -.search-actions { - display: flex; - align-items: center; - gap: 2px; - flex-shrink: 0; - padding-left: 4px; -} - -.search-btn { - display: flex; - align-items: center; - justify-content: center; - min-width: 26px; - height: 26px; - padding: 0 4px; - border: 1px solid var(--border); - border-radius: 4px; - background: var(--bg-secondary); - color: var(--text-secondary); - cursor: pointer; - font-family: "JetBrains Mono", monospace; - font-size: 0.7rem; - font-weight: 600; - transition: all 150ms ease; - flex-shrink: 0; -} - -.search-btn:hover { - border-color: var(--accent); - color: var(--accent); - background: color-mix(in srgb, var(--accent) 10%, var(--bg-secondary)); -} - -.search-btn.active { - border-color: var(--accent); - background: color-mix(in srgb, var(--accent) 20%, var(--bg-secondary)); - color: var(--accent); -} - -.header-menu { - position: relative; -} - -.header-menu-btn { - background: transparent; - border: 1px solid color-mix(in srgb, var(--accent) 22%, var(--border)); - border-radius: 12px; - padding: 10px 12px; - cursor: pointer; - color: var(--text-secondary); - display: flex; - align-items: center; - justify-content: center; - transition: - color 200ms ease, - border-color 200ms ease, - background 200ms ease, - transform 180ms ease; -} -.header-menu-btn:hover { - color: var(--accent); - border-color: var(--accent); - transform: translateY(-1px); -} -.header-menu-btn.active { - color: var(--accent); - border-color: var(--accent); - background: color-mix(in srgb, var(--accent) 10%, transparent); -} - -.header-menu-dropdown { - display: none; - position: absolute; - top: calc(100% + 8px); - right: 0; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 16px; - box-shadow: 0 16px 36px rgba(0, 0, 0, 0.28); - min-width: 260px; - z-index: 100; - padding: 8px; -} -.header-menu-dropdown.active { - display: block; -} - -.menu-list { - display: flex; - flex-direction: column; -} - -.menu-list-row { - width: 100%; - display: grid; - grid-template-columns: 28px minmax(0, 1fr); - align-items: center; - gap: 8px; - padding: 4px 8px; - border-radius: 6px; - text-align: left; -} - -.menu-list-button { - border: none; - background: transparent; - cursor: pointer; - transition: - background 160ms ease, - color 160ms ease; -} - -.menu-list-button:hover, -.menu-list-select-row:hover { - background: var(--bg-hover); -} - -.menu-list-button + .menu-list-button, -.menu-list-select-row + .menu-list-button { - margin-top: 2px; -} - -.menu-list-icon { - width: 18px; - height: 18px; - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - color: var(--accent); -} - -.menu-list-content { - display: flex; - flex-direction: column; - gap: 1px; - min-width: 0; -} - -.menu-list-title { - font-family: "JetBrains Mono", monospace; - font-size: 0.8rem; - font-weight: 600; - color: var(--text-primary); -} - -.menu-list-subtitle { - font-size: 0.7rem; - color: var(--text-muted); -} - -.menu-select { - width: 100%; - padding: 4px 22px 4px 0; - border: none; - border-radius: 0; - background: inherit; - color: var(--text-primary); - font-family: "JetBrains Mono", monospace; - font-size: 0.78rem; - font-weight: 500; - outline: none; - cursor: pointer; - transition: color 160ms ease; - color-scheme: dark; - background-color: transparent; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; -} - -.menu-select option { - background-color: var(--bg-secondary); - color: var(--text-primary); -} - -[data-theme="dark"] .menu-select, -[data-theme="dark"] .menu-select option { - background-color: #1e1e1e; - color: #e0e0e0; -} -.menu-select:hover, -.menu-select:focus { - color: var(--accent); -} - -.menu-list-select { - margin-top: 1px; -} - -/* Force dark mode on all select elements */ -select { - color-scheme: dark; -} - -[data-theme="dark"] select, -[data-theme="dark"] select option { - background-color: #161b22 !important; - color: #e6edf3 !important; -} - -[data-theme="light"] select, -[data-theme="light"] select option { - background-color: #f6f8fa !important; - color: #1f2328 !important; -} - -/* Custom Dropdown Styles */ -.custom-dropdown { - position: relative; - width: 100%; -} - -.custom-dropdown-trigger { - width: 100%; - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - padding: 8px 12px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 8px; - color: var(--text-primary); - font-family: "JetBrains Mono", monospace; - font-size: 0.8rem; - cursor: pointer; - transition: - border-color 200ms ease, - background 200ms ease; -} - -.custom-dropdown-trigger:hover { - border-color: var(--accent); - background: var(--bg-hover); -} - -.custom-dropdown-trigger[aria-expanded="true"] { - border-color: var(--accent); -} - -.custom-dropdown-selected { - flex: 1; - text-align: left; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.custom-dropdown-menu { - display: none; - position: absolute; - top: calc(100% + 4px); - left: 0; - right: 0; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 6px; - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4); - max-height: 240px; - overflow-y: auto; - z-index: 1000; - list-style: none; - padding: 3px; - margin: 0; -} - -.custom-dropdown.open .custom-dropdown-menu { - display: block; -} - -.custom-dropdown-option { - padding: 6px 10px; - border-radius: 4px; - cursor: pointer; - font-family: "JetBrains Mono", monospace; - font-size: 0.8rem; - color: var(--text-primary); - transition: - background 150ms ease, - color 150ms ease; -} - -.custom-dropdown-option:hover, -.custom-dropdown-option:focus { - background: var(--bg-hover); - color: var(--accent); -} - -.custom-dropdown-option.selected { - background: color-mix(in srgb, var(--accent) 15%, transparent); - color: var(--accent); -} - -/* Sidebar dropdown specific */ -.sidebar-dropdown { - padding: 0 16px 12px; - position: relative; -} - -.sidebar-dropdown .custom-dropdown-menu { - position: fixed; - z-index: 10000; - left: auto; - right: auto; - width: auto; - min-width: 200px; -} - -.sidebar-dropdown .custom-dropdown-trigger { - background: var(--bg-sidebar); -} - -/* Menu list dropdown specific */ -.menu-list-select-row .custom-dropdown { - margin-top: 4px; -} - -.menu-list-select-row .custom-dropdown-trigger { - padding: 6px 10px; - font-size: 0.78rem; - background: var(--bg-primary); -} - -.main-body { - display: flex; - flex: 1; - overflow: hidden; - position: relative; -} - -/* --- Mobile overlay --- */ -.sidebar-overlay { - display: none; - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: var(--overlay-bg); - z-index: 199; -} -.sidebar-overlay.active { - display: block; -} - -/* --- Sidebar --- */ -.sidebar { - width: 280px; - min-width: 200px; - max-width: 500px; - background: var(--bg-sidebar); - border-right: 1px solid var(--border); - display: flex; - flex-direction: column; - overflow: hidden; - transition: - background 200ms ease, - transform 300ms ease; - flex-shrink: 0; -} - -.sidebar.hidden { - transform: translateX(-100%); - width: 0; - min-width: 0; - border-right: none; -} - -/* --- Sidebar filter --- */ -.sidebar-filter { - padding: 10px 12px; - border-bottom: 1px solid var(--border); - position: relative; - flex-shrink: 0; - display: flex; - align-items: center; -} - -.sidebar-filter-input-wrapper { - position: relative; - flex: 1; - display: flex; - align-items: center; -} - -.sidebar-filter-input-wrapper input { - width: 100%; - padding: 6px 10px 6px 32px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--search-bg); - color: var(--text-primary); - font-family: "JetBrains Mono", monospace; - font-size: 0.78rem; - outline: none; - transition: border-color 200ms ease; -} - -.sidebar-filter-input-wrapper input:focus { - border-color: var(--accent); -} - -.sidebar-filter-icon { - position: absolute; - left: 10px; - top: 50%; - transform: translateY(-50%); - color: var(--text-muted); - pointer-events: none; - z-index: 1; -} - -.sidebar-filter-actions { - position: absolute; - right: 4px; - top: 50%; - transform: translateY(-50%); - display: flex; - align-items: center; - gap: 4px; -} - -.sidebar-filter-btn { - display: flex; - align-items: center; - justify-content: center; - width: 24px; - height: 24px; - border: 1px solid var(--border); - border-radius: 4px; - background: var(--bg-secondary); - color: var(--text-secondary); - cursor: pointer; - font-family: "JetBrains Mono", monospace; - font-size: 0.65rem; - font-weight: 600; - transition: all 150ms ease; - padding: 0; - flex-shrink: 0; -} - -.sidebar-filter-btn:hover { - border-color: var(--accent); - color: var(--accent); - background: color-mix(in srgb, var(--accent) 10%, var(--bg-secondary)); -} - -.sidebar-filter-btn.active { - border-color: var(--accent); - background: color-mix(in srgb, var(--accent) 20%, var(--bg-secondary)); - color: var(--accent); -} - -/* --- Sidebar tabs --- */ -.sidebar-tabs { - display: flex; - flex-shrink: 0; - border-bottom: 1px solid var(--border); - padding: 0 8px; - gap: 2px; - background: var(--bg-sidebar); -} - -.sidebar-tab { - flex: 1; - display: flex; - align-items: center; - justify-content: center; - padding: 8px 4px 6px; - border: none; - border-bottom: 2px solid transparent; - background: transparent; - color: var(--text-muted); - cursor: pointer; - transition: color 150ms ease, border-color 150ms ease; - margin-bottom: -1px; -} - -.sidebar-tab:hover { - color: var(--text-primary); -} - -.sidebar-tab.active { - color: var(--accent); - border-bottom-color: var(--accent); -} - -.sidebar-tab .icon { - flex-shrink: 0; - color: inherit; -} - -/* --- Sidebar tab panels --- */ -.sidebar-tab-panel { - display: none; - flex: 1 1 auto; - min-height: 0; - overflow-y: auto; - scroll-behavior: smooth; - flex-direction: column; -} - -.sidebar-tab-panel.active { - display: flex; - flex-direction: column; -} - -.sidebar-tab-panel::-webkit-scrollbar { - width: 6px; -} -.sidebar-tab-panel::-webkit-scrollbar-thumb { - background: var(--scrollbar); - border-radius: 3px; -} - -#sidebar-panel-vaults .sidebar-dropdown { - padding: 10px 12px 6px; -} - -.tree-item { - display: flex; - align-items: center; - gap: 6px; - padding: 5px 16px; - font-family: "JetBrains Mono", monospace; - font-size: 0.82rem; - color: var(--text-secondary); - cursor: pointer; - border-radius: 0; - transition: - background 120ms ease, - color 120ms ease; - white-space: nowrap; - min-width: 0; /* Allow flex item to shrink */ -} - -.tree-item > .tree-item-text { - flex: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - min-width: 0; -} -.tree-item:hover { - background: var(--bg-hover); - color: var(--text-primary); -} -.tree-item > .badge-small { - margin-left: 4px; -} -.tree-item.active { - background: var(--bg-hover); - color: var(--accent); -} -.tree-item.focused { - background: color-mix(in srgb, var(--accent) 12%, transparent); - color: var(--text-primary); - box-shadow: inset 2px 0 0 var(--accent); -} -.tree-item.path-selected { - background: color-mix(in srgb, var(--accent) 20%, transparent); - color: var(--accent); - box-shadow: - inset 0 0 0 2px var(--accent), - inset 2px 0 0 var(--accent); - border-radius: 6px; - animation: pathPulse 1.5s ease-out; -} -@keyframes pathPulse { - 0% { - background: color-mix(in srgb, var(--accent) 40%, transparent); - } - 100% { - background: color-mix(in srgb, var(--accent) 20%, transparent); - } -} -.tree-item.filtered-out { - display: none; -} - -.tree-item .icon { - width: 16px; - height: 16px; - flex-shrink: 0; - color: var(--accent); -} -.tree-item.active .icon { - color: var(--accent); -} -.tree-item.vault-item .icon { - color: var(--accent); -} - -.tree-item-action-btn { - margin-left: auto; - width: 24px; - height: 24px; - display: inline-flex; - align-items: center; - justify-content: center; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-secondary); - color: var(--accent); - cursor: pointer; - opacity: 1; - pointer-events: auto; - transition: - opacity 140ms ease, - color 140ms ease, - background 140ms ease, - border-color 140ms ease; - flex-shrink: 0; - z-index: 1; -} - -.tree-item-action-btn:hover, -.tree-item-action-btn:focus-visible { - background: color-mix(in srgb, var(--accent) 10%, transparent); - border-color: color-mix(in srgb, var(--accent) 25%, var(--border)); - color: var(--accent); - outline: none; -} - -/* --------------------------------------------------------------------------- - Drag & Drop — tree items - --------------------------------------------------------------------------- */ - -/* Source item being dragged */ -.tree-item.drag-source { - opacity: 0.35; - outline: 1px dashed var(--border); -} - -/* Valid drop targets during drag — subtle pulse indicator */ -.tree-item.drag-valid-target { - outline: 1px dashed color-mix(in srgb, var(--accent) 30%, transparent); - outline-offset: -1px; -} - -/* Active drop target (hovering over) */ -.tree-item.drag-over { - background: color-mix(in srgb, var(--accent) 18%, transparent) !important; - outline: 2px solid var(--accent); - outline-offset: -2px; - border-radius: 4px; -} - -/* Vault item as drop target */ -.tree-item.vault-item.drag-over { - background: color-mix(in srgb, var(--accent) 15%, transparent) !important; - outline: 2px solid var(--accent); - outline-offset: -2px; -} - -.tree-children { - padding-left: 16px; - overflow: hidden; -} - -.tree-children.collapsed { - display: none; -} -.tree-children.filtered-out { - display: none; -} - -.filter-results-header { - margin-top: 8px; -} - -.filter-results-group { - display: flex; - flex-direction: column; - gap: 4px; - padding: 4px 0 10px 12px; -} - -.filter-result-item { - align-items: flex-start; - white-space: normal; - overflow: visible; - border-radius: 6px; -} - -.filter-result-text { - flex: 1; - min-width: 0; - display: flex; - flex-direction: column; - gap: 2px; - white-space: normal; -} - -.filter-result-primary { - color: var(--text-primary); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.filter-result-secondary { - color: var(--text-muted); - font-size: 0.75rem; - word-break: break-all; - opacity: 0.8; -} - -.sidebar-filter-empty { - padding: 12px 16px; - color: var(--text-muted); - font-size: 0.85rem; -} - -.filter-highlight { - background: color-mix(in srgb, var(--accent) 22%, transparent); - color: var(--accent); - padding: 0 2px; - border-radius: 4px; -} - -/* --- Tag Cloud --- */ -.tag-cloud { - display: flex; - flex-wrap: wrap; - gap: 6px; - padding: 14px 16px 16px; - align-content: flex-start; -} - -.tag-item { - display: inline-block; - padding: 2px 8px; - background: var(--tag-bg); - color: var(--tag-text); - border-radius: 4px; - font-family: "JetBrains Mono", monospace; - cursor: pointer; - transition: opacity 150ms ease; - line-height: 1.4; -} -.tag-item:hover { - opacity: 0.8; -} -.tag-item.filtered-out { - display: none; -} - -/* --- Sidebar resize handle (horizontal) --- */ -.sidebar-resize-handle { - width: 5px; - cursor: ew-resize; - background: transparent; - flex-shrink: 0; - transition: - background 150ms ease, - opacity 300ms ease; - z-index: 10; -} -.sidebar-resize-handle:hover, -.sidebar-resize-handle.active { - background: var(--accent); - opacity: 0.5; -} -.sidebar-resize-handle.hidden { - width: 0; - opacity: 0; - pointer-events: none; -} - -/* --- Content Wrapper (tabs + content) --- */ -.content-wrapper { - flex: 1; - display: flex; - flex-direction: column; - min-width: 0; - overflow: hidden; -} - -/* --- Content Area --- */ -.content-area { - flex: 1; - overflow-y: auto; - overflow-x: hidden; - padding: clamp(16px, 3vw, 40px) clamp(16px, 4vw, 40px) 60px; - transition: - background 200ms ease, - margin 300ms ease; - min-width: 0; -} - -/* Center content when sidebar is hidden */ -.sidebar.hidden ~ .content-wrapper .content-area { - margin: 0 auto; - max-width: 1200px; -} -.content-area::-webkit-scrollbar { - width: 8px; -} -.content-area::-webkit-scrollbar-thumb { - background: var(--scrollbar); - border-radius: 4px; -} - -/* --- Right Sidebar Resize Handle --- */ -.right-sidebar-resize-handle { - width: 5px; - cursor: ew-resize; - background: transparent; - flex-shrink: 0; - transition: - background 150ms ease, - opacity 300ms ease; - z-index: 10; -} -.right-sidebar-resize-handle:hover, -.right-sidebar-resize-handle.active { - background: var(--accent); - opacity: 0.5; -} -.right-sidebar-resize-handle.hidden { - width: 0; - opacity: 0; - pointer-events: none; -} - -/* --- Right Sidebar (Outline/TOC) --- */ -.right-sidebar { - width: 280px; - min-width: 200px; - max-width: 400px; - background: var(--bg-sidebar); - border-left: 1px solid var(--border); - display: flex; - flex-direction: column; - overflow: hidden; - transition: - background 200ms ease, - transform 300ms ease, - width 300ms ease; - flex-shrink: 0; -} - -.right-sidebar.hidden { - transform: translateX(100%); - width: 0; - min-width: 0; - border-left: none; -} - -/* Right sidebar header */ -.right-sidebar-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 12px 16px; - border-bottom: 1px solid var(--border); - background: var(--bg-sidebar); - flex-shrink: 0; -} - -.right-sidebar-title { - font-family: "JetBrains Mono", monospace; - font-size: 0.7rem; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.08em; - color: var(--text-muted); - margin: 0; -} - -.right-sidebar-toggle-btn { - display: flex; - align-items: center; - justify-content: center; - width: 24px; - height: 24px; - padding: 0; - background: transparent; - border: 1px solid var(--border); - border-radius: 4px; - color: var(--text-secondary); - cursor: pointer; - transition: all 150ms ease; -} - -.right-sidebar-toggle-btn:hover { - background: var(--bg-hover); - border-color: var(--accent); - color: var(--accent); -} - -.right-sidebar-toggle-btn i { - transition: transform 200ms ease; -} - -.right-sidebar.hidden .right-sidebar-toggle-btn i { - transform: rotate(180deg); -} - -/* Outline panel */ -.outline-panel { - flex: 1; - overflow-y: auto; - overflow-x: hidden; - padding: 8px 0; - min-height: 0; -} - -.outline-panel::-webkit-scrollbar { - width: 6px; -} - -.outline-panel::-webkit-scrollbar-thumb { - background: var(--scrollbar); - border-radius: 3px; -} - -.outline-list { - display: flex; - flex-direction: column; - gap: 2px; - padding: 0 8px; -} - -.outline-item { - display: flex; - align-items: center; - padding: 8px 12px; - border-radius: 6px; - font-family: "JetBrains Mono", monospace; - font-size: 0.82rem; - color: var(--text-secondary); - cursor: pointer; - transition: all 150ms ease; - position: relative; - text-decoration: none; - line-height: 1.4; - word-break: break-word; -} - -.outline-item:hover { - background: var(--bg-hover); - color: var(--text-primary); -} - -.outline-item.active { - background: color-mix(in srgb, var(--accent) 12%, transparent); - color: var(--accent); - font-weight: 500; -} - -.outline-item.active::before { - content: ""; - position: absolute; - left: 0; - top: 0; - bottom: 0; - width: 3px; - background: var(--accent); - border-radius: 0 2px 2px 0; -} - -/* Heading levels */ -.outline-item.level-2 { - font-weight: 600; - font-size: 0.85rem; - padding-left: 12px; -} - -.outline-item.level-3 { - font-weight: 400; - font-size: 0.8rem; - padding-left: 28px; - color: var(--text-muted); -} - -.outline-item.level-3:hover { - color: var(--text-secondary); -} - -.outline-item.level-3.active { - color: var(--accent); -} - -/* Empty state */ -.outline-empty { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 40px 20px; - gap: 12px; - color: var(--text-muted); - font-size: 0.85rem; - text-align: center; -} - -/* Reading progress */ -.reading-progress { - padding: 12px 16px; - border-top: 1px solid var(--border); - background: var(--bg-sidebar); - flex-shrink: 0; -} - -.reading-progress-bar { - width: 100%; - height: 6px; - background: color-mix(in srgb, var(--border) 50%, transparent); - border-radius: 3px; - overflow: hidden; - margin-bottom: 8px; -} - -.reading-progress-fill { - height: 100%; - background: var(--accent); - border-radius: 3px; - transition: width 150ms ease; - width: 0%; -} - -.reading-progress-text { - font-family: "JetBrains Mono", monospace; - font-size: 0.75rem; - font-weight: 600; - color: var(--text-muted); - text-align: center; -} - -/* Welcome */ -.welcome { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100%; - color: var(--text-muted); - text-align: center; - gap: 12px; -} -.welcome h2 { - font-family: "JetBrains Mono", monospace; - font-size: 1.6rem; - color: var(--text-secondary); -} -.welcome p { - font-size: 0.95rem; - max-width: 400px; -} - -/* Breadcrumb */ -.breadcrumb { - font-family: "JetBrains Mono", monospace; - font-size: 0.78rem; - color: var(--text-muted); - margin-bottom: 12px; - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 4px; -} -.breadcrumb span { - cursor: pointer; - color: var(--text-secondary); - transition: color 120ms ease; -} -.breadcrumb span:hover { - color: var(--accent); -} -.breadcrumb .sep { - cursor: default; - color: var(--text-muted); -} -.breadcrumb .sep:hover { - color: var(--text-muted); -} - -/* File header */ -.file-header { - margin-bottom: 20px; -} -.file-title { - font-family: "JetBrains Mono", monospace; - font-size: 1.6rem; - font-weight: 700; - margin-bottom: 8px; -} -.file-tags { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin-bottom: 6px; -} -.file-tag { - display: inline-block; - padding: 2px 8px; - background: var(--tag-bg); - color: var(--tag-text); - border-radius: 4px; - font-family: "JetBrains Mono", monospace; - font-size: 0.75rem; - margin-right: 6px; - margin-bottom: 4px; - cursor: pointer; - transition: - opacity 150ms ease, - transform 100ms ease; -} -.file-tag:hover { - opacity: 0.8; - transform: translateY(-1px); -} -.file-actions { - margin-top: 8px; - display: flex; - flex-wrap: wrap; - gap: 6px; - align-items: center; -} -.btn-action { - font-family: "JetBrains Mono", monospace; - font-size: 0.75rem; - padding: 4px 10px; - border: 1px solid var(--border); - border-radius: 6px; - background: transparent; - color: var(--text-secondary); - cursor: pointer; - transition: - color 150ms ease, - border-color 150ms ease; - display: inline-flex; - align-items: center; - gap: 4px; -} -.btn-action:hover { - color: var(--accent); - border-color: var(--accent); -} -.btn-action.active { - color: var(--accent); - border-color: var(--accent); - background: var(--tag-bg); -} - -/* ===== FRONTMATTER — ACCENT CARD ===== */ - -/* Frontmatter section wrapper */ -.fm-section { - margin-bottom: 20px; -} - -/* Header toggle */ -.fm-header { - font-family: "JetBrains Mono", monospace; - font-size: 0.78rem; - color: var(--text-muted); - cursor: pointer; - display: inline-flex; - align-items: center; - gap: 6px; - margin-bottom: 12px; - user-select: none; - transition: color 150ms ease; -} -.fm-header:hover { - color: var(--text-secondary); -} - -/* Chevron icon */ -.fm-chevron { - transition: transform 0.2s; - display: inline-flex; - align-items: center; - justify-content: center; -} -.fm-chevron.open { - transform: rotate(0deg); -} -.fm-chevron.closed { - transform: rotate(-90deg); -} - -/* Accent Card main container */ -.ac-card { - border: 1px solid var(--border-md); - border-left: 3px solid var(--accent-card); - border-radius: 0 var(--radius-lg) var(--radius-lg) 0; - background: var(--surface); - overflow: hidden; -} - -/* ZONE 1 — Top strip */ -.ac-top { - padding: 12px 16px 10px; - border-bottom: 1px solid var(--border); - display: flex; - align-items: center; - gap: 10px; - flex-wrap: wrap; -} -.ac-title { - font-size: 14px; - font-weight: 600; - color: var(--text); - font-family: var(--mono); - letter-spacing: -0.01em; - flex-shrink: 0; -} -.ac-badge { - padding: 2px 9px; - border-radius: 99px; - font-size: 11px; - font-weight: 500; - display: inline-flex; - align-items: center; - gap: 4px; -} -.ac-badge.green { - background: var(--green-bg); - color: var(--green); -} -.ac-badge.blue { - background: var(--accent-bg); - color: var(--accent-text); -} -.ac-badge.purple { - background: var(--purple-bg); - color: var(--purple); -} -.ac-dot { - width: 6px; - height: 6px; - border-radius: 50%; - background: currentColor; - opacity: 0.7; -} - -/* ZONE 2 — Body 2 columns */ -.ac-body { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 0; -} -.ac-col { - padding: 12px 16px; -} -.ac-col + .ac-col { - border-left: 1px solid var(--border); -} -.ac-row { - display: flex; - align-items: baseline; - gap: 6px; - padding: 4px 0; - font-size: 12.5px; -} -.ac-row + .ac-row { - border-top: 1px solid var(--border); -} -.ac-k { - color: var(--text-3); - font-size: 11px; - font-family: var(--mono); - min-width: 110px; - flex-shrink: 0; -} -.ac-v { - color: var(--text); - font-weight: 500; - font-size: 12.5px; -} -.ac-v.mono { - font-family: var(--mono); - font-weight: 400; - color: var(--text-2); - font-size: 11px; -} -.ac-v.muted { - color: var(--text-3); - font-weight: 400; -} - -/* ZONE 3 — Tags row */ -.ac-tags-row { - padding: 10px 16px; - border-top: 1px solid var(--border); - display: flex; - align-items: center; - gap: 10px; -} -.ac-tags-k { - font-size: 11px; - font-family: var(--mono); - color: var(--text-3); - flex-shrink: 0; -} -.ac-tags-wrap { - display: flex; - flex-wrap: wrap; - gap: 4px; -} -.ac-tag { - padding: 2px 9px; - border-radius: 99px; - font-size: 11px; - font-weight: 500; - background: var(--accent-bg); - color: var(--accent-text); - border: 1px solid rgba(79, 110, 247, 0.18); -} - -/* ZONE 4 — Flags row */ -.ac-flags-row { - padding: 9px 16px; - border-top: 1px solid var(--border); - background: var(--surface2); - display: flex; - flex-wrap: wrap; - gap: 6px; - align-items: center; -} -.ac-flags-k { - font-size: 11px; - font-family: var(--mono); - color: var(--text-3); - margin-right: 2px; -} -.flag-chip { - display: inline-flex; - align-items: center; - gap: 4px; - padding: 2px 8px; - border-radius: var(--radius); - font-size: 11px; - font-weight: 500; - border: 1px solid var(--border-md); -} -.flag-chip.on { - background: var(--green-bg); - color: var(--green); - border-color: rgba(26, 127, 80, 0.2); -} -.flag-chip.off { - background: var(--surface3); - color: var(--text-3); -} -.flag-dot { - width: 5px; - height: 5px; - border-radius: 50%; - background: currentColor; - opacity: 0.7; -} - -/* --- Raw source view --- */ -.raw-source-view { - background: var(--code-bg); - border: 1px solid var(--border); - border-radius: 8px; - padding: 16px; - margin-top: 12px; - font-family: "JetBrains Mono", monospace; - font-size: 0.82rem; - color: var(--text-secondary); - white-space: pre-wrap; - word-break: break-word; - overflow-x: auto; - line-height: 1.55; - max-height: 70vh; - overflow-y: auto; -} - -/* --- Markdown Rendered Content --- */ -.md-content h1, -.md-content h2, -.md-content h3, -.md-content h4, -.md-content h5, -.md-content h6 { - font-family: "JetBrains Mono", monospace; - font-weight: 700; - margin: 1.4em 0 0.5em; - color: var(--text-primary); -} -.md-content h1 { - font-size: 1.5rem; - border-bottom: 1px solid var(--border); - padding-bottom: 6px; -} -.md-content h2 { - font-size: 1.25rem; -} -.md-content h3 { - font-size: 1.1rem; -} - -.md-content p { - margin: 0.6em 0; -} - -.md-content ul, -.md-content ol { - padding-left: 1.6em; - margin: 0.5em 0; -} - -.md-content li { - margin: 0.25em 0; -} - -.md-content blockquote { - border-left: 3px solid var(--accent); - padding: 4px 16px; - margin: 0.8em 0; - color: var(--text-secondary); - background: var(--bg-secondary); - border-radius: 0 6px 6px 0; -} - -.md-content code { - font-family: "JetBrains Mono", monospace; - background: var(--code-bg); - padding: 2px 6px; - border-radius: 4px; - font-size: 0.88em; - border: 1px solid var(--border); -} - -.md-content pre { - background: var(--code-bg); - border: 1px solid var(--border); - border-radius: 8px; - padding: 16px; - overflow-x: auto; - margin: 0.8em 0; -} -.md-content pre code { - background: none; - border: none; - padding: 0; - font-size: 0.85rem; - line-height: 1.55; -} - -.md-content table { - width: 100%; - border-collapse: collapse; - margin: 0.8em 0; - font-size: 0.92rem; -} -.md-content th, -.md-content td { - border: 1px solid var(--border); - padding: 8px 12px; - text-align: left; -} -.md-content th { - background: var(--bg-secondary); - font-family: "JetBrains Mono", monospace; - font-weight: 600; - font-size: 0.85rem; -} - -.md-content img { - max-width: 100%; - border-radius: 8px; - margin: 0.6em 0; -} - -.md-content hr { - border: none; - border-top: 1px solid var(--border); - margin: 1.5em 0; -} - -.md-content .task-list-item { - list-style: none; - margin-left: -1.2em; -} -.md-content .task-list-item input[type="checkbox"] { - margin-right: 6px; -} - -/* Wikilinks */ -.wikilink { - color: var(--accent); - border-bottom: 1px dashed var(--accent); - cursor: pointer; -} -.wikilink:hover { - opacity: 0.8; -} -.wikilink-missing { - color: var(--text-muted); - border-bottom: 1px dashed var(--text-muted); - cursor: default; -} - -/* Image placeholders */ -.image-not-found { - display: inline-block; - padding: 8px 12px; - background: var(--danger-bg); - color: var(--danger); - border: 1px dashed var(--danger); - border-radius: 4px; - font-family: "JetBrains Mono", monospace; - font-size: 0.85rem; - cursor: help; -} - -/* Markdown images */ -.file-content img { - max-width: 100%; - height: auto; - display: block; - margin: 16px 0; - border-radius: 6px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); -} - -.file-content a img { - cursor: pointer; - transition: opacity 0.2s ease; -} - -.file-content a img:hover { - opacity: 0.85; -} - -/* --- Search Results --- */ -.search-results { - padding: 0; -} -.search-results-header { - font-family: "JetBrains Mono", monospace; - font-size: 0.85rem; - color: var(--text-muted); - margin-bottom: 16px; - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 8px; -} -.search-results-summary-text { - display: inline; -} -.search-results-active-tags { - display: inline-flex; - flex-wrap: wrap; - gap: 6px; - align-items: center; -} -.search-results-active-tag { - display: inline-flex; - align-items: center; - gap: 4px; - padding: 3px 8px; - background: var(--tag-bg); - color: var(--tag-text); - border-radius: 999px; - font-family: "JetBrains Mono", monospace; - font-size: 0.75rem; - line-height: 1.2; -} -.search-results-active-tag-remove { - display: inline-flex; - align-items: center; - justify-content: center; - width: 16px; - height: 16px; - border: none; - background: transparent; - color: inherit; - cursor: pointer; - padding: 0; -} -.search-result-item { - padding: 14px 16px; - border: 1px solid var(--border); - border-radius: 8px; - margin-bottom: 10px; - cursor: pointer; - transition: - background 120ms ease, - border-color 120ms ease; - position: relative; -} -.search-result-item:hover { - background: var(--bg-hover); - border-color: var(--accent); -} -.search-result-ext { - position: absolute; - top: 8px; - right: 10px; - font-size: 0.65rem; - font-weight: 700; - text-transform: uppercase; - color: var(--accent); - background: var(--accent-bg, rgba(99, 102, 241, 0.12)); - padding: 2px 8px; - border-radius: 4px; - letter-spacing: 0.5px; - border: 1px solid rgba(99, 102, 241, 0.2); -} -.search-filters-row { - display: flex; - gap: 4px; - flex-wrap: wrap; - margin-top: 4px; -} -.search-filter-badge { - font-size: 0.65rem; - font-family: "JetBrains Mono", monospace; - padding: 1px 6px; - border-radius: 3px; - background: rgba(99, 102, 241, 0.1); - color: var(--accent); - font-weight: 600; -} -.search-filter-badge.path { - background: rgba(5, 150, 105, 0.1); - color: #059669; -} - -/* Save search button */ -.search-save-btn { - padding: 4px 10px; - font-size: 0.75rem; - border: 1px solid var(--border); - border-radius: 4px; - background: var(--bg-secondary); - color: var(--text-primary); - cursor: pointer; - display: flex; - align-items: center; - gap: 4px; -} -.search-save-btn:hover { background: var(--bg-hover); } - -/* Saved searches sidebar */ -.saved-search-item { - position: relative; - padding: 10px 12px; - cursor: pointer; - border-radius: 6px; - transition: background 0.15s; - border: 1px solid transparent; - margin-bottom: 4px; -} -.saved-search-item:hover { background: var(--bg-hover); border-color: var(--border); } -.saved-search-query { - font-size: 0.82rem; - font-family: "JetBrains Mono", monospace; - line-height: 1.4; - word-break: break-word; - overflow-wrap: anywhere; - margin-bottom: 6px; -} -.saved-search-meta { - display: flex; - gap: 4px; - align-items: center; - flex-wrap: wrap; - margin-bottom: 2px; -} -.saved-search-badges { - display: flex; - gap: 4px; - align-items: center; - flex-wrap: wrap; - flex: 1; - min-width: 0; -} -.saved-search-type-icon { - margin-left: auto; - flex-shrink: 0; - opacity: 0.6; -} -/* Saved filter bar */ -.saved-filter-bar { - display: flex; - gap: 6px; - padding: 8px 10px 10px; -} -.saved-filter-pill { - padding: 3px 10px; - font-size: 0.7rem; - font-weight: 500; - border: 1px solid var(--border); - border-radius: 12px; - background: transparent; - color: var(--text-secondary); - cursor: pointer; - transition: background 0.15s, color 0.15s, border-color 0.15s; -} -.saved-filter-pill:hover { background: var(--bg-hover); color: var(--text-primary); } -.saved-filter-pill.active { - background: var(--accent-bg, rgba(99,102,241,0.12)); - color: var(--accent); - border-color: var(--accent); -} -/* Offline indicator */ -.offline-indicator { - display: flex; - align-items: center; - gap: 6px; - padding: 2px 8px; - border-radius: 4px; - font-size: 0.7rem; - cursor: default; -} -.offline-indicator.offline { - background: var(--warn-bg, rgba(251,191,36,0.12)); - color: var(--warn); - border: 1px solid var(--warn); -} -.offline-pending { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 16px; - height: 16px; - padding: 0 4px; - border-radius: 8px; - background: var(--warn); - color: #000; - font-size: 0.6rem; - font-weight: 700; -} -/* Theme picker grid */ -.theme-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); - gap: 10px; - margin-top: 12px; -} -.theme-card { - background: var(--bg-secondary); - border: 2px solid var(--border); - border-radius: 8px; - padding: 10px; - cursor: pointer; - transition: border-color 0.2s, transform 0.15s; -} -.theme-card:hover { border-color: var(--accent); transform: translateY(-1px); } -.theme-card.active { border-color: var(--accent-green); } -.theme-card-preview { - height: 40px; - border-radius: 4px; - margin-bottom: 8px; - overflow: hidden; - display: flex; - flex-direction: column; -} -.theme-card-preview-bar { - height: 14px; -} -.theme-card-preview-body { - flex: 1; - display: flex; - align-items: center; - padding: 0 6px; -} -.theme-card-preview-btn { - width: 50%; - height: 10px; - border-radius: 3px; -} -.theme-card-name { - font-size: 0.75rem; - font-weight: 600; - color: var(--text-primary); - margin-bottom: 2px; -} -.theme-card-desc { - font-size: 0.65rem; - color: var(--text-muted); -} -.theme-mode-toggle { - display: flex; - gap: 0; - margin-top: 16px; - border: 1px solid var(--border); - border-radius: 6px; - overflow: hidden; - width: fit-content; -} -.theme-mode-btn { - padding: 4px 14px; - font-size: 0.7rem; - border: none; - background: transparent; - color: var(--text-secondary); - cursor: pointer; -} -.theme-mode-btn.active { - background: var(--accent); - color: #fff; -} -/* Profile section */ -.profile-form { max-width: 420px; } -.profile-field { margin-bottom: 14px; } -.profile-field label { display: block; font-size: 0.75rem; font-weight: 600; color: var(--text-primary); margin-bottom: 4px; } -.profile-field .config-input, -.profile-field .config-select { - width: 100%; padding: 6px 10px; font-size: 0.8rem; - background: var(--bg-primary); color: var(--text-primary); - border: 1px solid var(--border); border-radius: 6px; - font-family: inherit; -} -.profile-hint { display: block; font-size: 0.65rem; color: var(--text-muted); margin-top: 4px; } -.profile-saved { font-size: 0.7rem; color: var(--accent-green); margin-left: 10px; } -.config-save-btn { - padding: 6px 18px; font-size: 0.75rem; font-weight: 600; - background: var(--accent); color: #fff; - border: 1px solid var(--accent); border-radius: 6px; - cursor: pointer; transition: opacity 0.15s; -} -.config-save-btn:hover { opacity: 0.85; } -.saved-search-vault { - font-size: 0.65rem; - color: var(--text-muted); - padding: 1px 5px; - background: var(--bg-secondary); - border-radius: 3px; -} -.saved-search-filters { - font-size: 0.65rem; - color: var(--accent); - display: flex; - gap: 4px; - flex-wrap: wrap; -} -.saved-search-path { - font-size: 0.6rem; - color: #059669; - background: rgba(5,150,105,0.08); - padding: 1px 5px; - border-radius: 3px; - max-width: 100%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.saved-search-delete { - position: absolute; - top: 6px; - right: 8px; - background: none; - border: none; - color: var(--text-muted); - cursor: pointer; - font-size: 0.9rem; - padding: 2px 6px; - opacity: 0; - transition: opacity 0.15s; -} -.saved-search-item:hover .saved-search-delete { opacity: 1; } -.saved-search-delete:hover { color: var(--text-error); } -.search-result-title { - font-family: "JetBrains Mono", monospace; - font-size: 0.92rem; - font-weight: 600; - color: var(--text-primary); - margin-bottom: 4px; -} -.search-result-vault { - font-family: "JetBrains Mono", monospace; - font-size: 0.72rem; - color: var(--accent-green); - margin-bottom: 4px; -} -.search-result-snippet { - font-size: 0.85rem; - color: var(--text-secondary); - line-height: 1.5; -} -.search-result-snippet .search-highlight { - background: color-mix(in srgb, var(--accent) 25%, transparent); - color: var(--accent); - font-weight: 600; - padding: 1px 3px; - border-radius: 3px; -} -.search-result-title .search-highlight { - background: color-mix(in srgb, var(--accent) 25%, transparent); - color: var(--accent); - font-weight: 700; - padding: 1px 3px; - border-radius: 3px; -} -.search-result-tags { - margin-top: 6px; - display: flex; - flex-wrap: wrap; - gap: 4px; -} -.search-result-tags .file-tag { - font-size: 0.7rem; - padding: 1px 6px; -} - -/* --- Loading indicator --- */ -.loading-indicator { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 40px 20px; - color: var(--text-muted); - gap: 12px; -} -.loading-spinner { - width: 32px; - height: 32px; - border: 3px solid var(--border); - border-top-color: var(--accent); - border-radius: 50%; - animation: spin 0.8s linear infinite; -} -@keyframes spin { - to { - transform: rotate(360deg); - } -} - -/* --- Search progress bar --- */ -.search-progress-bar { - position: fixed; - top: 0; - left: 0; - right: 0; - height: 3px; - z-index: 9999; - background: transparent; - pointer-events: none; - opacity: 0; - transition: opacity 0.15s; -} -.search-progress-bar.active { - opacity: 1; -} -.search-progress-bar .search-progress-bar__fill { - height: 100%; - background: var(--accent); - width: 0%; - animation: progress-indeterminate 1.5s ease-in-out infinite; -} -@keyframes progress-indeterminate { - 0% { - width: 0%; - margin-left: 0%; - } - 50% { - width: 40%; - margin-left: 30%; - } - 100% { - width: 0%; - margin-left: 100%; - } -} -.search-time-badge { - font-size: 0.7rem; - color: var(--text-muted); - margin-left: 8px; -} - -/* --- Editor Modal --- */ -.editor-modal { - display: none; - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 1000; - background: var(--overlay-bg); - align-items: center; - justify-content: center; - padding: 20px; -} -.editor-modal.active { - display: flex; -} -.help-container { - max-width: 1320px; -} -.editor-container { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 12px; - width: 100%; - max-width: 1200px; - max-height: 90vh; - display: flex; - flex-direction: column; - overflow: hidden; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4); -} -.editor-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 12px 16px; - border-bottom: 1px solid var(--border); - background: var(--bg-primary); - flex-shrink: 0; - position: sticky; - top: 0; - z-index: 10; -} - -/* AI processing indicator — shown inside editor header during AI calls */ -.ai-processing-indicator { - display: none; - align-items: center; - gap: 6px; - padding: 3px 10px; - border-radius: 12px; - font-size: 0.72rem; - font-weight: 500; - color: #ffffff; - background: rgba(59, 130, 246, 0.3); - border: 1px solid rgba(96, 165, 250, 0.4); - animation: ai-indicator-pulse 1s ease-in-out infinite; - margin-left: 12px; -} - -.ai-spinner { - width: 10px; - height: 10px; - border: 2px solid rgba(255,255,255,0.3); - border-top-color: #ffffff; - border-radius: 50%; - animation: ai-spinner-spin 0.6s linear infinite; -} - -@keyframes ai-spinner-spin { - to { transform: rotate(360deg); } -} - -@keyframes ai-indicator-pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.6; } -} - -.editor-title { - font-family: "JetBrains Mono", monospace; - font-size: 0.9rem; - color: var(--text-primary); - font-weight: 600; -} -.editor-brand { font-weight: 700; font-size: 12px; color: var(--accent); letter-spacing: 0.5px; white-space: nowrap; margin-right: 8px; } -.editor-title-input { flex: 1; min-width: 80px; background: transparent; border: 1px solid transparent; color: var(--text-primary); font-size: 13px; padding: 3px 6px; border-radius: 6px; outline: none; font-family: var(--font-sans); } -.editor-title-input:hover { border-color: var(--border); } -.editor-title-input:focus { border-color: var(--accent); background: var(--bg-input); } -.editor-sep { color: var(--text-muted); font-size: 13px; padding: 0 2px; user-select: none; } -.editor-filename-input { width: 140px; background: transparent; border: 1px solid transparent; color: var(--text-primary); font-size: 12px; padding: 3px 6px; border-radius: 6px; outline: none; font-family: var(--font-mono); } -.editor-filename-input:hover { border-color: var(--border); } -.editor-filename-input:focus { border-color: var(--ok); background: var(--bg-input); } -.editor-spacer { flex: 1; } -.editor-save-dot { display: flex; align-items: center; gap: 4px; font-size: 11px; padding: 0 4px; margin-right: 8px; } -.editor-btn + .editor-btn { margin-left: 6px; } -.editor-save-dot .dot { width: 6px; height: 6px; border-radius: 50%; } -.editor-save-dot.ok { color: var(--ok); } .editor-save-dot.ok .dot { background: var(--ok); } -.editor-save-dot.dirty { color: var(--warn); } .editor-save-dot.dirty .dot { background: var(--warn); } -.editor-save-dot.saving { color: var(--ai); } .editor-save-dot.saving .dot { background: var(--ai); } -@keyframes editor-pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.4; } } -.editor-save-dot.saving { animation: editor-pulse 0.8s infinite; } -.editor-save-dot.err { color: var(--err); } .editor-save-dot.err .dot { background: var(--err); } -.editor-body-cm { flex: 1; overflow: auto; } -.editor-body-cm .cm-editor { height: 100%; } -.editor-body-cm .cm-editor .cm-scroller { font-family: var(--font-mono); font-size: 13.5px; line-height: 1.75; } -.editor-footer { height: 26px; min-height: 26px; display: flex; align-items: center; justify-content: space-between; padding: 0 12px; background: var(--bg-secondary); border-top: 1px solid var(--border); font-size: 11px; color: var(--text-muted); flex-shrink: 0; } -.editor-stat-file { color: var(--text-secondary); max-width: 320px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } -.editor-actions { - display: flex; - gap: 6px; -} -.editor-btn { - width: 36px; - height: 36px; - padding: 0; - border: 1px solid var(--border); - border-radius: 6px; - background: transparent; - color: var(--text-secondary); - cursor: pointer; - transition: all 150ms ease; - display: inline-flex; - align-items: center; - justify-content: center; - flex: 0 0 auto; -} -.editor-btn:hover { - color: var(--accent); - border-color: var(--accent); -} -.editor-btn.primary { - background: var(--accent); - color: #ffffff; - border-color: var(--accent); -} -.editor-btn.primary:hover { - opacity: 0.9; -} -.editor-btn.danger:hover { - color: var(--danger); - border-color: var(--danger); -} -.editor-body { - flex: 1; - min-height: 0; - position: relative; - overflow-y: auto; - overflow-x: hidden; -} -.help-body { - padding: 0; - background: radial-gradient(circle at top right, color-mix(in srgb, var(--accent) 10%, transparent), transparent 30%), var(--bg-primary); - display: flex; - gap: 0; - overflow-y: auto; - overflow-x: hidden; - scroll-behavior: smooth; -} - -/* Help Navigation Menu */ -.help-hamburger { - display: none; - width: 36px; height: 36px; - padding: 0; - border: 1px solid var(--border); - border-radius: 6px; - background: transparent; - color: var(--text-secondary); - cursor: pointer; - align-items: center; - justify-content: center; - flex-shrink: 0; - margin-right: 8px; -} -.help-hamburger:hover { color: var(--accent); border-color: var(--accent); } -.help-nav { - width: 260px; - min-width: 260px; - background: color-mix(in srgb, var(--bg-secondary) 94%, var(--bg-primary)); - border-right: 1px solid color-mix(in srgb, var(--border) 85%, transparent); - display: flex; - flex-direction: column; - position: sticky; - top: 0; - align-self: flex-start; - height: 100%; - max-height: calc(90vh - 57px); - flex-shrink: 0; - backdrop-filter: blur(12px); - overflow: hidden; -} -.help-nav-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 20px 16px 10px; - flex-shrink: 0; -} -.help-nav-title { - font-family: "JetBrains Mono", monospace; - font-size: 0.75rem; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--text-muted); -} -.help-nav-search-wrap { - padding: 0 12px 8px; - flex-shrink: 0; - display: flex; - align-items: center; - gap: 0; -} -.help-nav-search { - flex: 1; - padding: 7px 10px; - border: 1px solid var(--border); - border-right: none; - border-radius: 8px 0 0 8px; - background: var(--bg-primary); - color: var(--text-primary); - font-size: 0.78rem; - outline: none; - transition: border-color 0.2s; - min-width: 0; -} -.help-nav-search:focus { - border-color: var(--accent); -} -.help-nav-search:focus + .help-search-clear { - border-color: var(--accent); - border-left-color: var(--accent); -} -.help-nav-search::placeholder { color: var(--text-muted); } -.help-search-clear { - padding: 7px 10px; - border: 1px solid var(--border); - border-left: none; - border-radius: 0 8px 8px 0; - background: var(--bg-primary); - color: var(--text-muted); - cursor: pointer; - font-size: 14px; - line-height: 1; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - transition: color 0.15s, background 0.15s; -} -.help-search-clear:hover { - color: var(--text-primary); - background: rgba(255,255,255,0.06); -} -.help-nav-list { - list-style: none; - margin: 0; - padding: 0 12px 20px; - flex: 1; - overflow-y: auto; - overflow-x: hidden; - scrollbar-width: thin; - scrollbar-color: var(--border) transparent; -} -.help-nav-list li { - margin: 0 0 3px; -} -.help-nav-link { - display: block; - padding: 8px 12px; - font-size: 0.85rem; - color: var(--text-secondary); - text-decoration: none; - transition: all 150ms ease; - border: 1px solid transparent; - border-radius: 8px; - outline: none; -} -.help-nav-link:hover { - color: var(--accent); - background: color-mix(in srgb, var(--bg-hover) 80%, transparent); - border-color: color-mix(in srgb, var(--accent) 16%, transparent); - text-decoration: none; - transform: translateX(2px); -} -.help-nav-link:focus-visible { - outline: 2px solid var(--accent); - outline-offset: -2px; - border-radius: 8px; -} -.help-nav-link.active { - color: var(--accent); - background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 16%, transparent), color-mix(in srgb, var(--accent) 7%, transparent)); - border-color: color-mix(in srgb, var(--accent) 22%, transparent); - font-weight: 600; - box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 10%, transparent); -} -.help-nav-link.hidden { - display: none; -} -.help-section.help-hidden { - display: none; -} -.help-search-highlight { - background: rgba(250, 204, 21, 0.35); - color: inherit; - border-radius: 2px; - padding: 0 1px; -} - -.help-content { - flex: 1; - max-width: 980px; - margin: 0 auto; - padding: 32px 40px 56px; - overflow: visible; - min-width: 0; -} -.help-lead { - font-size: 1.08rem; - line-height: 1.75; - color: var(--text-primary); - margin-bottom: 18px; -} -.help-footer { - margin-top: 48px; - padding-top: 24px; - border-top: 1px solid var(--border); - text-align: center; - color: var(--text-muted); - font-size: 0.85rem; -} -.help-footer a { - color: var(--accent); - text-decoration: none; -} -.help-footer a:hover { - text-decoration: underline; -} -.help-content h1, -.help-content h2, -.help-content h3 { - font-family: "JetBrains Mono", monospace; - color: var(--text-primary); -} -.help-content h1 { - font-size: 2rem; - margin-bottom: 16px; - letter-spacing: -0.02em; -} -.help-content h2 { - font-size: 1.18rem; - margin: 0 0 14px; -} -.help-content h3 { - font-size: 0.95rem; - margin: 20px 0 8px; - color: var(--text-secondary); -} -.help-content p { - margin: 0 0 14px; - color: var(--text-secondary); - line-height: 1.7; -} -.help-content pre, -.help-content table { - max-width: 100%; - overflow-x: auto; -} -.help-content pre code { - white-space: pre; -} -.help-content ul, -.help-content ol { - margin: 10px 0 18px; - padding-left: 24px; - color: var(--text-secondary); -} -.help-content ul li, -.help-content ol li { - margin: 6px 0; - line-height: 1.6; -} -.help-content code { - font-family: "JetBrains Mono", monospace; - background: var(--code-bg); - border: 1px solid var(--border); - border-radius: 4px; - padding: 1px 5px; - color: var(--text-primary); - font-size: 0.88em; -} -.help-content strong { - color: var(--text-primary); - font-weight: 600; -} - -.help-section { - position: relative; - margin-bottom: 22px; - padding: 24px 26px; - border: 1px solid color-mix(in srgb, var(--border) 82%, transparent); - border-radius: 18px; - background: linear-gradient(180deg, color-mix(in srgb, var(--bg-secondary) 94%, var(--bg-primary)), color-mix(in srgb, var(--bg-secondary) 86%, var(--bg-primary))); - box-shadow: 0 14px 34px rgba(0, 0, 0, 0.18); -} - -.help-section::before { - content: ""; - position: absolute; - inset: 0; - border-radius: inherit; - pointer-events: none; - background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 8%, transparent), transparent 35%); -} - -.help-hero { - display: grid; - grid-template-columns: minmax(0, 1.5fr) minmax(260px, 1fr); - gap: 22px; - align-items: stretch; - padding: 22px; - border: 1px solid color-mix(in srgb, var(--accent) 16%, var(--border)); - border-radius: 18px; - background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 12%, transparent), transparent 45%), color-mix(in srgb, var(--bg-secondary) 92%, var(--bg-primary)); - margin-bottom: 26px; -} - -.help-kicker { - display: inline-flex; - align-items: center; - padding: 5px 10px; - border-radius: 999px; - background: color-mix(in srgb, var(--accent) 16%, transparent); - color: var(--accent); - font-family: "JetBrains Mono", monospace; - font-size: 0.72rem; - margin-bottom: 12px; -} - -.help-badges { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-top: 16px; -} - -.help-badge { - display: inline-flex; - align-items: center; - padding: 6px 10px; - border-radius: 999px; - background: color-mix(in srgb, var(--bg-primary) 72%, transparent); - border: 1px solid var(--border); - color: var(--text-primary); - font-size: 0.8rem; -} - -.help-hero-visual { - display: flex; - align-items: center; - justify-content: center; -} - -.help-mini-window { - width: 100%; - max-width: 320px; - border-radius: 18px; - overflow: hidden; - border: 1px solid color-mix(in srgb, var(--accent) 18%, var(--border)); - background: color-mix(in srgb, var(--bg-primary) 88%, black 12%); - box-shadow: 0 18px 44px rgba(0, 0, 0, 0.28); -} - -.help-mini-window-bar { - display: flex; - gap: 7px; - padding: 12px 14px; - border-bottom: 1px solid var(--border); -} - -.help-mini-window-bar span { - width: 9px; - height: 9px; - border-radius: 50%; - background: color-mix(in srgb, var(--accent) 45%, var(--text-muted)); -} - -.help-mini-window-body { - display: flex; - min-height: 190px; -} - -.help-mini-sidebar { - width: 72px; - background: color-mix(in srgb, var(--bg-secondary) 92%, black 8%); - border-right: 1px solid var(--border); -} - -.help-mini-content { - flex: 1; - padding: 16px; -} - -.help-mini-line { - height: 10px; - border-radius: 999px; - background: color-mix(in srgb, var(--text-muted) 28%, transparent); - margin-bottom: 10px; -} - -.help-mini-line.short { - width: 62%; -} - -.help-mini-tags { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin: 14px 0; -} - -.help-mini-tags span { - padding: 3px 8px; - border-radius: 999px; - background: color-mix(in srgb, var(--accent) 16%, transparent); - color: var(--text-primary); - font-size: 0.72rem; -} - -.help-mini-card { - height: 64px; - border-radius: 12px; - border: 1px solid var(--border); - background: linear-gradient(180deg, color-mix(in srgb, var(--bg-secondary) 94%, white 6%), var(--bg-primary)); -} - -.help-grid { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: 16px; - margin-bottom: 26px; -} - -.help-card { - padding: 18px; - border-radius: 16px; - border: 1px solid var(--border); - background: color-mix(in srgb, var(--bg-secondary) 92%, var(--bg-primary)); -} - -.help-card-icon { - width: 42px; - height: 42px; - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: 12px; - background: color-mix(in srgb, var(--accent) 14%, transparent); - font-size: 1.2rem; - margin-bottom: 10px; -} - -.help-section { - margin-top: 26px; -} - -.help-feature-list, -.help-steps, -.help-checklist, -.help-tip-grid { - display: grid; - gap: 14px; -} - -.help-feature-item, -.help-step, -.help-check-item, -.help-tip-card { - border: 1px solid var(--border); - border-radius: 16px; - background: color-mix(in srgb, var(--bg-secondary) 92%, var(--bg-primary)); -} - -.help-feature-item { - display: grid; - grid-template-columns: 52px minmax(0, 1fr); - gap: 14px; - padding: 16px; -} - -.help-feature-emoji { - width: 52px; - height: 52px; - display: flex; - align-items: center; - justify-content: center; - border-radius: 14px; - background: color-mix(in srgb, var(--accent) 12%, transparent); - font-size: 1.4rem; -} - -.help-steps { - counter-reset: step; -} - -.help-step { - display: grid; - grid-template-columns: 44px minmax(0, 1fr); - gap: 14px; - padding: 16px; -} - -.help-step-number { - width: 44px; - height: 44px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - background: color-mix(in srgb, var(--accent) 18%, transparent); - color: var(--accent); - font-family: "JetBrains Mono", monospace; - font-weight: 700; -} - -.help-check-item { - display: grid; - grid-template-columns: 28px minmax(0, 1fr); - gap: 12px; - padding: 14px 16px; - align-items: start; -} - -.help-check-item span { - font-size: 1rem; - line-height: 1.4; -} - -.help-check-item p { - margin-bottom: 0; -} - -.help-tip-panel { - margin-top: 28px; -} - -.help-tip-grid { - grid-template-columns: repeat(3, minmax(0, 1fr)); -} - -.help-tip-card { - padding: 16px; -} -.cm-editor { - height: auto; - min-height: 100%; - font-size: 0.9rem; -} -.cm-scroller { - font-family: "JetBrains Mono", monospace; - overflow-y: auto !important; - overflow-x: auto !important; - height: auto; - min-height: 100%; - max-width: 100%; -} -.fallback-editor { - width: 100%; - min-height: 100%; - height: auto; - border: none; - outline: none; - resize: none; - padding: 16px; - background: var(--code-bg); - color: var(--text-primary); - font-family: "JetBrains Mono", monospace; - font-size: 0.9rem; - line-height: 1.55; - box-sizing: border-box; - overflow-y: auto; - overflow-x: auto; - white-space: pre-wrap; - word-wrap: break-word; -} - -/* Mobile right sidebar - hide by default */ -@media (max-width: 768px) { - .right-sidebar { - display: none; - } - .right-sidebar-resize-handle { - display: none; - } -} - -/* Mobile help navigation */ -@media (max-width: 768px) { - .help-nav { - display: none; - } - .help-content { - padding: 20px 16px 32px; - } - .vault-context-indicator { - /* Keep visible on mobile — same look as desktop */ - padding: 4px 8px; - font-size: 0.7rem; - } -} - -/* Mobile editor */ -@media (max-width: 768px) { - .editor-modal { - padding: 0; - align-items: stretch; - } - .editor-container { - max-width: 100%; - max-height: 100vh; - border-radius: 0; - height: 100vh; - overflow: hidden; - } - .editor-header { - padding: 10px 12px; - position: sticky; - top: 0; - z-index: 20; - background: var(--bg-primary); - } - .editor-title { - font-size: 0.85rem; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - .editor-actions { - gap: 4px; - } - .editor-btn { - width: 36px; - height: 36px; - min-width: 36px; - } - .editor-body { - flex: 1; - min-height: 0; - overflow: auto; - } - .cm-editor { - height: auto; - min-height: 100%; - } - .cm-scroller { - overflow: auto !important; - height: auto; - min-height: 100%; - } - .fallback-editor { - min-height: 100%; - height: auto; - } - .search-results-header { - align-items: flex-start; - } -} - -/* --- No-select during resize --- */ -body.resizing { - user-select: none; - -webkit-user-select: none; - cursor: ew-resize; -} -body.resizing-v { - user-select: none; - -webkit-user-select: none; - cursor: ns-resize; -} - -/* --- Responsive — Tablet --- */ -@media (max-width: 1024px) { - .sidebar { - width: 240px; - min-width: 200px; - } -} - -/* --- Responsive — Mobile --- */ -@media (max-width: 768px) { - .hamburger-btn { - display: flex; - } - - .sidebar-toggle-btn { - display: none; - } - - .header { - flex-wrap: wrap; - gap: 8px 10px; - padding: 10px 12px; - } - - .header-left { - flex: 1; - gap: 12px; - } - - .header-center { - flex: 0 0 100%; - order: 3; - max-width: none; - padding: 4px 0; - } - - .header-right { - flex: 0 0 auto; - gap: 8px; - } - - .header-logo { - font-size: 1.05rem; - gap: 8px; - } - - .user-display-name { - display: none; /* Masquer le nom d'utilisateur sur mobile pour gagner de la place */ - } - - .search-wrapper { - max-width: none; - width: 100%; - } - - .search-input-wrapper input { - padding: 10px 40px 10px 40px; - font-size: 1rem; - border-radius: 12px; - } - - .search-wrapper .search-icon { - left: 14px; - top: 14px; - width: 18px !important; - height: 18px !important; - } - - /* Mobile: keep only filter + clear visible in header search */ - .search-actions .tog, - .search-actions .search-sep, - .search-actions .search-count { display: none; } - .search-actions { gap: 4px; } - .search-actions .search-btn#search-clear-btn { display: flex; } - - .search-dropdown { - position: fixed; - top: 100px; - left: 8px; - right: 8px; - width: calc(100vw - 16px); - max-height: calc(100vh - 120px); - border-radius: 12px; - box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4); - } - - .search-dropdown__item { - padding: 14px 16px; - font-size: 0.95rem; - } - - .search-dropdown__icon { - width: 18px; - height: 18px; - margin-right: 8px; - } - - .header-menu-btn { - padding: 10px; - border-radius: 10px; - } - - .header-menu-dropdown { - position: fixed; - top: 60px; - right: 10px; - left: 10px; - width: auto; - min-width: 0; - border-radius: 16px; - } - - .sidebar-quick-select { - padding: 0 16px 12px; - } - - .sidebar-quick-select select { - color-scheme: dark; - background-color: var(--bg-secondary); - color: var(--text-primary); - } - - [data-theme="dark"] .sidebar-quick-select select { - background-color: #1e1e1e; - color: #e0e0e0; - } - - .sidebar-panel-toggle { - padding: 8px 12px 10px; - } - - .tag-cloud { - padding: 0 12px 12px; - } - - .sidebar { - position: fixed; - top: 0; - left: 0; - bottom: 0; - z-index: 200; - width: 280px !important; - min-width: 280px !important; - max-width: 85vw !important; - transform: translateX(-100%); - transition: - transform 250ms ease, - background 200ms ease; - box-shadow: none; - } - .sidebar.mobile-open { - transform: translateX(0); - box-shadow: 4px 0 20px rgba(0, 0, 0, 0.3); - } - - /* Mobile sidebar overlay */ - .sidebar-overlay { - display: none; - position: fixed; - inset: 0; - background: rgba(0,0,0,0.4); - z-index: 199; - } - .sidebar-overlay.active { display: block; } - - /* Right Sidebar handling on mobile */ - .right-sidebar { - position: fixed; - top: 0; - right: 0; - bottom: 0; - z-index: 200; - width: 280px !important; - min-width: 280px !important; - max-width: 85vw !important; - transform: translateX(100%); - transition: - transform 250ms ease, - background 200ms ease; - box-shadow: none; - border-left: 1px solid var(--border); - } - .right-sidebar.hidden { - transform: translateX(100%) !important; - width: 280px !important; - min-width: 280px !important; - display: flex; - } - .right-sidebar:not(.hidden) { - transform: translateX(0) !important; - box-shadow: -4px 0 20px rgba(0, 0, 0, 0.3) !important; - display: flex !important; - visibility: visible !important; - } - - .right-sidebar-resize-handle { - display: none; - } - - .sidebar-resize-handle { - display: none; - } - - .tag-resize-handle { - display: none; - } - - .tag-cloud-section { - height: auto; - max-height: 200px; - min-height: 80px; - } - - #vault-panel-content { - max-height: none; - } - #tag-panel-content { - max-height: none; - } - - .help-content { - padding: 20px 16px 28px; - } - - .help-hero { - grid-template-columns: 1fr; - padding: 18px; - } - - .help-grid, - .help-tip-grid { - grid-template-columns: 1fr; - } - - .content-area { - padding: 12px 8px 24px; - width: 100%; - } - - .file-title { - font-size: 1.15rem; - } - - .file-actions { - flex-wrap: wrap; - gap: 4px; - } - - .file-actions .btn-action { - padding: 6px 8px; - font-size: 0.75rem; - } - - /* Full-width search results */ - .search-result-item { - padding: 12px 14px; - border-radius: 8px; - margin-bottom: 8px; - } - - .search-result-title { - font-size: 0.9rem; - padding-right: 40px; - } - - .search-result-ext { - top: 6px; - right: 8px; - font-size: 0.6rem; - } - - .search-results-header { - flex-wrap: wrap; - gap: 6px; - } - - /* Full-width dashboard */ - .dashboard-stats-grid { - grid-template-columns: repeat(2, 1fr); - gap: 8px; - } - - .stat-card { - padding: 12px 8px; - } - - .dashboard-tab { - padding: 6px 5px !important; - font-size: 0 !important; - gap: 0 !important; - overflow: hidden; - min-width: 32px; - } - .dashboard-tab > *:not(i):not(svg) { display: none; } - .dashboard-tab i, .dashboard-tab svg { - width: 18px !important; - height: 18px !important; - flex-shrink: 0; - } - - .breadcrumb { - font-size: 0.75rem; - flex-wrap: wrap; - } - - /* Mobile tab bar */ - .tab-bar { - padding: 0 4px; - } - .tab-item { - padding: 6px 10px; - font-size: 0.7rem; - } - .tab-item .tab-name { max-width: 80px; } - .tab-item .tab-close { opacity: 0.6; width: 14px; height: 14px; } - - .md-content { - padding: 0 4px; - } - - .md-content h1 { font-size: 1.4rem; } - .md-content h2 { font-size: 1.15rem; } - .md-content h3 { font-size: 1rem; } - - .md-content pre { - margin: 8px -4px; - border-radius: 6px; - padding: 10px 12px; - font-size: 0.8rem; - } - - /* Full-width content wrapper */ - .content-wrapper { - margin-left: 0 !important; - } -} - -/* --- Configuration Modal --- */ -.config-content { - max-width: 720px; - margin: 0 auto; - padding: 28px 24px 40px; -} - -.config-section { - margin-bottom: 28px; -} - -.config-section h2 { - font-family: "JetBrains Mono", monospace; - font-size: 1.05rem; - font-weight: 600; - color: var(--text-primary); - margin-bottom: 8px; -} - -.config-description { - font-size: 0.85rem; - color: var(--text-secondary); - margin-bottom: 16px; - line-height: 1.5; -} - -.config-filters-list { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-bottom: 16px; - min-height: 32px; -} - -.config-filter-badge { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 6px 12px; - background: var(--tag-bg); - color: var(--tag-text); - border-radius: 6px; - font-family: "JetBrains Mono", monospace; - font-size: 0.8rem; - border: 1px solid color-mix(in srgb, var(--tag-text) 30%, transparent); -} - -.config-filter-badge.disabled { - opacity: 0.5; -} - -.config-filter-remove { - display: inline-flex; - align-items: center; - justify-content: center; - width: 16px; - height: 16px; - border: none; - background: transparent; - color: inherit; - cursor: pointer; - padding: 0; - font-size: 1.1rem; - line-height: 1; -} - -.config-filter-remove:hover { - opacity: 0.7; -} - -.config-filter-toggle { - display: inline-flex; - align-items: center; - justify-content: center; - width: 16px; - height: 16px; - border: none; - background: transparent; - color: inherit; - cursor: pointer; - padding: 0; - font-size: 0.9rem; -} - -.config-add-pattern { - display: flex; - gap: 8px; - margin-bottom: 12px; -} - -.config-input { - flex: 1; - padding: 8px 12px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-secondary); - color: var(--text-primary); - font-family: "JetBrains Mono", monospace; - font-size: 0.8rem; - outline: none; - transition: border-color 200ms ease; -} - -.config-input:focus { - border-color: var(--accent); -} - -.config-select { - padding: 8px 12px; - border: 1px solid var(--border); - border-radius: var(--r); - background: var(--bg-input); - color: var(--text-primary); - font-size: 0.86rem; - font-family: var(--mono); - cursor: pointer; -} - -.config-btn-add { - padding: 8px 16px; - border: 1px solid var(--accent); - border-radius: 6px; - background: var(--accent); - color: #ffffff; - font-family: "JetBrains Mono", monospace; - font-size: 0.8rem; - font-weight: 600; - cursor: pointer; - transition: opacity 150ms ease; -} - -.config-btn-add:hover { - opacity: 0.9; -} - -.config-regex-preview { - padding: 8px 12px; - background: var(--code-bg); - border: 1px solid var(--border); - border-radius: 6px; - font-size: 0.75rem; - color: var(--text-secondary); -} - -.config-regex-preview code { - font-family: "JetBrains Mono", monospace; - color: var(--accent); - background: transparent; - border: none; - padding: 0; -} - -/* --- Config rows & controls --- */ -.config-row { - display: grid; - grid-template-columns: 200px 120px 1fr; - align-items: center; - gap: 12px; - margin-bottom: 10px; -} -.config-label { - font-size: 0.82rem; - color: var(--text-primary); - font-weight: 500; -} -.config-input--num { - flex: none; - width: 120px; - text-align: right; -} -.config-hint { - font-size: 0.72rem; - color: var(--text-muted); -} -.config-badge-restart { - display: inline-block; - font-size: 0.65rem; - font-weight: 500; - padding: 2px 8px; - border-radius: 4px; - background: var(--danger-bg, #3d1a18); - color: var(--danger, #ff7b72); - vertical-align: middle; - margin-left: 6px; -} -.config-actions-row { - display: flex; - gap: 8px; - margin-top: 16px; - flex-wrap: wrap; -} -.config-btn-save { - padding: 8px 20px; - border: 1px solid var(--accent); - border-radius: 6px; - background: var(--accent); - color: #fff; - font-family: "JetBrains Mono", monospace; - font-size: 0.8rem; - font-weight: 600; - cursor: pointer; - transition: opacity 150ms; -} -.config-btn-save:hover { - opacity: 0.9; -} -.config-btn-save.config-btn-highlight { - background: var(--accent-green); - border-color: var(--accent-green); - animation: pulse 2s ease-in-out infinite; -} -@keyframes pulse { - 0%, - 100% { - opacity: 1; - } - 50% { - opacity: 0.8; - } -} -.config-btn-secondary { - padding: 8px 16px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-secondary); - color: var(--text-primary); - font-family: "JetBrains Mono", monospace; - font-size: 0.8rem; - cursor: pointer; - transition: background 150ms; -} -.config-btn-secondary:hover { - background: var(--bg-hover); -} - -/* --- Config diagnostics panel --- */ -.config-diagnostics { - background: var(--code-bg); - border: 1px solid var(--border); - border-radius: 6px; - padding: 14px 16px; - font-family: "JetBrains Mono", monospace; - font-size: 0.78rem; - line-height: 1.7; - color: var(--text-secondary); -} -.config-diag-loading { - color: var(--text-muted); -} -.config-diag-row { - display: flex; - justify-content: space-between; -} -.config-diag-row .diag-label { - color: var(--text-secondary); -} -.config-diag-row .diag-value { - color: var(--text-primary); - font-weight: 500; -} -.config-diag-section { - margin-bottom: 8px; - padding-bottom: 8px; - border-bottom: 1px solid var(--border); -} -.config-diag-section:last-child { - margin-bottom: 0; - padding-bottom: 0; - border-bottom: none; -} -.config-diag-section-title { - font-weight: 600; - color: var(--accent); - margin-bottom: 4px; - font-size: 0.75rem; - text-transform: uppercase; - letter-spacing: 0.5px; -} - -@media (max-width: 768px) { - .config-row { - grid-template-columns: 1fr; - gap: 4px; - } - .config-input--num { - width: 100%; - } -} - -/* --- Toast notifications --- */ -.toast-container { - position: fixed; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - z-index: 10000; - display: flex; - flex-direction: column; - align-items: center; - gap: 8px; - pointer-events: none; -} -.toast { - padding: 10px 20px; - border-radius: 8px; - font-family: "JetBrains Mono", monospace; - font-size: 0.82rem; - color: var(--text-primary); - background: var(--bg-secondary); - border: 1px solid var(--border); - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); - opacity: 0; - transform: translateY(12px); - transition: - opacity 250ms ease, - transform 250ms ease; - pointer-events: auto; - max-width: 420px; - text-align: center; -} -.toast.show { - opacity: 1; - transform: translateY(0); -} -.toast-error { - border-color: var(--danger); - background: var(--danger-bg); - color: var(--danger); -} -.toast-success { - border-color: var(--success); - background: var(--success-bg); - color: var(--success); -} - -/* --- Tree loading indicator --- */ -.tree-loading { - display: flex; - align-items: center; - justify-content: center; - padding: 8px 16px; -} - -/* --------------------------------------------------------------------------- - Advanced Search — Autocomplete Dropdown - --------------------------------------------------------------------------- */ -.search-dropdown { - position: absolute; - top: 100%; - left: 0; - right: 0; - margin-top: 4px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 8px; - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25); - z-index: 200; -} -.search-dropdown[hidden] { - display: none; -} -.search-dropdown__section { - border-bottom: 1px solid var(--border); -} -.search-dropdown__section:last-child { - border-bottom: none; -} -.search-dropdown__section[hidden] { - display: none; -} -.search-dropdown__section-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 6px 12px; - font-size: 0.7rem; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--text-muted); - background: var(--bg-primary); - position: sticky; - top: 0; - z-index: 1; -} -.search-dropdown__clear-btn { - background: none; - border: none; - color: var(--text-muted); - cursor: pointer; - padding: 2px 4px; - border-radius: 4px; - display: flex; - align-items: center; -} -.search-dropdown__clear-btn:hover { - color: var(--danger); - background: var(--danger-bg, rgba(255, 0, 0, 0.08)); -} -.search-dropdown__list { - list-style: none; - margin: 0; - padding: 0; -} -.search-dropdown__item { - display: flex; - align-items: center; - gap: 8px; - padding: 7px 12px; - cursor: pointer; - font-size: 0.82rem; - color: var(--text-primary); - transition: background 120ms ease; -} -.search-dropdown__item:hover, -.search-dropdown__item.active { - background: var(--bg-hover); -} -.search-dropdown__item--history { - color: var(--text-secondary); -} -.search-dropdown__item--history .search-dropdown__icon { - color: var(--text-muted); -} -.search-dropdown__item--title .search-dropdown__meta { - font-size: 0.72rem; - color: var(--text-muted); - margin-left: auto; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 180px; -} -.search-dropdown__item--tag .search-dropdown__badge { - margin-left: auto; - font-size: 0.7rem; - color: var(--text-muted); - background: var(--bg-primary); - padding: 1px 6px; - border-radius: 10px; -} -.search-dropdown__icon { - flex-shrink: 0; - width: 14px; - height: 14px; - color: var(--text-muted); -} -.search-dropdown__text { - flex: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.search-dropdown__text mark { - background: var(--accent); - color: var(--bg-primary); - border-radius: 2px; - padding: 0 1px; -} -.search-dropdown__empty { - padding: 16px 12px; - text-align: center; - font-size: 0.82rem; - color: var(--text-muted); -} -.search-dropdown__empty[hidden] { - display: none; -} - -/* --------------------------------------------------------------------------- - Advanced Search — Filter Chips - --------------------------------------------------------------------------- */ -.search-chips { - display: flex; - flex-wrap: wrap; - gap: 6px; - padding: 6px 0 0; -} -.search-chips[hidden] { - display: none; -} -.search-chip { - display: inline-flex; - align-items: center; - gap: 4px; - padding: 3px 8px; - font-size: 0.75rem; - font-family: "JetBrains Mono", monospace; - border-radius: 12px; - background: var(--accent); - color: var(--bg-primary); - cursor: default; - max-width: 200px; - white-space: nowrap; -} -.search-chip__label { - overflow: hidden; - text-overflow: ellipsis; -} -.search-chip__remove { - display: flex; - align-items: center; - justify-content: center; - background: none; - border: none; - color: inherit; - cursor: pointer; - padding: 0; - opacity: 0.7; - transition: opacity 120ms; -} -.search-chip__remove:hover { - opacity: 1; -} -.search-chip--tag { - background: var(--accent); - color: var(--bg-primary); -} -.search-chip--vault { - background: var(--success, #22c55e); - color: #fff; -} -.search-chip--title { - background: var(--warning, #f59e0b); - color: #1a1a1a; -} -.search-chip--path { - background: var(--text-muted); - color: var(--bg-primary); -} - -/* --------------------------------------------------------------------------- - Advanced Search — Snippet Highlights - --------------------------------------------------------------------------- */ -.search-result__snippet mark { - background: var(--accent); - color: var(--bg-primary); - border-radius: 2px; - padding: 0 2px; - font-weight: 600; -} - -/* --------------------------------------------------------------------------- - Advanced Search — Facets Panel - --------------------------------------------------------------------------- */ -.search-facets { - display: flex; - flex-wrap: wrap; - gap: 12px; - margin-bottom: 12px; - padding: 10px 12px; - background: var(--bg-primary); - border: 1px solid var(--border); - border-radius: 8px; -} -.search-facets[hidden] { - display: none; -} -.search-facets__group { - display: flex; - flex-wrap: wrap; - gap: 6px; - align-items: center; -} -.search-facets__label { - font-size: 0.72rem; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--text-muted); - margin-right: 4px; -} -.search-facets__item { - display: inline-flex; - align-items: center; - gap: 4px; - padding: 2px 8px; - font-size: 0.75rem; - border: 1px solid var(--border); - border-radius: 12px; - color: var(--text-secondary); - background: var(--bg-secondary); - cursor: pointer; - transition: - border-color 120ms, - background 120ms; -} -.search-facets__item:hover { - border-color: var(--accent); - background: var(--bg-hover); -} -.search-facets__item .facet-count { - font-size: 0.68rem; - color: var(--text-muted); -} - -/* --------------------------------------------------------------------------- - Advanced Search — Pagination - --------------------------------------------------------------------------- */ -.search-pagination { - display: flex; - align-items: center; - justify-content: center; - gap: 8px; - padding: 12px 0; -} -.search-pagination__btn { - padding: 6px 14px; - font-size: 0.82rem; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-secondary); - color: var(--text-primary); - cursor: pointer; - transition: - border-color 120ms, - background 120ms; -} -.search-pagination__btn:hover:not(:disabled) { - border-color: var(--accent); - background: var(--bg-hover); -} -.search-pagination__btn:disabled { - opacity: 0.4; - cursor: not-allowed; -} -.search-pagination__info { - font-size: 0.78rem; - color: var(--text-muted); -} - -/* --------------------------------------------------------------------------- - Advanced Search — Sort Controls - --------------------------------------------------------------------------- */ -.search-sort { - display: flex; - align-items: center; - gap: 6px; - margin-left: auto; -} -.search-sort__btn { - padding: 3px 10px; - font-size: 0.75rem; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-secondary); - color: var(--text-secondary); - cursor: pointer; - transition: all 120ms; -} -.search-sort__btn.active { - border-color: var(--accent); - color: var(--accent); - background: var(--bg-hover); -} - -/* --------------------------------------------------------------------------- - Advanced Search — Responsive - --------------------------------------------------------------------------- */ -@media (max-width: 768px) { - .search-dropdown { - max-height: 280px; - } - .search-facets { - flex-direction: column; - gap: 8px; - } - .search-chip { - max-width: 150px; - } -} - -/* --------------------------------------------------------------------------- - Sync Badge — real-time connection status indicator - --------------------------------------------------------------------------- */ -.sync-badge { - display: inline-block; - width: 10px; - height: 10px; - border-radius: 50%; - margin-left: 8px; - cursor: pointer; - transition: - background 300ms, - box-shadow 300ms; - flex-shrink: 0; - vertical-align: middle; -} -.sync-badge--disconnected { - background: #ef4444; - box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.25); -} -.sync-badge--connecting { - background: #f59e0b; - box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.25); - animation: sync-pulse 1.5s ease-in-out infinite; -} -.sync-badge--connected { - background: #22c55e; - box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.2); -} -.sync-badge--syncing { - background: #3b82f6; - box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.3); - animation: sync-pulse 0.8s ease-in-out infinite; -} -@keyframes sync-pulse { - 0%, - 100% { - opacity: 1; - } - 50% { - opacity: 0.4; - } -} - -/* AI processing — white flash on the sync badge */ -.sync-badge--ai-processing { - background: #ffffff !important; - box-shadow: 0 0 6px 3px rgba(255, 255, 255, 0.6) !important; - animation: ai-flash 0.6s ease-in-out infinite; -} - -@keyframes ai-flash { - 0%, 100% { opacity: 1; box-shadow: 0 0 6px 3px rgba(255,255,255,0.6); } - 50% { opacity: 0.3; box-shadow: 0 0 12px 6px rgba(255,255,255,0.9); } -} - -/* ── AI Status section inside sync panel ── */ - -.sync-panel__ai-section { - border-top: 1px solid var(--border); - padding: 10px 14px; -} - -.sync-panel__ai-title { - font-size: 0.78rem; - font-weight: 600; - color: var(--text-primary); - margin-bottom: 8px; -} - -.sync-panel__ai-row { - display: flex; - align-items: center; - justify-content: space-between; - margin-top: 5px; -} - -.sync-panel__ai-label { - font-size: 0.72rem; - color: var(--text-muted); -} - -.sync-panel__ai-state { - font-size: 0.75rem; - display: flex; - align-items: center; - gap: 5px; - padding: 2px 8px; - border-radius: 4px; -} - -.sync-panel__ai-state i { - flex-shrink: 0; -} - -.sync-panel__ai--active { - color: #22c55e; - background: rgba(34, 197, 94, 0.1); -} - -.sync-panel__ai--inactive { - color: #f59e0b; - background: rgba(245, 158, 11, 0.1); -} - -.sync-panel__ai--processing { - color: #ffffff; - background: rgba(59, 130, 246, 0.2); - animation: ai-status-pulse 1s ease-in-out infinite; -} - -.sync-panel__ai--unknown { - color: var(--text-muted); - background: var(--bg-tertiary); -} - -@keyframes ai-status-pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.6; } -} - -/* --------------------------------------------------------------------------- - Vault Home Page - --------------------------------------------------------------------------- */ - -.vault-home { - padding: 16px 24px; - max-width: 900px; - margin: 0 auto; -} - -.vault-home-breadcrumb { - display: flex; - align-items: center; - flex-wrap: wrap; - gap: 2px; - font-size: 0.85rem; - margin-bottom: 16px; - padding: 8px 12px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 8px; -} - -.vault-home-breadcrumb-item { - display: inline-flex; - align-items: center; - gap: 4px; - padding: 2px 6px; - border-radius: 4px; - color: var(--text-secondary); - transition: background 0.15s, color 0.15s; - user-select: none; -} - -.vault-home-breadcrumb-item:hover { - background: color-mix(in srgb, var(--accent) 10%, transparent); - color: var(--text-primary); -} - -.vault-home-breadcrumb-root { - font-weight: 600; - color: var(--accent); -} - -.vault-home-breadcrumb-sep { - color: var(--text-muted); - user-select: none; - font-size: 0.8rem; -} - -.vault-home-header { - display: flex; - align-items: center; - gap: 12px; - margin-bottom: 12px; - padding-bottom: 8px; - border-bottom: 1px solid var(--border); -} - -.vault-home-count { - font-size: 0.8rem; - font-weight: 600; - color: var(--text-primary); - background: var(--bg-secondary); - padding: 3px 10px; - border-radius: 4px; -} - -.vault-home-recursive-badge { - font-size: 0.7rem; - font-weight: 600; - color: var(--accent); - background: color-mix(in srgb, var(--accent) 12%, transparent); - padding: 2px 8px; - border-radius: 4px; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.vault-home-dir-info { - font-size: 0.75rem; - color: var(--text-muted); - font-family: var(--font-mono); -} - -.vault-home-results { - min-height: 200px; -} - -.vault-home-empty { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 3rem; - color: var(--text-muted); - gap: 8px; -} - -.vault-home-empty p { - font-size: 0.85rem; - margin: 0; -} - -.vault-home-error { - padding: 2rem; - text-align: center; - color: var(--danger, #ef4444); - font-size: 0.85rem; -} - -/* ── Recent files section on vault home ── */ -.vault-home-recent { - margin-bottom: 20px; - padding: 12px 16px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 8px; -} - -.vault-home-recent-header { - display: flex; - align-items: center; - gap: 6px; - font-size: 0.75rem; - font-weight: 600; - color: var(--text-muted); - text-transform: uppercase; - letter-spacing: 0.05em; - margin-bottom: 8px; - padding-bottom: 6px; - border-bottom: 1px solid var(--border); -} - -.vault-home-recent-list { - display: flex; - flex-direction: column; - gap: 2px; -} - -.vault-home-recent-item { - display: flex; - align-items: center; - gap: 8px; - padding: 5px 6px; - border-radius: 4px; - cursor: pointer; - transition: background 0.12s; - font-size: 0.82rem; -} - -.vault-home-recent-item:hover { - background: color-mix(in srgb, var(--accent) 8%, transparent); -} - -.vault-home-recent-title { - color: var(--text-primary); - font-weight: 500; - flex: 1; - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.vault-home-recent-dir { - color: var(--text-muted); - font-size: 0.72rem; - font-family: var(--font-mono); - max-width: 180px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.vault-home-recent-time { - color: var(--text-muted); - font-size: 0.7rem; - white-space: nowrap; - flex-shrink: 0; -} - -.vault-home-item { - cursor: pointer; -} - -.vault-home-item:hover { - background: var(--bg-secondary); -} - -/* --------------------------------------------------------------------------- - Sync Panel — event log overlay - --------------------------------------------------------------------------- */ -.sync-panel { - position: fixed; - top: 52px; - left: 16px; - width: 340px; - max-height: 400px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 10px; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); - z-index: 9999; - overflow: hidden; - font-size: 0.82rem; -} -.sync-panel__header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 12px 14px; - border-bottom: 1px solid var(--border); -} -.sync-panel__title { - font-weight: 600; - color: var(--text-primary); -} -.sync-panel__state { - font-size: 0.72rem; - padding: 2px 8px; - border-radius: 8px; - font-weight: 500; -} -.sync-panel__state--connected { - background: rgba(34, 197, 94, 0.15); - color: #22c55e; -} -.sync-panel__state--disconnected { - background: rgba(239, 68, 68, 0.15); - color: #ef4444; -} -.sync-panel__state--connecting { - background: rgba(245, 158, 11, 0.15); - color: #f59e0b; -} -.sync-panel__state--syncing { - background: rgba(59, 130, 246, 0.15); - color: #3b82f6; -} -.sync-panel__empty { - padding: 20px 14px; - text-align: center; - color: var(--text-muted); -} -.sync-panel__events { - max-height: 320px; - overflow-y: auto; - padding: 4px 0; -} -.sync-panel__event { - display: flex; - align-items: center; - gap: 8px; - padding: 7px 14px; - border-bottom: 1px solid var(--border); -} -.sync-panel__event:last-child { - border-bottom: none; -} -.sync-panel__event-type { - font-weight: 500; - color: var(--text-primary); - white-space: nowrap; -} -.sync-panel__event-detail { - color: var(--text-secondary); - flex: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.sync-panel__event-time { - font-size: 0.7rem; - color: var(--text-muted); - white-space: nowrap; -} - -/* --------------------------------------------------------------------------- - Toast — info variant (blue) - --------------------------------------------------------------------------- */ -.toast.toast-info { - background: #1e3a5f; - border-left: 4px solid #3b82f6; - color: #bfdbfe; -} -[data-theme="light"] .toast.toast-info { - background: #eff6ff; - border-left: 4px solid #3b82f6; - color: #1e40af; -} - -/* --------------------------------------------------------------------------- - Config Toggle Switch - --------------------------------------------------------------------------- */ -.config-toggle { - position: relative; - display: inline-block; - width: 40px; - height: 22px; - flex-shrink: 0; -} -.config-toggle input { - opacity: 0; - width: 0; - height: 0; -} -.config-toggle-slider { - position: absolute; - cursor: pointer; - inset: 0; - background: var(--bg-hover); - border: 1px solid var(--border); - border-radius: 22px; - transition: - background 200ms, - border-color 200ms; -} -.config-toggle-slider::before { - content: ""; - position: absolute; - height: 16px; - width: 16px; - left: 2px; - bottom: 2px; - background: var(--text-muted); - border-radius: 50%; - transition: - transform 200ms, - background 200ms; -} -.config-toggle input:checked + .config-toggle-slider { - background: rgba(34, 197, 94, 0.2); - border-color: #22c55e; -} -.config-toggle input:checked + .config-toggle-slider::before { - transform: translateX(18px); - background: #22c55e; -} - -/* --------------------------------------------------------------------------- - Hidden Files Configuration - --------------------------------------------------------------------------- */ -.hidden-files-vault-card { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 6px; - padding: 12px; - margin-bottom: 12px; - transition: border-color 200ms ease; -} - -.hidden-files-vault-card:hover { - border-color: var(--accent); -} - -.hidden-files-vault-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 12px; - padding-bottom: 8px; - border-bottom: 1px solid var(--border); -} - -.hidden-files-vault-header h3 { - font-size: 0.95rem; - font-weight: 600; - color: var(--text-primary); - margin: 0; -} - -.hidden-files-vault-type { - font-size: 0.7rem; - padding: 2px 6px; - background: var(--tag-bg); - color: var(--tag-text); - border-radius: 3px; - font-family: var(--mono); - text-transform: uppercase; - letter-spacing: 0.5px; -} - -.hidden-files-whitelist { - margin-top: 12px; - padding-top: 12px; - border-top: 1px solid var(--border); -} - -.hidden-files-whitelist-items { - display: flex; - flex-wrap: wrap; - gap: 6px; - margin-bottom: 10px; - min-height: 28px; - padding: 4px; - background: var(--bg-primary); - border-radius: 4px; - border: 1px dashed var(--border); -} - -.hidden-files-whitelist-items:empty::before { - content: "Aucun dossier dans la liste blanche"; - color: var(--text-muted); - font-size: 0.85rem; - font-style: italic; -} - -.hidden-files-whitelist-item { - display: inline-flex; - align-items: center; - gap: 4px; - padding: 3px 6px 3px 8px; - background: var(--tag-bg); - color: var(--tag-text); - border-radius: 4px; - font-size: 0.85rem; - font-family: var(--mono); - border: 1px solid color-mix(in srgb, var(--tag-text) 30%, transparent); - transition: all 150ms ease; -} - -.hidden-files-whitelist-item:hover { - background: color-mix(in srgb, var(--tag-bg) 80%, var(--accent) 20%); - border-color: var(--accent); -} - -.whitelist-item-text { - user-select: none; -} - -.whitelist-item-remove { - background: none; - border: none; - color: var(--text-muted); - cursor: pointer; - font-size: 1.1rem; - line-height: 1; - padding: 0 2px; - transition: all 150ms ease; - border-radius: 2px; -} - -.whitelist-item-remove:hover { - color: var(--danger); - background: color-mix(in srgb, var(--danger) 15%, transparent); -} - -.hidden-files-add-row { - display: flex; - gap: 8px; - align-items: center; - margin-top: 4px; -} - -.hidden-files-add-row .config-input { - flex: 1; - max-width: 250px; - font-family: var(--mono); - font-size: 0.9rem; -} - -.config-btn-add { - padding: 6px 12px; - background: var(--accent); - color: white; - border: none; - border-radius: 4px; - cursor: pointer; - font-size: 0.875rem; - font-weight: 500; - transition: all 150ms ease; - white-space: nowrap; -} - -.config-btn-add:hover { - background: color-mix(in srgb, var(--accent) 85%, black); - transform: translateY(-1px); -} - -.config-btn-add:active { - transform: translateY(0); -} - -/* --------------------------------------------------------------------------- - Utility — hidden class - --------------------------------------------------------------------------- */ -.hidden { - display: none !important; -} - -/* --------------------------------------------------------------------------- - Login Screen - --------------------------------------------------------------------------- */ -.login-screen { - position: fixed; - inset: 0; - z-index: 10001; - display: flex; - align-items: center; - justify-content: center; - background: linear-gradient(135deg, #090e17 0%, #101827 50%, #1b2838 100%); -} -.login-card { - width: 380px; - max-width: 90vw; - background: rgba(30, 30, 46, 0.85); - backdrop-filter: blur(20px); - border: 1px solid rgba(255, 255, 255, 0.08); - border-radius: 16px; - padding: 40px 36px; - box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5); - animation: loginFadeIn 0.4s ease-out; -} -@keyframes loginFadeIn { - from { - opacity: 0; - transform: translateY(20px) scale(0.97); - } - to { - opacity: 1; - transform: translateY(0) scale(1); - } -} -.login-header { - text-align: center; - margin-bottom: 32px; -} -.login-logo { - display: flex; - align-items: center; - justify-content: center; - gap: 10px; - margin-bottom: 8px; -} -.login-logo-icon { - font-size: 2rem; -} -.login-logo-text { - font-size: 1.8rem; - font-weight: 700; - background: linear-gradient(135deg, #7dd3fc, #38bdf8, #0ea5e9); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - letter-spacing: -0.02em; -} -.login-subtitle { - font-size: 0.88rem; - color: rgba(255, 255, 255, 0.45); - margin: 0; -} -.login-form .form-group { - margin-bottom: 20px; -} -.login-form .form-group label { - display: block; - font-size: 0.82rem; - font-weight: 500; - color: rgba(255, 255, 255, 0.6); - margin-bottom: 6px; -} -.login-form input[type="text"], -.login-form input[type="password"] { - width: 100%; - padding: 12px 14px; - border: 1px solid rgba(255, 255, 255, 0.1); - border-radius: 10px; - background: rgba(255, 255, 255, 0.06); - color: #e2e8f0; - font-size: 0.92rem; - font-family: inherit; - outline: none; - transition: - border-color 200ms, - box-shadow 200ms; - box-sizing: border-box; -} -.login-form input:focus { - border-color: #818cf8; - box-shadow: 0 0 0 3px rgba(129, 140, 248, 0.2); -} -.login-form input::placeholder { - color: rgba(255, 255, 255, 0.25); -} -.password-input-wrapper { - position: relative; -} -.password-toggle { - position: absolute; - right: 10px; - top: 50%; - transform: translateY(-50%); - background: none; - border: none; - cursor: pointer; - font-size: 1rem; - opacity: 0.5; - transition: opacity 150ms; - padding: 4px; -} -.password-toggle:hover { - opacity: 0.9; -} -.form-group--inline { - display: flex; - align-items: center; -} -.checkbox-label { - display: flex; - align-items: center; - gap: 8px; - cursor: pointer; - font-size: 0.82rem; - color: rgba(255, 255, 255, 0.5); -} -.checkbox-label input[type="checkbox"] { - accent-color: #818cf8; - width: 15px; - height: 15px; -} -.login-error { - padding: 10px 14px; - border-radius: 8px; - background: rgba(239, 68, 68, 0.12); - border: 1px solid rgba(239, 68, 68, 0.3); - color: #fca5a5; - font-size: 0.82rem; - margin-bottom: 16px; -} -.btn-login { - width: 100%; - padding: 13px 24px; - border: none; - border-radius: 10px; - background: linear-gradient(135deg, #3b82f6, #2563eb); - color: #fff; - font-size: 0.95rem; - font-weight: 600; - cursor: pointer; - transition: - opacity 200ms, - transform 100ms; - display: flex; - align-items: center; - justify-content: center; - gap: 8px; - font-family: inherit; -} -.btn-login:hover:not(:disabled) { - opacity: 0.92; -} -.btn-login:active:not(:disabled) { - transform: scale(0.98); -} -.btn-login:disabled { - opacity: 0.6; - cursor: not-allowed; -} -.btn-spinner { - font-size: 1rem; -} - -/* Light theme login */ -[data-theme="light"] .login-screen { - background: linear-gradient(135deg, #dbeafe, #eff6ff, #bfdbfe); -} -[data-theme="light"] .login-card { - background: rgba(255, 255, 255, 0.9); - border: 1px solid rgba(0, 0, 0, 0.08); - box-shadow: 0 20px 60px rgba(0, 0, 0, 0.12); -} -[data-theme="light"] .login-subtitle { - color: rgba(0, 0, 0, 0.45); -} -[data-theme="light"] .login-form .form-group label { - color: rgba(0, 0, 0, 0.6); -} -[data-theme="light"] .login-form input[type="text"], -[data-theme="light"] .login-form input[type="password"] { - background: rgba(0, 0, 0, 0.04); - border-color: rgba(0, 0, 0, 0.12); - color: #1e293b; -} -[data-theme="light"] .login-form input::placeholder { - color: rgba(0, 0, 0, 0.3); -} -[data-theme="light"] .checkbox-label { - color: rgba(0, 0, 0, 0.5); -} -[data-theme="light"] .login-error { - background: rgba(239, 68, 68, 0.08); - color: #dc2626; -} - -/* --------------------------------------------------------------------------- - User Menu (header) - --------------------------------------------------------------------------- */ -.user-menu { - display: flex; - align-items: center; - gap: 8px; -} -.user-display-name { - font-size: 0.8rem; - color: var(--text-secondary); - font-weight: 500; - max-width: 120px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.user-menu-link, -.btn-logout { - display: flex; - align-items: center; - justify-content: center; - background: none; - border: none; - color: var(--text-muted); - cursor: pointer; - padding: 4px; - border-radius: 4px; - transition: - color 150ms, - background 150ms; -} -.user-menu-link:hover, -.btn-logout:hover { - color: var(--text-primary); - background: var(--bg-hover); -} -.btn-logout:hover { - color: var(--danger); -} - -/* --------------------------------------------------------------------------- - Admin Panel - --------------------------------------------------------------------------- */ -.admin-toolbar { - padding: 16px; - display: flex; - justify-content: flex-end; -} -.admin-users-list { - padding: 0 16px 16px; -} -.admin-table { - width: 100%; - border-collapse: collapse; - font-size: 0.82rem; -} -.admin-table th, -.admin-table td { - padding: 10px 12px; - text-align: left; - border-bottom: 1px solid var(--border); -} -.admin-table th { - font-size: 0.72rem; - text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--text-muted); - font-weight: 600; - background: var(--bg-primary); - position: sticky; - top: 0; -} -.admin-table td { - color: var(--text-primary); -} -.admin-role-badge { - display: inline-block; - padding: 2px 10px; - border-radius: 10px; - font-size: 0.72rem; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.03em; -} -.admin-role-admin { - background: rgba(59, 130, 246, 0.15); - color: #3b82f6; -} -.admin-role-user { - background: rgba(34, 197, 94, 0.12); - color: #22c55e; -} -.admin-vaults-text { - font-size: 0.78rem; - color: var(--text-secondary); -} -.admin-actions { - white-space: nowrap; -} -.admin-action-btn { - background: none; - border: none; - cursor: pointer; - padding: 4px 6px; - border-radius: 4px; - font-size: 0.9rem; - transition: background 150ms; -} -.admin-action-btn:hover { - background: var(--bg-hover); -} -.admin-action-btn.danger:hover { - background: rgba(239, 68, 68, 0.12); -} - -/* Admin form overlay */ -.admin-form-overlay { - position: absolute; - inset: 0; - background: rgba(0, 0, 0, 0.6); - display: flex; - align-items: center; - justify-content: center; - z-index: 10; - backdrop-filter: blur(4px); -} -.admin-form-card { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 12px; - padding: 28px 24px; - width: 440px; - max-width: 90vw; - max-height: 80vh; - overflow-y: auto; - box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3); -} -.admin-form-card h3 { - margin: 0 0 20px; - font-size: 1.05rem; - color: var(--text-primary); -} -.admin-form-card .form-group { - margin-bottom: 16px; -} -.admin-form-card .form-group label { - display: block; - font-size: 0.82rem; - font-weight: 500; - color: var(--text-secondary); - margin-bottom: 6px; -} -.admin-form-card input[type="text"], -.admin-form-card input[type="password"], -.admin-form-card select { - width: 100%; - padding: 10px 12px; - border: 1px solid var(--border); - border-radius: 8px; - background: var(--bg-primary); - color: var(--text-primary); - font-size: 0.88rem; - font-family: inherit; - outline: none; - transition: border-color 200ms; - box-sizing: border-box; -} -.admin-form-card input:focus, -.admin-form-card select:focus { - border-color: var(--accent); -} -.admin-vault-list { - display: flex; - flex-direction: column; - gap: 6px; - max-height: 160px; - overflow-y: auto; - padding: 8px; - background: var(--bg-primary); - border: 1px solid var(--border); - border-radius: 8px; -} -.admin-vault-list .checkbox-label { - color: var(--text-primary); - font-size: 0.82rem; -} -.admin-form-actions { - display: flex; - justify-content: flex-end; - gap: 8px; - margin-top: 20px; -} - -/* --------------------------------------------------------------------------- - Popup Mode (Nouvelle fenêtre) - --------------------------------------------------------------------------- */ -body.popup-mode .top-nav, -body.popup-mode .sidebar, -body.popup-mode .resizer, -body.popup-mode .content-header { - display: none !important; -} -body.popup-mode .main-layout { - height: 100vh; -} -body.popup-mode .content-area { - margin: 15px auto; - padding: 30px; - border: 1px solid var(--border); - border-radius: 12px; - height: calc(100vh - 30px); - max-width: 1000px; - overflow-y: auto; - box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15); - box-sizing: border-box; -} - -/* --------------------------------------------------------------------------- - Recent Tab Styles - --------------------------------------------------------------------------- */ - -/* Liste récente */ -.recent-list { - display: flex; - flex-direction: column; - gap: 2px; - padding: 4px 0; -} - -/* Item */ -.recent-item { - padding: 10px 12px; - border-radius: 6px; - cursor: pointer; - border-left: 3px solid transparent; - transition: - background 0.15s, - border-color 0.15s; -} -.recent-item:hover { - background: var(--bg-secondary); - border-left-color: var(--accent); -} -.recent-item.active { - border-left-color: var(--accent); - background: var(--bg-secondary); -} - -/* Header: temps + badge vault */ -.recent-item-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 3px; -} -.recent-time { - font-size: 11px; - color: var(--text-muted); - display: flex; - align-items: center; - gap: 4px; -} -.recent-vault-badge { - font-size: 10px; - font-weight: 600; - padding: 1px 6px; - border-radius: 10px; - background: var(--accent); - color: #fff; - opacity: 0.85; -} - -/* Titre */ -.recent-item-title { - font-size: 13px; - font-weight: 600; - color: var(--text-primary); - margin-bottom: 2px; -} - -/* Breadcrumb path */ -.recent-item-path { - font-size: 11px; - color: var(--text-muted); - margin-bottom: 4px; - font-family: monospace; -} - -/* Preview */ -.recent-item-preview { - font-size: 12px; - color: var(--text-muted); - display: -webkit-box; - -webkit-line-clamp: 2; - line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - line-height: 1.4; - margin-bottom: 5px; -} - -/* Tags */ -.recent-item-tags { - display: flex; - flex-wrap: wrap; - gap: 4px; -} -.recent-item-tags .tag-pill { - font-size: 10px; - padding: 1px 6px; - border-radius: 10px; - background: var(--bg-secondary); - color: var(--accent); - border: 1px solid var(--border); -} - -/* Filtre vault */ -.recent-filter-bar { - padding: 8px 12px 4px; -} -.recent-filter-bar select { - width: 100%; - padding: 4px 8px; - font-size: 12px; - background: var(--bg-secondary); - color: var(--text-primary); - border: 1px solid var(--border); - border-radius: 4px; - cursor: pointer; -} - -/* État vide */ -.recent-empty { - display: flex; - flex-direction: column; - align-items: center; - padding: 32px 16px; - color: var(--text-muted); - gap: 8px; - font-size: 13px; -} - -/* --------------------------------------------------------------------------- - Find in Page - --------------------------------------------------------------------------- */ - -/* Animation d'entrée */ -@keyframes slideUp { - from { - opacity: 0; - transform: translateY(20px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -/* Barre principale */ -.find-in-page-bar { - position: fixed; - bottom: 20px; - right: 20px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 12px; - padding: 12px 16px; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); - z-index: 1000; - animation: slideUp 200ms ease; - max-width: calc(100vw - 40px); -} - -.find-in-page-bar[hidden] { - display: none; -} - -/* Contenu de la barre */ -.find-in-page-content { - display: flex; - align-items: center; - gap: 10px; - flex-wrap: wrap; -} - -/* Icône de recherche */ -.find-icon { - color: var(--text-secondary); - flex-shrink: 0; -} - -/* Input de recherche */ -#find-input { - flex: 1; - min-width: 200px; - padding: 6px 10px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-primary); - color: var(--text-primary); - font-family: "JetBrains Mono", monospace; - font-size: 0.85rem; - outline: none; - transition: border-color 200ms ease; -} - -#find-input:focus { - border-color: var(--accent); -} - -/* Compteur d'occurrences */ -.find-counter { - font-family: "JetBrains Mono", monospace; - font-size: 0.75rem; - color: var(--text-secondary); - white-space: nowrap; - min-width: 90px; - text-align: center; -} - -/* Boutons de navigation */ -.find-nav-buttons { - display: flex; - gap: 4px; -} - -/* Boutons génériques */ -.find-btn { - display: flex; - align-items: center; - justify-content: center; - width: 28px; - height: 28px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-primary); - color: var(--text-secondary); - cursor: pointer; - transition: all 150ms ease; - padding: 0; - flex-shrink: 0; -} - -.find-btn:hover:not(:disabled) { - border-color: var(--accent); - color: var(--accent); - background: color-mix(in srgb, var(--accent) 10%, var(--bg-primary)); -} - -.find-btn:disabled { - opacity: 0.4; - cursor: not-allowed; -} - -/* Options */ -.find-options { - display: flex; - gap: 4px; - border-left: 1px solid var(--border); - padding-left: 10px; -} - -.find-option-btn { - font-family: "JetBrains Mono", monospace; - font-size: 0.7rem; - font-weight: 600; -} - -.find-option-btn[aria-pressed="true"] { - border-color: var(--accent); - background: color-mix(in srgb, var(--accent) 20%, var(--bg-primary)); - color: var(--accent); -} - -.find-option-text { - pointer-events: none; -} - -/* Bouton fermer */ -.find-close { - border-left: 1px solid var(--border); - margin-left: 6px; -} - -.find-close:hover { - background: var(--danger-bg); - border-color: var(--danger); - color: var(--danger); -} - -/* Message d'erreur */ -.find-error { - margin-top: 8px; - padding: 6px 10px; - background: var(--danger-bg); - border: 1px solid var(--danger); - border-radius: 6px; - color: var(--danger); - font-size: 0.75rem; - font-family: "JetBrains Mono", monospace; -} - -.find-error[hidden] { - display: none; -} - -/* Highlights dans le contenu */ -.find-highlight { - background: rgba(255, 235, 59, 0.4); - padding: 0 2px; - border-radius: 2px; - transition: background 150ms ease; -} - -[data-theme="dark"] .find-highlight { - background: rgba(255, 193, 7, 0.35); -} - -.find-highlight-active { - background: rgba(255, 193, 7, 0.7); - box-shadow: 0 0 0 2px rgba(255, 193, 7, 0.3); -} - -[data-theme="dark"] .find-highlight-active { - background: rgba(255, 193, 7, 0.6); - box-shadow: 0 0 0 2px rgba(255, 193, 7, 0.4); -} - -/* Responsive mobile */ -@media (max-width: 768px) { - .find-in-page-bar { - bottom: 10px; - left: 10px; - right: 10px; - max-width: none; - padding: 10px 12px; - } - - .find-in-page-content { - gap: 6px; - } - - #find-input { - min-width: 120px; - font-size: 0.8rem; - } - - .find-counter { - font-size: 0.7rem; - min-width: 80px; - } - - .find-btn { - width: 32px; - height: 32px; - } - - .find-options { - padding-left: 6px; - } -} - -/* ===== PWA STYLES ===== */ - -/* PWA Update Notification */ -.pwa-update-notification { - position: fixed; - bottom: 20px; - right: 20px; - z-index: 10000; - animation: slideInUp 0.3s ease-out; -} - -.pwa-update-content { - background: var(--accent); - color: white; - padding: 16px 20px; - border-radius: var(--radius); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); - display: flex; - align-items: center; - gap: 12px; - max-width: 400px; -} - -.pwa-update-content span { - flex: 1; - font-size: 0.9rem; - font-weight: 500; -} - -.pwa-update-btn { - background: white; - color: var(--accent); - border: none; - padding: 8px 16px; - border-radius: var(--radius); - font-size: 0.85rem; - font-weight: 600; - cursor: pointer; - transition: all 0.2s ease; - white-space: nowrap; -} - -.pwa-update-btn:hover { - transform: translateY(-1px); - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); -} - -.pwa-update-dismiss { - background: transparent; - border: none; - color: white; - font-size: 1.5rem; - line-height: 1; - cursor: pointer; - padding: 0; - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; - opacity: 0.8; - transition: opacity 0.2s ease; -} - -.pwa-update-dismiss:hover { - opacity: 1; -} - -/* PWA Install Button (optional - can be added to header) */ -#pwa-install-btn { - display: none; - background: var(--accent); - color: white; - border: none; - padding: 8px 16px; - border-radius: var(--radius); - font-size: 0.85rem; - font-weight: 600; - cursor: pointer; - transition: all 0.2s ease; -} - -#pwa-install-btn:hover { - background: var(--accent-green); - transform: translateY(-1px); -} - -/* Animations */ -@keyframes slideInUp { - from { - transform: translateY(100%); - opacity: 0; - } - to { - transform: translateY(0); - opacity: 1; - } -} - -/* Mobile responsive */ -@media (max-width: 768px) { - .pwa-update-notification { - bottom: 10px; - right: 10px; - left: 10px; - } - - .pwa-update-content { - padding: 12px 16px; - font-size: 0.85rem; - } - - .pwa-update-btn { - padding: 6px 12px; - font-size: 0.8rem; - } -} - -/* --------------------------------------------------------------------------- - Dashboard Home - Recent Files Widget - --------------------------------------------------------------------------- */ - -.dashboard-home { - padding: 0; - width: 100%; - display: flex; - flex-direction: column; - gap: 32px; -} - -.dashboard-section { - display: flex; - flex-direction: column; -} - -.dashboard-header { - margin-bottom: 20px; -} - -.dashboard-title-row { - display: flex; - align-items: center; - gap: 12px; - margin-bottom: 16px; -} - -.dashboard-icon { - width: 28px; - height: 28px; - color: var(--accent); -} - -.dashboard-title-row h2 { - font-family: "JetBrains Mono", monospace; - font-size: 1.4rem; - font-weight: 600; - color: var(--text-primary); - margin: 0; -} - -.dashboard-filter-row { - display: flex; - align-items: center; - gap: 12px; -} - -.dashboard-select { - padding: 6px 12px; - font-size: 13px; - background: var(--bg-secondary); - color: var(--text-primary); - border: 1px solid var(--border); - border-radius: 6px; - cursor: pointer; - min-width: 160px; -} - -.dashboard-select:focus { - outline: none; - border-color: var(--accent); -} - -.dashboard-count { - font-size: 12px; - color: var(--text-muted); - padding: 4px 10px; - background: var(--bg-secondary); - border-radius: 12px; -} - -/* Grid */ -.dashboard-recent-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); - gap: 16px; - flex: 1; - width: 100%; -} - -@media (max-width: 1200px) { - .dashboard-recent-grid { - grid-template-columns: repeat(2, 1fr); - } -} - -@media (max-width: 768px) { - .dashboard-home { - padding: 16px; - } - - .dashboard-recent-grid { - grid-template-columns: 1fr; - } - - .dashboard-title-row h2 { - font-size: 1.2rem; - } -} - -/* Card */ -.dashboard-card { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 12px; - padding: 12px; - cursor: pointer; - transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); - position: relative; - display: flex; - flex-direction: column; - gap: 4px; - animation: fadeSlideIn 0.3s ease forwards; - opacity: 0; -} - -.dashboard-card:hover { - transform: translateY(-2px); - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); - border-color: var(--accent); -} - -.dashboard-card:active { - transform: translateY(0); -} - -@keyframes fadeSlideIn { - from { - opacity: 0; - transform: translateY(10px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -/* Staggered animation for cards */ -.dashboard-card:nth-child(1) { - animation-delay: 0ms; -} -.dashboard-card:nth-child(2) { - animation-delay: 50ms; -} -.dashboard-card:nth-child(3) { - animation-delay: 100ms; -} -.dashboard-card:nth-child(4) { - animation-delay: 150ms; -} -.dashboard-card:nth-child(5) { - animation-delay: 200ms; -} -.dashboard-card:nth-child(6) { - animation-delay: 250ms; -} -.dashboard-card:nth-child(7) { - animation-delay: 300ms; -} -.dashboard-card:nth-child(8) { - animation-delay: 350ms; -} -.dashboard-card:nth-child(9) { - animation-delay: 400ms; -} - -/* Card header */ -.dashboard-card-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 8px; -} - -.dashboard-card-icon { - width: 40px; - height: 40px; - padding: 4px; - background: transparent; - border: 2px solid var(--accent); - border-radius: 8px; - color: var(--accent); - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; -} - -.dashboard-card-icon svg { - width: 24px; - height: 24px; -} - -.dashboard-vault-badge { - font-size: 10px; - font-weight: 600; - padding: 3px 8px; - border-radius: 10px; - background: var(--bg-primary); - color: var(--text-secondary); - border: 1px solid var(--border); - margin-right: auto; -} - -.dashboard-card-bookmark-btn { - background: transparent; - border: none; - color: var(--text-muted); - cursor: pointer; - padding: 4px; - border-radius: 4px; - display: flex; - align-items: center; - justify-content: center; - transition: all 0.2s ease; -} - -.dashboard-card-bookmark-btn:hover { - background: var(--bg-primary); - color: var(--accent); -} - -.dashboard-card-bookmark-btn.active { - color: var(--accent-green); -} - -/* Card title */ -.dashboard-card-title { - font-size: 14px; - font-weight: 600; - color: var(--text-primary); - margin: 0; - line-height: 1.4; - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 2; - line-clamp: 2; - -webkit-box-orient: vertical; -} - -/* Card path */ -.dashboard-card-path { - font-size: 11px; - color: var(--text-muted); - font-family: "JetBrains Mono", monospace; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -/* Card preview */ -.dashboard-card-preview { - display: none; -} - -/* Card footer */ -.dashboard-card-footer { - display: flex; - align-items: center; - justify-content: space-between; - gap: 8px; - margin-top: 4px; - padding-top: 6px; - border-top: 1px solid color-mix(in srgb, var(--border) 50%, transparent); -} - -.dashboard-card-time { - font-size: 11px; - color: var(--text-muted); - display: flex; - align-items: center; - gap: 4px; -} - -.dashboard-card-time svg { - width: 12px; - height: 12px; -} - -/* Card tags */ -.dashboard-card-tags { - display: flex; - flex-wrap: wrap; - gap: 4px; -} - -.dashboard-card-tags .tag-pill { - font-size: 10px; - padding: 2px 6px; - border-radius: 8px; - background: var(--bg-tertiary); - color: var(--accent); - border: 1px solid var(--border); -} - -/* Empty state */ -.dashboard-recent-empty { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 48px 24px; - color: var(--text-muted); - gap: 12px; - text-align: center; - flex: 1; -} - -.dashboard-recent-empty svg { - width: 48px; - height: 48px; - opacity: 0.4; -} - -.dashboard-recent-empty span { - font-size: 16px; - font-weight: 500; -} - -.dashboard-recent-empty p { - font-size: 13px; - margin: 0; - opacity: 0.7; -} - -/* Loading skeletons */ -.dashboard-loading { - display: none; - grid-template-columns: repeat(3, 1fr); - gap: 16px; -} - -.dashboard-loading.active { - display: grid; -} - -@media (max-width: 1200px) { - .dashboard-loading { - grid-template-columns: repeat(2, 1fr); - } -} - -@media (max-width: 768px) { - .dashboard-loading { - grid-template-columns: 1fr; - } -} - -.skeleton-card { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 12px; - padding: 16px; - height: 160px; - position: relative; - overflow: hidden; -} - -.skeleton-card::after { - content: ""; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.05), transparent); - animation: shimmer 1.5s infinite; -} - -@keyframes shimmer { - 0% { - transform: translateX(-100%); - } - 100% { - transform: translateX(100%); - } -} - -/* ===== CONTEXT MENU ===== */ -.context-menu { - position: fixed; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 8px; - box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4); - min-width: 200px; - z-index: 10000; - padding: 4px; - display: none; -} - -.context-menu.active { - display: block; -} - -.context-menu-item { - display: flex; - align-items: center; - gap: 10px; - padding: 8px 12px; - border-radius: 6px; - cursor: pointer; - font-family: "JetBrains Mono", monospace; - font-size: 0.82rem; - color: var(--text-primary); - transition: all 150ms ease; -} - -.context-menu-item:hover:not(.disabled) { - background: var(--bg-hover); - color: var(--accent); -} - -.context-menu-item.disabled { - opacity: 0.4; - cursor: not-allowed; -} - -.context-menu-item .icon { - width: 16px; - height: 16px; - flex-shrink: 0; -} - -.context-menu-separator { - height: 1px; - background: var(--border); - margin: 4px 0; -} - -/* ===== INLINE RENAME ===== */ -.sidebar-item-input { - width: 100%; - padding: 4px 8px; - background: var(--bg-primary); - border: 1px solid var(--accent); - border-radius: 4px; - color: var(--text-primary); - font-family: "JetBrains Mono", monospace; - font-size: 0.82rem; - outline: none; -} - -/* ===== VAULT READONLY BADGE ===== */ -.vault-readonly-badge { - display: inline-flex; - align-items: center; - gap: 4px; - padding: 2px 6px; - background: var(--danger-bg); - color: var(--danger); - border-radius: 4px; - font-size: 0.7rem; - font-weight: 600; - margin-left: 6px; -} - -/* ===== OBSIGATE MODALS ===== */ -.obsigate-modal-overlay { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: var(--overlay-bg); - z-index: 9999; - display: flex; - align-items: center; - justify-content: center; - opacity: 0; - pointer-events: none; - transition: opacity 200ms ease; -} - -.obsigate-modal-overlay.active { - opacity: 1; - pointer-events: all; -} - -.obsigate-modal { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 12px; - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5); - min-width: 400px; - max-width: 600px; - transform: scale(0.9); - transition: transform 200ms ease; -} - -.obsigate-modal-overlay.active .obsigate-modal { - transform: scale(1); -} - -.obsigate-modal-header { - padding: 16px 20px; - border-bottom: 1px solid var(--border); - display: flex; - align-items: center; - justify-content: space-between; -} - -.obsigate-modal-title { - font-family: "JetBrains Mono", monospace; - font-size: 1.1rem; - font-weight: 700; - color: var(--text-primary); -} - -.obsigate-modal-body { - padding: 20px; -} - -.obsigate-modal-footer { - padding: 16px 20px; - border-top: 1px solid var(--border); - display: flex; - gap: 10px; - justify-content: flex-end; -} - -.modal-input { - width: 100%; - padding: 10px 12px; - background: var(--bg-primary); - border: 1px solid var(--border); - border-radius: 6px; - color: var(--text-primary); - font-family: "JetBrains Mono", monospace; - font-size: 0.9rem; - outline: none; - transition: border-color 200ms ease; -} - -.modal-input:focus { - border-color: var(--accent); -} - -.modal-input.error { - border-color: var(--danger); -} - -.modal-label { - display: block; - font-family: "JetBrains Mono", monospace; - font-size: 0.85rem; - font-weight: 600; - color: var(--text-secondary); - margin-bottom: 8px; -} - -.modal-hint { - font-size: 0.75rem; - color: var(--text-muted); - margin-top: 6px; -} - -.modal-error { - font-size: 0.8rem; - color: var(--danger); - margin-top: 6px; -} - -.modal-select { - width: 100%; - padding: 10px 12px; - background: var(--bg-primary); - border: 1px solid var(--border); - border-radius: 6px; - color: var(--text-primary); - font-family: "JetBrains Mono", monospace; - font-size: 0.9rem; - outline: none; - cursor: pointer; - transition: border-color 200ms ease; -} - -.modal-select:focus { - border-color: var(--accent); -} - -.modal-btn { - padding: 8px 16px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-primary); - color: var(--text-primary); - font-family: "JetBrains Mono", monospace; - font-size: 0.85rem; - cursor: pointer; - transition: all 150ms ease; -} - -.modal-btn:hover { - border-color: var(--accent); - color: var(--accent); -} - -.modal-btn.primary { - background: var(--accent); - color: white; - border-color: var(--accent); -} - -.modal-btn.primary:hover { - opacity: 0.9; -} - -.modal-btn.danger { - background: var(--danger); - color: white; - border-color: var(--danger); -} - -.modal-btn.danger:hover { - opacity: 0.9; -} - -.modal-btn:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.modal-form-group { - margin-bottom: 16px; -} - -.modal-form-group:last-child { - margin-bottom: 0; -} - -.modal-warning { - padding: 12px; - background: var(--danger-bg); - border: 1px solid var(--danger); - border-radius: 6px; - color: var(--danger); - font-size: 0.85rem; - margin-bottom: 16px; - display: flex; - align-items: flex-start; - gap: 10px; -} - -.modal-warning .icon { - flex-shrink: 0; - margin-top: 2px; -} - -/* ===== TAB BAR ===== */ -.tab-bar { - display: flex; - align-items: stretch; - background: var(--bg-secondary); - border-bottom: 1px solid var(--border); - overflow: hidden; - flex-shrink: 0; - min-height: 36px; -} - -.tab-bar[hidden] { - display: none; -} - -.tab-list { - display: flex; - align-items: stretch; - overflow-x: auto; - overflow-y: hidden; - flex: 1; - scrollbar-width: thin; -} - -.tab-list::-webkit-scrollbar { - height: 3px; -} - -.tab-item { - display: flex; - align-items: center; - gap: 6px; - padding: 6px 12px; - font-size: 0.8rem; - color: var(--text-muted); - cursor: pointer; - white-space: nowrap; - border-right: 1px solid var(--border); - background: transparent; - transition: background 0.15s, color 0.15s; - user-select: none; - position: relative; - min-width: 0; - flex-shrink: 0; -} - -.tab-item:hover { - background: var(--bg-hover); - color: var(--text-secondary); -} - -.tab-item.active { - background: var(--bg-primary); - color: var(--text-primary); - border-bottom: 2px solid var(--accent); - margin-bottom: -1px; -} - -.tab-item .tab-icon { - width: 14px; - height: 14px; - flex-shrink: 0; - opacity: 0.7; -} - -.tab-item .tab-name { - overflow: hidden; - text-overflow: ellipsis; - max-width: 150px; -} - -/* Preview tab (single-click) — italic title, slightly muted */ -.tab-item.preview .tab-name { - font-style: italic; - opacity: 0.75; -} -.tab-item.preview { - background: var(--bg-hover); -} - -.tab-item .tab-close { - width: 16px; - height: 16px; - display: flex; - align-items: center; - justify-content: center; - border-radius: 3px; - flex-shrink: 0; - opacity: 0; - transition: opacity 0.15s, background 0.15s; -} - -.tab-item:hover .tab-close, -.tab-item.active .tab-close { - opacity: 0.6; -} - -.tab-item .tab-close:hover { - opacity: 1; - background: var(--bg-hover); -} - -.tab-item.dragging { - opacity: 0.5; - background: var(--bg-hover); -} - -.tab-drop-indicator { - width: 2px; - background: var(--accent); - flex-shrink: 0; -} - -/* ── Backlinks panel ── */ -.backlinks-panel { - margin-top: 24px; - padding: 12px 16px; - background: var(--bg-card, var(--bg-secondary)); - border-radius: 8px; - border: 1px solid var(--border); -} -.backlinks-header { - font-size: 0.8rem; - font-weight: 600; - color: var(--text-muted); - display: flex; - align-items: center; - gap: 6px; - margin-bottom: 8px; - text-transform: uppercase; - letter-spacing: 0.5px; -} -.backlinks-list { - display: flex; - flex-direction: column; - gap: 4px; -} -.backlink-item { - display: flex; - align-items: center; - gap: 8px; - padding: 6px 8px; - border-radius: 4px; - cursor: pointer; - transition: background 0.15s; -} -.backlink-item:hover { - background: var(--bg-hover); -} -.backlink-vault { - font-size: 0.7rem; - color: var(--accent); - background: var(--accent-bg, rgba(99, 102, 241, 0.1)); - padding: 1px 6px; - border-radius: 3px; -} -.backlink-title { - font-size: 0.85rem; - color: var(--text-primary); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -/* ── Unsupported file notice ── */ -.unsupported-file { - padding: 40px; - text-align: center; - color: var(--text-muted); -} -.unsupported-file i { - display: block; - margin: 0 auto 12px; - opacity: 0.4; -} -.unsupported-file .filename { - font-weight: 600; - color: var(--text-primary); - margin-bottom: 8px; - word-break: break-all; -} -.unsupported-file .btn-action { - margin-top: 12px; - display: inline-flex; -} - -/* ── Dashboard Stats Grid ── */ -.dashboard-stats-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); - gap: 12px; -} -.stat-card { - display: flex; - flex-direction: column; - align-items: center; - padding: 16px 12px; - background: var(--bg-card, var(--bg-secondary)); - border-radius: 8px; - border: 1px solid var(--border); -} -.stat-icon { - width: 24px; - height: 24px; - opacity: 0.6; - margin-bottom: 8px; - color: var(--accent); -} -.stat-value { - font-size: 1.4rem; - font-weight: 700; - color: var(--text-primary); -} -.stat-label { - font-size: 0.75rem; - color: var(--text-muted); - margin-top: 2px; -} -.dashboard-stats-loading { - padding: 16px; - text-align: center; - color: var(--text-muted); -} - -/* ── Dashboard Conflicts ── */ -.dashboard-conflicts-grid { - display: flex; - flex-direction: column; - gap: 8px; -} -.conflict-card { - display: flex; - align-items: center; - justify-content: space-between; - padding: 10px 14px; - background: var(--bg-card, var(--bg-secondary)); - border-radius: 6px; - border: 1px solid var(--border); - gap: 12px; -} -.conflict-info { - display: flex; - flex-direction: column; - gap: 2px; - min-width: 0; -} -.conflict-vault { - font-size: 0.7rem; - color: var(--accent); - background: var(--accent-bg, rgba(99,102,241,0.1)); - padding: 1px 6px; - border-radius: 3px; - align-self: flex-start; -} -.conflict-name { - font-size: 0.85rem; - font-weight: 500; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.conflict-date { - font-size: 0.7rem; - color: var(--text-muted); -} -.conflict-actions { - display: flex; - gap: 8px; - flex-shrink: 0; -} -.conflict-btn { - padding: 4px 10px; - font-size: 0.75rem; - border: 1px solid var(--border); - border-radius: 4px; - cursor: pointer; - background: var(--bg-primary); - color: var(--text-primary); - white-space: nowrap; -} -.conflict-btn:hover { background: var(--bg-hover); } - -/* ── Quick Help (Dashboard) ── */ -.quick-help { - margin-top: 16px; - background: var(--bg-card, var(--bg-secondary)); - border: 1px solid var(--border); - border-radius: var(--radius-lg); - overflow: hidden; -} -.qh-header { - display: flex; - align-items: center; - gap: 8px; - padding: 10px 14px; - font-size: 0.8rem; - font-weight: 600; - color: var(--text-secondary); - border-bottom: 1px solid var(--border); - user-select: none; -} -.qh-header i { color: var(--accent); opacity: 0.7; } -.qh-toggle { - margin-left: auto; - background: none; - border: none; - color: var(--text-muted); - cursor: pointer; - font-size: 1rem; - line-height: 1; - padding: 2px 6px; - border-radius: 4px; -} -.qh-toggle:hover { color: var(--text-secondary); background: var(--bg-hover); } -.qh-body { - padding: 10px 14px 14px; - display: grid; - grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); - gap: 6px 20px; -} -.qh-body.collapsed { display: none; } -.qh-row { - display: flex; - align-items: center; - gap: 10px; - padding: 4px 0; -} -.qh-kbd { - display: inline-flex; - align-items: center; - padding: 2px 8px; - font-family: var(--mono); - font-size: 0.7rem; - font-weight: 500; - color: var(--accent-text, #79c0ff); - background: var(--accent-bg, #1f2a3a); - border: 1px solid var(--border-md, #30363d); - border-radius: 4px; - white-space: nowrap; - min-width: 0; - letter-spacing: 0.3px; -} -.qh-desc { - font-size: 0.78rem; - color: var(--text-secondary); -} -.qh-divider { - grid-column: 1 / -1; - height: 1px; - background: var(--border); - margin: 6px 0 8px; -} -.qh-tip { - grid-column: 1 / -1; - display: flex; - align-items: flex-start; - gap: 8px; - font-size: 0.75rem; - color: var(--text-muted); - line-height: 1.5; -} -.qh-tip i { color: var(--warn); flex-shrink: 0; margin-top: 1px; } -.qh-tip strong { color: var(--text-secondary); } - -/* ── Webhooks UI ── */ -.webhook-item { - display: flex; - align-items: center; - gap: 10px; - padding: 8px 10px; - background: var(--bg-card, var(--bg-secondary)); - border-radius: 6px; - margin-bottom: 6px; - font-size: 0.8rem; -} -.webhook-name { font-weight: 500; min-width: 80px; } -.webhook-url { color: var(--accent); overflow: hidden; text-overflow: ellipsis; flex: 1; } -.webhook-events { color: var(--text-muted); font-size: 0.7rem; } -.webhook-delete { background: none; border: none; color: var(--text-error); cursor: pointer; font-size: 1rem; padding: 2px 6px; } -.config-add-row { display: flex; gap: 8px; margin-top: 8px; } -.config-btn-add { padding: 6px 14px; background: var(--accent); color: #fff; border: none; border-radius: 6px; cursor: pointer; font-size: 0.8rem; } - -/* ── Shares UI ── */ -.share-item { - display: flex; - align-items: center; - gap: 10px; - padding: 8px 10px; - background: var(--bg-card, var(--bg-secondary)); - border-radius: 6px; - margin-bottom: 6px; - font-size: 0.8rem; -} -.share-path { font-weight: 500; min-width: 0; overflow: hidden; text-overflow: ellipsis; } -.share-url a { color: var(--accent); font-size: 0.75rem; } -.share-meta { color: var(--text-muted); font-size: 0.7rem; } -.share-revoke { background: none; border: 1px solid var(--text-error); color: var(--text-error); cursor: pointer; padding: 2px 8px; border-radius: 4px; font-size: 0.7rem; } - -/* ── Share Dialog ── */ -.share-dialog-overlay { - position: fixed; - top: 0; left: 0; right: 0; bottom: 0; - background: rgba(0,0,0,0.5); - display: flex; - align-items: center; - justify-content: center; - z-index: 10000; -} -.share-dialog { - background: var(--bg-primary); - border-radius: 12px; - padding: 24px; - max-width: 480px; - width: 90%; - box-shadow: 0 8px 32px rgba(0,0,0,0.2); -} -.share-dialog h3 { margin: 0 0 4px; } -.share-url-input { - width: 100%; - padding: 8px 12px; - border: 1px solid var(--border); - border-radius: 6px; - font-size: 0.8rem; - background: var(--bg-secondary); - color: var(--text-primary); - box-sizing: border-box; -} -.share-dialog-actions { - display: flex; - gap: 8px; - margin-top: 12px; - justify-content: flex-end; -} -.share-copy-btn { - padding: 6px 16px; - background: var(--accent); - color: #fff; - border: none; - border-radius: 6px; - cursor: pointer; - font-size: 0.85rem; -} -.share-close-btn { - padding: 6px 16px; - background: var(--bg-secondary); - color: var(--text-primary); - border: 1px solid var(--border); - border-radius: 6px; - cursor: pointer; - font-size: 0.85rem; -} -.share-create-btn { - padding: 6px 16px; - background: var(--accent); - color: #fff; - border: none; - border-radius: 6px; - cursor: pointer; - font-size: 0.85rem; -} -.share-revoke-btn { - padding: 6px 16px; - background: none; - color: var(--text-error); - border: 1px solid var(--text-error); - border-radius: 6px; - cursor: pointer; - font-size: 0.85rem; -} - -/* ── Enhanced Search Bar Toggles ── */ -.search-actions .tog { - font-family: var(--font-mono, monospace); - font-size: 10px; - font-weight: 600; - padding: 2px 5px; - border-radius: 3px; - min-width: auto; - line-height: 1.4; -} -.search-actions .tog.active { - color: var(--accent); - border-color: var(--accent); - background: rgba(99, 102, 241, 0.12); -} -.search-actions .icon-only { - padding: 2px 4px; - min-width: auto; -} -.search-sep { - width: 1px; - height: 16px; - background: var(--border); - margin: 0 2px; - align-self: center; -} -.search-count { - font-size: 10px; - color: var(--text-muted); - font-family: var(--font-mono, monospace); - white-space: nowrap; - min-width: 28px; - text-align: center; -} -.search-filter-row, .search-replace-row { - display: flex; - gap: 6px; - align-items: center; - padding: 4px 0 0 0; -} -.search-filter-input { - flex: 1; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 4px; - color: var(--text-primary); - font-family: var(--font-mono, monospace); - font-size: 11px; - padding: 4px 8px; - outline: none; -} -.search-filter-input:focus { border-color: var(--accent); } -.search-filter-input::placeholder { color: var(--text-muted); } - -/* ── Floating Results Bar ── */ -.results-bar { - position: fixed; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - display: flex; - align-items: center; - gap: 2px; - margin: 0 auto; - padding: 6px 10px; - background: var(--bg-secondary); - border: 1px solid var(--border-md, var(--border)); - border-radius: 10px; - box-shadow: 0 2px 16px rgba(0,0,0,0.35); - width: fit-content; - max-width: 95%; - z-index: 50; - backdrop-filter: blur(8px); -} -.results-bar-count { - font-size: 10px; - color: var(--text-muted); - font-family: var(--mono); - white-space: nowrap; - min-width: 28px; - text-align: center; - padding: 0 4px; -} -.results-bar-btn { - display: inline-flex; - align-items: center; - justify-content: center; - width: 24px; - height: 24px; - border: 1px solid transparent; - border-radius: 4px; - background: transparent; - color: var(--text-secondary); - cursor: pointer; - font-size: 12px; - transition: background 0.15s, color 0.15s, border-color 0.15s; -} -.results-bar-btn:hover { background: var(--bg-hover); color: var(--text-primary); } -.results-bar-btn.tog { - font-family: var(--mono); - font-size: 10px; - font-weight: 600; - width: auto; - padding: 2px 5px; -} -.results-bar-btn.tog.active { - color: var(--accent); - border-color: var(--accent); - background: rgba(99,102,241,0.12); -} -.results-bar-sep { - width: 1px; - height: 16px; - background: var(--border); - margin: 0 6px; - align-self: center; -} -.search-replace-btn { - padding: 4px 10px; - font-size: 11px; - border: 1px solid var(--border); - border-radius: 4px; - background: var(--bg-secondary); - color: var(--text-primary); - cursor: pointer; - white-space: nowrap; -} -.search-replace-btn:hover { background: var(--bg-hover); } -.search-replace-btn.destructive { border-color: var(--text-error); color: var(--text-error); } - -/* ── Active search result highlight ── */ -.btn-bookmark.active { - color: #059669; - border-color: #059669; - background: rgba(5, 150, 105, 0.08); -} -.btn-bookmark.active:hover { - background: rgba(5, 150, 105, 0.15); -} - -.btn-share.shared { - color: #059669; - border-color: #059669; - background: rgba(5, 150, 105, 0.08); -} -.btn-share.shared:hover { - background: rgba(5, 150, 105, 0.15); -} - -/* ── Shared Cards ── */ -.shared-card { - padding: 10px 14px; - background: var(--bg-card, var(--bg-secondary)); - border-radius: 6px; - border: 1px solid var(--border); - cursor: pointer; - transition: background 0.15s; - display: flex; - flex-direction: column; - gap: 6px; -} -.shared-card:hover { background: var(--bg-hover); } -.shared-card-header { - display: flex; - align-items: center; - gap: 8px; -} -.shared-card-title { font-weight: 500; font-size: 0.85rem; } -.shared-card-vault { - font-size: 0.65rem; - color: var(--accent); - background: var(--accent-bg, rgba(99,102,241,0.1)); - padding: 1px 6px; - border-radius: 3px; - margin-left: auto; -} -.shared-card-meta { - font-size: 0.7rem; - color: var(--text-muted); - display: flex; - gap: 12px; -} -.shared-card-actions { - display: flex; - gap: 6px; -} -.shared-card-actions button { - font-size: 0.7rem; - padding: 2px 8px; - border: 1px solid var(--border); - border-radius: 4px; - background: var(--bg-primary); - color: var(--text-primary); - cursor: pointer; -} -.shared-card-actions button:hover { background: var(--bg-hover); } - -/* ── Dashboard Tab Navigation ── */ -.dashboard-tabs { - display: flex; - gap: 2px; - margin-bottom: 16px; - border-bottom: 2px solid var(--border); -} -.dashboard-tab { - padding: 8px 16px; - border: none; - background: none; - color: var(--text-muted); - cursor: pointer; - font-size: 0.85rem; - font-weight: 500; - display: flex; - align-items: center; - gap: 6px; - border-bottom: 2px solid transparent; - margin-bottom: -2px; - transition: color 0.15s, border-color 0.15s; -} -.dashboard-tab:hover { color: var(--text-primary); } -.dashboard-tab.active { - color: var(--accent); - border-bottom-color: var(--accent); -} -.dashboard-panel { - display: none; -} -.dashboard-panel.active { - display: block; -} - -/* ═══════════════════════════════════════════════════════════════════ - Command Palette (Ctrl+P) - ═══════════════════════════════════════════════════════════════════ */ - -.command-palette-overlay { - position: fixed; - top: 0; left: 0; right: 0; bottom: 0; - background: 0 0; - z-index: 10000; - display: flex; - justify-content: center; - padding-top: 12vh; - pointer-events: none; - opacity: 0; - transition: opacity 0.1s ease, background 0.1s ease; -} - -.command-palette-overlay.active { - opacity: 1; - background: var(--overlay-bg); - pointer-events: auto; -} - -.command-palette { - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: 10px; - box-shadow: 0 8px 40px rgba(0,0,0,0.45), 0 0 0 1px rgba(255,255,255,0.03); - width: 580px; - max-width: calc(100vw - 40px); - max-height: 60vh; - display: flex; - flex-direction: column; - overflow: hidden; - animation: cp-slide-in 0.12s ease-out; -} - -@keyframes cp-slide-in { - from { transform: translateY(-12px); opacity: 0; } - to { transform: translateY(0); opacity: 1; } -} - -.cp-header { - display: flex; - align-items: center; - border-bottom: 1px solid var(--border); - padding: 0 14px; -} - -.cp-input { - flex: 1; - border: none; - background: none; - padding: 14px 0; - font-size: 16px; - color: var(--text-primary); - outline: none; - font-family: inherit; -} - -.cp-input::placeholder { - color: var(--text-muted); -} - -.cp-hint { - font-size: 11px; - color: var(--text-muted); - background: var(--bg-hover); - padding: 3px 8px; - border-radius: 4px; - font-family: "JetBrains Mono", monospace; - opacity: 0.7; -} - -.cp-results { - flex: 1; - overflow-y: auto; - padding: 6px 0; - max-height: 40vh; -} - -.cp-empty { - padding: 24px 16px; - text-align: center; - color: var(--text-muted); - font-size: 13px; -} - -.cp-error { - color: var(--accent-orange, #d29922); -} - -.cp-item { - display: flex; - justify-content: space-between; - align-items: center; - padding: 8px 14px; - cursor: pointer; - border-left: 3px solid transparent; -} - -.cp-item:hover { - background: var(--bg-hover); - border-left-color: var(--accent); -} - -.cp-item.cp-selected { - background: var(--accent-bg); - border-left-color: var(--accent); -} - -.cp-item-label { - font-size: 14px; - color: var(--text-primary); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.cp-item-sublabel { - font-size: 11px; - color: var(--text-muted); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 45%; - text-align: right; - margin-left: 12px; -} - -.cp-footer { - display: flex; - gap: 14px; - padding: 8px 14px; - border-top: 1px solid var(--border); - font-size: 11px; - color: var(--text-muted); -} - -.cp-footer span { - display: flex; - align-items: center; - gap: 4px; -} - -.cp-footer span::before { - content: ''; - display: inline-block; - width: 3px; height: 3px; - background: var(--text-muted); - border-radius: 50%; - margin-right: 4px; -} - -.cp-footer span:first-child::before { display: none; } - -/* ── Breadcrumb ── */ -.cp-breadcrumb { - display: none; - align-items: center; - gap: 2px; - padding: 8px 14px; - font-size: 12px; - color: var(--text-secondary); - background: var(--bg-primary); - border-bottom: 1px solid var(--border); - overflow-x: auto; - white-space: nowrap; - scrollbar-width: none; -} -.cp-breadcrumb::-webkit-scrollbar { display: none; } -.cp-bc-root { font-weight: 600; color: var(--accent); } -.cp-bc-sep { color: var(--text-muted); padding: 0 2px; } -.cp-bc-item { cursor: pointer; padding: 1px 4px; border-radius: 3px; } -.cp-bc-item:hover { background: var(--bg-hover); } - -/* ── Name input ── */ -.cp-name-input { - display: flex; - flex-direction: column; - padding: 8px 14px; - border-bottom: 1px solid var(--border); - background: var(--bg-primary); -} -.cp-name-field { - width: 100%; - border: 1px solid var(--border); - background: var(--bg-secondary); - color: var(--text-primary); - padding: 10px 12px; - border-radius: 6px; - font-size: 14px; - font-family: inherit; - outline: none; - transition: border-color 0.15s; -} -.cp-name-field:focus { border-color: var(--accent); } -.cp-name-hint { - font-size: 11px; - color: var(--text-muted); - margin-top: 6px; -} - -/* Browse filter in command palette */ -.cp-browse-filter { - width: calc(100% - 24px); - margin: 8px 12px 4px; - padding: 7px 10px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-primary); - color: var(--text-primary); - font-size: 0.8rem; - font-family: inherit; - outline: none; - transition: border-color 0.15s; -} -.cp-browse-filter:focus { border-color: var(--accent); } -.cp-browse-filter::placeholder { color: var(--text-muted); } - -/* ── Help Modal: Mobile responsive ── */ -@media (max-width: 768px) { - .help-container, - .editor-container.help-container { - max-width: 100vw; - width: 100vw; - height: 100vh; - max-height: 100vh; - border-radius: 0; - box-sizing: border-box; - } - - .help-hamburger { - display: inline-flex; - } - - /* TOC: collapsible block at top (not slide-over) */ - .help-nav { - position: static; - width: 100%; - min-width: 0; - max-width: 100%; - max-height: none; - height: auto; - z-index: auto; - transform: none; - transition: none; - border-right: none; - border-bottom: 1px solid var(--border); - box-shadow: none; - flex-shrink: 0; - display: none; - box-sizing: border-box; - } - .help-nav-header { - padding: 10px 16px 6px; - } - - /* Content full-width */ - .help-body { - flex-direction: column; - overflow-y: auto; - overflow-x: hidden; - padding: 0; - width: 100%; - box-sizing: border-box; - } - .help-content { - padding: 14px 14px 40px; - flex: 1; - overflow-y: auto; - overflow-x: hidden; - -webkit-overflow-scrolling: touch; - word-break: break-word; - width: 100%; - max-width: 100%; - box-sizing: border-box; - } - .help-content pre, .help-content code, .help-content table { - max-width: 100%; - overflow-x: auto; - } - .help-content:focus { outline: none; } - .help-hero { - flex-direction: column; - gap: 16px; - min-width: 0; - width: 100%; - box-sizing: border-box; - padding: 20px 16px; - } - .help-hero-copy { - min-width: 0; - width: 100%; - } - .help-badges { - flex-wrap: wrap; - gap: 6px; - } - .help-badge { - white-space: normal; - } - .help-hero-visual { display: none; } - .help-section { - padding: 20px 0 16px; - min-width: 0; - width: 100%; - box-sizing: border-box; - } - .help-nav-link { - padding: 10px 12px; - font-size: 0.88rem; - } -} - -/* ══════════════════════════════════════════ - Mobile Bottom Toolbar (Obsidian-style) - ══════════════════════════════════════════ */ -.mobile-toolbar { - display: none; -} -.vault-context-bar { - display: none; -} - -@media (max-width: 768px) { - .mobile-toolbar { - display: flex; - position: fixed; - bottom: 0; - left: 0; - right: 0; - height: 64px; - background: var(--bg-secondary); - border-top: 1px solid var(--border); - z-index: 900; - align-items: center; - justify-content: space-around; - padding: 4px 4px; - padding-bottom: calc(4px + env(safe-area-inset-bottom, 0)); - -webkit-backdrop-filter: blur(12px); - backdrop-filter: blur(12px); - } - - /* Push content up to avoid toolbar overlap */ - .main-layout { - padding-bottom: 64px; - padding-bottom: calc(64px + env(safe-area-inset-bottom, 0)); - } - .editor-modal.active ~ .main-layout { - padding-bottom: 0; - } - - /* Enable pull-to-refresh on mobile — unblock the overscroll chain */ - html { - overscroll-behavior-y: auto; - } - body { - overflow-y: auto; - overscroll-behavior-y: auto; - height: 100vh; - height: 100dvh; - } - .app-container { - overflow-y: visible; - } - .main-layout { - overflow-y: visible; - } - .content-wrapper { - overflow: visible; - } - .content-area { - overscroll-behavior-y: auto; - } - - /* Hide desktop tab bar on mobile (bottom toolbar has its own tab button) */ - .tab-bar { - display: none !important; - } - - /* Vault context indicator — hidden (now in header) */ - .vault-context-bar { - display: none !important; - } - .vault-context-pill { - display: none; - } - - .mt-btn { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 3px; - flex: 1; - height: auto; - min-height: 48px; - padding: 4px 4px; - border: none; - border-radius: 8px; - background: transparent; - color: var(--text-muted); - cursor: pointer; - transition: color 0.15s, background 0.15s; - position: relative; - -webkit-tap-highlight-color: transparent; - } - .mt-btn:active { - background: rgba(255,255,255,0.06); - } - .mt-btn svg { - flex-shrink: 0; - } - .mt-label { - font-size: 10px; - font-weight: 500; - line-height: 1; - } - .mt-btn-primary { - color: var(--accent); - } - .mt-btn-primary .mt-label { - color: var(--accent); - } - - /* Tab count badge */ - .mt-badge { - position: absolute; - top: 2px; - right: 50%; - transform: translateX(18px); - background: var(--accent); - color: #fff; - font-size: 9px; - font-weight: 700; - min-width: 16px; - height: 16px; - border-radius: 8px; - display: flex; - align-items: center; - justify-content: center; - padding: 0 4px; - line-height: 1; - } - - /* ── Tab Switcher Bottom Sheet ── */ - .mt-overlay { - display: none; - position: fixed; - inset: 0; - background: rgba(0,0,0,0.5); - z-index: 950; - opacity: 0; - transition: opacity 0.25s; - } - .mt-overlay.visible { - display: block; - opacity: 1; - } - - .mt-tab-switcher { - position: fixed; - bottom: 0; - left: 0; - right: 0; - max-height: 60vh; - background: var(--bg-secondary); - border-radius: 16px 16px 0 0; - z-index: 960; - transform: translateY(100%); - transition: transform 0.3s cubic-bezier(0.32, 0.72, 0, 1); - display: flex; - flex-direction: column; - box-shadow: 0 -4px 24px rgba(0,0,0,0.4); - padding-bottom: env(safe-area-inset-bottom, 0); - } - .mt-tab-switcher.open { - transform: translateY(0); - } - - .mt-sheet-handle { - width: 36px; - height: 4px; - background: var(--border); - border-radius: 2px; - margin: 10px auto 6px; - flex-shrink: 0; - } - - .mt-sheet-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 8px 16px 12px; - flex-shrink: 0; - } - .mt-sheet-title { - font-family: "JetBrains Mono", monospace; - font-size: 0.8rem; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--text-muted); - } - .mt-sheet-close { - width: 28px; height: 28px; - padding: 0; - border: 1px solid var(--border); - border-radius: 6px; - background: transparent; - color: var(--text-secondary); - cursor: pointer; - font-size: 12px; - display: flex; - align-items: center; - justify-content: center; - } - .mt-sheet-close:hover { color: var(--accent); border-color: var(--accent); } - .mt-sheet-actions { - display: flex; - align-items: center; - gap: 8px; - } - .mt-sheet-close-all { - padding: 5px 10px; - border: 1px solid var(--danger, #ef4444); - border-radius: 6px; - background: transparent; - color: var(--danger, #ef4444); - cursor: pointer; - font-size: 0.7rem; - font-weight: 600; - transition: background 0.15s; - } - .mt-sheet-close-all:hover { - background: rgba(239,68,68,0.1); - } - - .mt-sheet-list { - flex: 1; - overflow-y: auto; - padding: 0 12px 12px; - -webkit-overflow-scrolling: touch; - } - - .mt-tab-item { - display: flex; - align-items: center; - gap: 10px; - padding: 10px 12px; - border-radius: 8px; - cursor: pointer; - color: var(--text-primary); - font-size: 0.85rem; - transition: background 0.1s; - margin-bottom: 2px; - } - .mt-tab-item:active { - background: rgba(255,255,255,0.06); - } - .mt-tab-item.active { - background: color-mix(in srgb, var(--accent) 12%, transparent); - color: var(--accent); - font-weight: 600; - } - .mt-tab-item-icon { - flex-shrink: 0; - opacity: 0.6; - } - .mt-tab-item-name { - flex: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - .mt-tab-item-close { - width: 24px; height: 24px; - padding: 0; - border: none; - border-radius: 4px; - background: transparent; - color: var(--text-muted); - cursor: pointer; - font-size: 14px; - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - } - .mt-tab-item-close:hover { - color: var(--danger, #ef4444); - background: rgba(239,68,68,0.1); - } -} - -/* ========================================================================== - Backup / Diff Viewer Modal - ========================================================================== */ - -.backup-viewer-panel { - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: min(90vw, 960px); - height: min(85vh, 700px); - background: var(--bg-primary, #1e1e2e); - border: 1px solid var(--border); - border-radius: 12px; - box-shadow: 0 25px 60px rgba(0,0,0,0.5); - display: flex; - flex-direction: column; - overflow: hidden; - z-index: 1001; -} - -.backup-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: 14px 18px; - border-bottom: 1px solid var(--border); - background: var(--bg-secondary); - flex-shrink: 0; -} - -.backup-header-left { - display: flex; - align-items: baseline; - gap: 10px; - min-width: 0; -} - -.backup-header h3 { - margin: 0; - font-size: 1rem; - font-weight: 600; - color: var(--text-primary); -} - -.backup-file-path { - font-size: 0.78rem; - color: var(--text-muted); - font-family: var(--font-mono, 'SF Mono', 'Fira Code', monospace); - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.backup-header-right { - display: flex; - align-items: center; - gap: 12px; - flex-shrink: 0; -} - -.backup-count { - font-size: 0.75rem; - color: var(--text-muted); - background: var(--bg-tertiary); - padding: 3px 8px; - border-radius: 4px; -} - -.backup-close-btn { - width: 36px; - height: 36px; - padding: 0; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-primary); - color: var(--text-secondary); - cursor: pointer; - transition: all 150ms ease; - display: inline-flex; - align-items: center; - justify-content: center; - flex: 0 0 auto; - box-shadow: 0 2px 8px rgba(0,0,0,0.15); -} - -.backup-close-btn:hover { - color: var(--accent); - border-color: var(--accent); -} - -.backup-toolbar { - display: flex; - align-items: center; - gap: 10px; - padding: 10px 18px; - border-bottom: 1px solid var(--border); - background: var(--bg-primary); - flex-shrink: 0; -} - -.backup-selector-group { - display: flex; - align-items: center; - gap: 6px; -} - -.backup-selector-group label { - font-size: 0.78rem; - color: var(--text-muted); - white-space: nowrap; -} - -.backup-select { - padding: 6px 10px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-secondary); - color: var(--text-primary); - font-size: 0.8rem; - font-family: var(--font-mono); - max-width: 240px; - cursor: pointer; -} - -.backup-select:focus { - outline: none; - border-color: var(--accent); -} - -.backup-vs-label { - font-size: 0.75rem; - color: var(--text-muted); - font-weight: 600; - user-select: none; -} - -.backup-restore-btn { - margin-left: auto; - padding: 6px 14px; - border: 1px solid var(--accent); - border-radius: 6px; - background: color-mix(in srgb, var(--accent) 10%, transparent); - color: var(--accent); - font-size: 0.8rem; - font-weight: 500; - cursor: pointer; - display: flex; - align-items: center; - gap: 5px; - transition: background 0.15s, opacity 0.15s; - white-space: nowrap; -} - -.backup-restore-btn:hover { - background: color-mix(in srgb, var(--accent) 20%, transparent); -} - -.backup-restore-btn:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.backup-restore-btn .icon-sm { - width: 14px; - height: 14px; -} - -.backup-diff-container { - flex: 1; - overflow-y: auto; - background: var(--bg-primary); -} - -.backup-diff-loading, -.backup-diff-error, -.backup-diff-empty { - display: flex; - align-items: center; - justify-content: center; - height: 100%; - color: var(--text-muted); - font-size: 0.85rem; -} - -.backup-diff-error { - color: var(--danger, #ef4444); -} - -.backup-diff-output { - padding: 0; -} - -.backup-diff-table { - width: 100%; - border-collapse: collapse; - font-family: var(--font-mono, 'SF Mono', 'Fira Code', 'Cascadia Code', monospace); - font-size: 0.8rem; - line-height: 1.55; - table-layout: fixed; -} - -.backup-diff-table td { - padding: 0; -} - -.backup-diff-table td.diff-prefix { - width: 22px; - text-align: center; - user-select: none; - font-weight: 600; - padding: 1px 0; - vertical-align: top; -} - -.backup-diff-table td.diff-content { - padding: 1px 8px; - vertical-align: top; -} - -.backup-diff-table td.diff-content pre { - margin: 0; - white-space: pre-wrap; - word-break: break-all; - font-family: inherit; - font-size: inherit; - line-height: inherit; -} - -.backup-diff-table tr.diff-add td { - background: rgba(34, 197, 94, 0.12); -} - -.backup-diff-table tr.diff-add td.diff-prefix { - color: #22c55e; -} - -.backup-diff-table tr.diff-del td { - background: rgba(239, 68, 68, 0.12); -} - -.backup-diff-table tr.diff-del td.diff-prefix { - color: #ef4444; -} - -.backup-diff-table tr.diff-hunk td { - background: color-mix(in srgb, var(--accent) 8%, transparent); - color: var(--accent); - font-weight: 600; -} - -.backup-diff-table tr.diff-header-line td { - background: var(--bg-secondary); - color: var(--text-muted); - font-weight: 600; -} - -.backup-diff-table tr.diff-context td { - color: var(--text-secondary); -} - -.backup-body { - flex: 1; - display: flex; - flex-direction: column; - overflow: auto; -} - -.backup-footer { - padding: 6px 18px; - border-top: 1px solid var(--border); - background: var(--bg-secondary); - flex-shrink: 0; -} - -.backup-footer-hint { - font-size: 0.7rem; - color: var(--text-muted); -} - -/* ── Side-by-side diff view ── */ -.backup-diff-sidebyside .sidebyside { - table-layout: fixed; -} - -.backup-diff-sidebyside td.sidebyside-left { - border-right: 1px solid var(--border); -} - -.backup-diff-sidebyside td.sidebyside-right { - border-left: 1px solid var(--border); -} - -.backup-diff-sidebyside td.diff-empty-cell { - background: var(--bg-tertiary); -} - -.backup-diff-mode-btn { - padding: 6px 10px; - border: 1px solid var(--border); - border-radius: 6px; - background: transparent; - color: var(--text-secondary); - cursor: pointer; - display: inline-flex; - align-items: center; - gap: 4px; - font-size: 0.8rem; - transition: all 150ms ease; -} - -.backup-diff-mode-btn:hover { - color: var(--accent); - border-color: var(--accent); -} - -.backup-diff-mode-btn .icon-sm { - width: 14px; - height: 14px; -} - -/* ── Backup Manager ── */ -.backup-manager { - padding: 16px 24px; - max-width: 1000px; - margin: 0 auto; -} - -.backup-manager-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 12px; - gap: 12px; -} - -.backup-manager-header h2 { - margin: 0; - font-size: 1.1rem; - display: flex; - align-items: center; - gap: 8px; -} - -.backup-manager-actions { - display: flex; - gap: 6px; -} - -.backup-manager-filter { - padding: 6px 10px; - border: 1px solid var(--border); - border-radius: 6px; - background: var(--bg-primary); - color: var(--text-primary); - font-size: 0.8rem; - min-width: 200px; -} - -.backup-manager-btn { - width: 32px; height: 32px; - border: 1px solid var(--border); - border-radius: 6px; - background: transparent; - color: var(--text-secondary); - cursor: pointer; - display: inline-flex; - align-items: center; - justify-content: center; -} - -.backup-manager-btn:hover { color: var(--accent); border-color: var(--accent); } - -.backup-manager-stats { display: flex; gap: 16px; margin-bottom: 14px; } -.bm-stat { font-size: 0.8rem; color: var(--text-muted); } - -.bm-vault-group { margin-bottom: 16px; } -.bm-vault-name { - font-size: 0.85rem; font-weight: 600; margin: 0 0 6px 0; - display: flex; align-items: center; gap: 6px; -} - -.bm-file-group { - border: 1px solid var(--border); border-radius: 6px; - margin-bottom: 8px; overflow: hidden; -} - -.bm-file-header { - display: flex; align-items: center; gap: 12px; - padding: 8px 12px; background: var(--bg-secondary); - border-bottom: 1px solid var(--border); -} - -.bm-file-name { font-size: 0.8rem; font-weight: 500; display: flex; align-items: center; gap: 4px; } -.bm-file-meta { font-size: 0.7rem; color: var(--text-muted); flex: 1; } - -.bm-file-purge { - width: 28px; height: 28px; border: 1px solid var(--border); border-radius: 4px; - background: transparent; color: var(--text-muted); cursor: pointer; - display: flex; align-items: center; justify-content: center; -} -.bm-file-purge:hover { color: var(--danger); border-color: var(--danger); } - -.bm-backup-list { padding: 2px 0; } - -.bm-backup-item { - display: flex; align-items: center; gap: 12px; - padding: 4px 12px; font-size: 0.75rem; -} -.bm-backup-item:hover { background: var(--bg-secondary); } - -.bm-backup-date { color: var(--text-secondary); min-width: 130px; font-family: var(--font-mono); } -.bm-backup-size { color: var(--text-muted); flex: 1; } - -.bm-backup-delete { - width: 22px; height: 22px; border: none; border-radius: 4px; - background: transparent; color: var(--text-muted); cursor: pointer; - display: flex; align-items: center; justify-content: center; - opacity: 0; -} -.bm-backup-item:hover .bm-backup-delete { opacity: 1; } -.bm-backup-delete:hover { color: var(--danger); background: rgba(239,68,68,0.1); } - -.backup-footer-manage-btn { - background: none; border: 1px solid var(--border); - border-radius: 4px; color: var(--accent); - font-size: 0.7rem; cursor: pointer; padding: 3px 10px; - transition: all 150ms ease; -} -.backup-footer-manage-btn:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); } - -.backup-manager-empty, -.backup-manager-error { - text-align: center; padding: 2rem; color: var(--text-muted); font-size: 0.85rem; -} -.backup-manager-error { color: var(--danger); } - -/* ========================================================================== - Mermaid.js Diagrams - ========================================================================== */ - -.mermaid-container { - margin: 12px 0; - border: 1px solid var(--border); - border-radius: 8px; - overflow: hidden; - background: var(--bg-secondary); -} - -/* ── Header bar ── */ -.mermaid-header { - display: flex; align-items: center; justify-content: space-between; - padding: 6px 10px; - background: var(--bg-hover); - border-bottom: 1px solid var(--border); - min-height: 34px; -} -.mermaid-diagram-type { - font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace; - font-size: 0.75rem; font-weight: 600; - color: var(--text-secondary); -} -.mermaid-header-actions { - display: flex; align-items: center; gap: 2px; -} - -/* ── Buttons ── */ -.mermaid-btn { - width: 28px; height: 28px; - border: 1px solid transparent; border-radius: 4px; - background: transparent; color: var(--text-secondary); - cursor: pointer; display: flex; align-items: center; justify-content: center; - transition: background 0.12s, color 0.12s; -} -.mermaid-btn:hover { background: var(--bg-primary); color: var(--accent); border-color: var(--border); } - -/* ── Code / Preview toggle ── */ -.mermaid-toggle { - display: flex; margin-left: 8px; - border: 1px solid var(--border); border-radius: 5px; - overflow: hidden; -} -.mermaid-toggle-btn { - padding: 2px 10px; font-size: 0.7rem; font-weight: 500; - border: none; background: transparent; - color: var(--text-muted, #999); cursor: pointer; - transition: background 0.12s, color 0.12s; -} -.mermaid-toggle-btn.active { - background: var(--bg-primary); color: var(--text-primary); - box-shadow: 0 0 0 1px var(--border); -} -.mermaid-toggle-btn:first-child { border-right: 1px solid var(--border); } - -/* ── Body ── */ -.mermaid-body { - position: relative; -} -.mermaid-rendered { - padding: 16px; - overflow: hidden; - min-height: 80px; - display: flex; - justify-content: center; -} -.mermaid-rendered svg { max-width: 100%; height: auto; } - -.mermaid-source { padding: 16px; overflow: auto; } -.mermaid-source pre { - margin: 0; padding: 12px; - background: var(--code-bg); - border-radius: 4px; - font-size: 0.78rem; line-height: 1.5; - color: var(--text-primary); -} - -/* ── Error ── */ -.mermaid-error { - margin: 12px 0; padding: 12px 16px; - border: 1px solid rgba(239,68,68,0.3); border-radius: 6px; - background: rgba(239,68,68,0.08); color: var(--danger); - font-size: 0.8rem; line-height: 1.5; -} -.mermaid-error strong { display: block; margin-bottom: 4px; } - -/* ── Fullscreen ── */ -.mermaid-fullscreen-overlay { - position: fixed; top: 0; left: 0; right: 0; bottom: 0; - z-index: 10000; - display: flex; flex-direction: column; -} -/* Light theme — clean white like the example */ -[data-theme="light"] .mermaid-fullscreen-overlay { - background: rgba(255,255,255,0.97); -} -[data-theme="light"] .mermaid-fullscreen-header { - background: rgba(0,0,0,0.03); - border-bottom: 1px solid rgba(0,0,0,0.08); -} -[data-theme="light"] .mermaid-fullscreen-header .mermaid-diagram-type { - color: rgba(0,0,0,0.5); -} -[data-theme="light"] .mermaid-fullscreen-header .mermaid-btn { - color: rgba(0,0,0,0.4); -} -[data-theme="light"] .mermaid-fullscreen-header .mermaid-btn:hover { - background: rgba(0,0,0,0.05); - color: rgba(0,0,0,0.8); -} - -/* Dark theme */ -[data-theme="dark"] .mermaid-fullscreen-overlay { - background: rgba(18,18,24,0.97); -} -[data-theme="dark"] .mermaid-fullscreen-header { - background: rgba(255,255,255,0.06); - border-bottom: 1px solid rgba(255,255,255,0.08); -} -[data-theme="dark"] .mermaid-fullscreen-header .mermaid-diagram-type { - color: rgba(255,255,255,0.7); -} -[data-theme="dark"] .mermaid-fullscreen-header .mermaid-btn { - color: rgba(255,255,255,0.6); -} -[data-theme="dark"] .mermaid-fullscreen-header .mermaid-btn:hover { - background: rgba(255,255,255,0.1); - color: #fff; -} - -.mermaid-fullscreen-header { - display: flex; align-items: center; justify-content: space-between; - padding: 10px 16px; - min-height: 46px; - flex-shrink: 0; -} -.mermaid-fullscreen-content { - flex: 1; - display: flex; align-items: center; justify-content: center; - padding: 16px; - overflow: hidden; -} -.mermaid-fullscreen-content svg { - width: 100%; height: 100%; - max-width: 100%; max-height: 100%; -} - -/* ── Dark mode overrides for beta diagrams that ignore themeVariables ── */ - -/* packet-beta */ -[data-theme="dark"] .mermaid-rendered svg .row rect, -[data-theme="dark"] .mermaid-rendered svg g[id*="packet"] rect { - fill: #1e3a5f !important; - stroke: #4a7ab5 !important; -} -[data-theme="dark"] .mermaid-rendered svg .row text, -[data-theme="dark"] .mermaid-rendered svg g[id*="packet"] text { - fill: #c8daf0 !important; -} -[data-theme="dark"] .mermaid-fullscreen-content svg .row rect, -[data-theme="dark"] .mermaid-fullscreen-content svg g[id*="packet"] rect { - fill: #1e3a5f !important; - stroke: #4a7ab5 !important; -} -[data-theme="dark"] .mermaid-fullscreen-content svg .row text, -[data-theme="dark"] .mermaid-fullscreen-content svg g[id*="packet"] text { - fill: #c8daf0 !important; -} - -/* xychart-beta — bar fills and line color */ -[data-theme="dark"] .mermaid-rendered svg rect[class*="plot"], -[data-theme="dark"] .mermaid-rendered svg rect[id*="bar"] { - fill: #1e3a5f !important; - stroke: #4a7ab5 !important; -} -[data-theme="dark"] .mermaid-rendered svg path[class*="plot"], -[data-theme="dark"] .mermaid-rendered svg path[id*="line"] { - stroke: #6a9ad0 !important; -} -[data-theme="dark"] .mermaid-fullscreen-content svg rect[class*="plot"], -[data-theme="dark"] .mermaid-fullscreen-content svg rect[id*="bar"] { - fill: #1e3a5f !important; - stroke: #4a7ab5 !important; -} -[data-theme="dark"] .mermaid-fullscreen-content svg path[class*="plot"], -[data-theme="dark"] .mermaid-fullscreen-content svg path[id*="line"] { - stroke: #6a9ad0 !important; -} - -.mermaid-focus-panel { - position: fixed; top: 0; right: 0; bottom: 0; width: 480px; - z-index: 9998; background: var(--bg-secondary); - border-left: 1px solid var(--border); - box-shadow: -4px 0 24px rgba(0,0,0,0.3); - display: flex; flex-direction: column; -} -.mermaid-focus-header { - display: flex; align-items: center; justify-content: space-between; - padding: 10px 14px; border-bottom: 1px solid var(--border); - font-size: 0.85rem; font-weight: 600; -} -.mermaid-focus-close { - width: 28px; height: 28px; border: 1px solid var(--border); border-radius: 4px; - background: transparent; color: var(--text-muted); cursor: pointer; - display: flex; align-items: center; justify-content: center; -} -.mermaid-focus-close:hover { color: var(--accent); } -.mermaid-focus-content { flex: 1; overflow: auto; padding: 16px; } - -/* Mermaid editor live preview panel */ -.mermaid-live-preview { - border-top: 1px solid var(--border); - background: var(--bg-secondary); - min-height: 100px; max-height: 300px; - overflow: auto; padding: 12px; -} -.mermaid-live-preview .mermaid-error { margin: 0; } - -/* Manager body: list + preview side panel */ -.backup-manager-body { display: flex; gap: 0; min-height: 400px; } - -.backup-manager-list { flex: 1; min-width: 0; } - -.backup-manager-preview { - width: 400px; flex-shrink: 0; - border-left: 1px solid var(--border); - background: var(--bg-primary); - display: flex; flex-direction: column; -} -.bm-preview-header { - display: flex; align-items: center; justify-content: space-between; - padding: 10px 14px; border-bottom: 1px solid var(--border); -} -.bm-preview-header h3 { margin: 0; font-size: 0.85rem; } -.bm-preview-content { - flex: 1; overflow: auto; padding: 12px 14px; - font-family: var(--font-mono); font-size: 0.75rem; line-height: 1.55; - white-space: pre-wrap; word-break: break-all; - color: var(--text-secondary); margin: 0; -} - -/* Vault header with purge button */ -.bm-vault-header { - display: flex; align-items: center; gap: 12px; - padding: 8px 0; border-bottom: 1px solid var(--border); margin-bottom: 8px; -} -.bm-vault-meta { font-size: 0.7rem; color: var(--text-muted); flex: 1; } - -.bm-vault-purge { - padding: 3px 10px; border: 1px solid var(--border); border-radius: 4px; - background: transparent; color: var(--danger); cursor: pointer; - font-size: 0.7rem; display: flex; align-items: center; gap: 4px; - transition: all 150ms ease; -} -.bm-vault-purge:hover { background: rgba(239,68,68,0.08); border-color: var(--danger); } - -/* Backup item actions */ -.bm-backup-actions { display: flex; gap: 2px; opacity: 0; transition: opacity 0.12s; } -.bm-backup-item:hover .bm-backup-actions { opacity: 1; } - -.bm-backup-preview, -.bm-backup-restore { - width: 22px; height: 22px; border: none; border-radius: 4px; - background: transparent; color: var(--text-muted); cursor: pointer; - display: flex; align-items: center; justify-content: center; -} -.bm-backup-preview:hover { color: var(--accent); background: rgba(59,130,246,0.1); } -.bm-backup-restore:hover { color: #22c55e; background: rgba(34,197,94,0.1); } - -.bm-backup-item.active { - background: color-mix(in srgb, var(--accent) 10%, transparent); - border-radius: 4px; -} - -/* ── About Modal ── */ -.about-overlay { - position: fixed; inset: 0; z-index: 1000; - background: rgba(0,0,0,0.7); backdrop-filter: blur(6px); - display: none; align-items: center; justify-content: center; -} -.about-overlay.active { display: flex; } -.about-modal { - background: var(--bg-secondary); - border: 1px solid var(--border-md); - border-radius: 16px; - width: 540px; max-width: 94vw; max-height: 90vh; - overflow-y: auto; - position: relative; - box-shadow: 0 20px 60px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.05); - animation: about-in 0.35s ease; -} -@keyframes about-in { - from { opacity: 0; transform: translateY(20px) scale(0.97); } - to { opacity: 1; transform: translateY(0) scale(1); } -} -.about-close { - position: absolute; top: 12px; right: 14px; - background: var(--bg-hover); border: none; color: var(--text-secondary); - width: 30px; height: 30px; border-radius: 8px; font-size: 18px; - cursor: pointer; display: flex; align-items: center; justify-content: center; - transition: background 0.15s, color 0.15s; z-index: 1; -} -.about-close:hover { background: var(--danger-bg); color: var(--danger); } -.about-hero { - text-align: center; padding: 22px 24px 16px; - background: linear-gradient(160deg, var(--accent-bg) 0%, transparent 60%); - border-bottom: 1px solid var(--border); -} -.about-logo { margin-bottom: 8px; display: inline-block; } -.about-title { - font-size: 1.4rem; font-weight: 700; color: var(--text-primary); - letter-spacing: -0.5px; margin-bottom: 4px; -} -.about-tagline { - font-size: 0.8rem; color: var(--text-secondary); line-height: 1.4; - margin-bottom: 8px; -} -.about-version { - display: inline-block; padding: 3px 12px; - background: var(--accent); color: #fff; - font-size: 0.7rem; font-weight: 600; font-family: var(--mono); - border-radius: 20px; letter-spacing: 0.5px; -} -.about-body { padding: 12px 28px 16px; } -.about-stats { - display: flex; gap: 0; justify-content: center; - margin-bottom: 10px; -} -.about-stat { - flex: 1; text-align: center; padding: 8px 8px; - border-right: 1px solid var(--border); -} -.about-stat:last-child { border-right: none; } -.about-stat-value { - display: block; font-size: 1.3rem; font-weight: 700; - color: var(--accent); font-family: var(--mono); -} -.about-stat-label { - font-size: 0.6rem; color: var(--text-muted); - text-transform: uppercase; letter-spacing: 0.6px; margin-top: 1px; -} -.about-stack { margin-bottom: 10px; } -.about-stack h3 { - font-size: 0.65rem; color: var(--text-muted); text-transform: uppercase; - letter-spacing: 0.8px; margin-bottom: 6px; -} -.about-stack-grid { - display: flex; flex-wrap: wrap; gap: 5px; -} -.about-stack-badge { - padding: 2px 8px; font-size: 0.65rem; - background: var(--bg-hover); color: var(--text-secondary); - border: 1px solid var(--border); border-radius: 6px; - font-family: var(--mono); -} -.about-footer { border-top: 1px solid var(--border); padding-top: 10px; } -.about-meta { - display: flex; gap: 16px; font-size: 0.65rem; color: var(--text-muted); - margin-bottom: 6px; flex-wrap: wrap; -} -.about-meta strong { color: var(--text-secondary); font-family: var(--mono); font-size: 0.65rem; } -.about-joke { - font-size: 0.68rem; color: var(--text-muted); font-style: italic; - margin-bottom: 6px; opacity: 0.7; -} -.about-copy { - font-size: 0.62rem; color: var(--text-muted); opacity: 0.5; -} -.about-copy code { font-family: var(--mono); font-size: 0.58rem; } - -/* ── PDF Viewer ── */ -.pdf-viewer-container { - display: flex; - flex-direction: column; - height: 100%; -} -.pdf-toolbar { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 16px; - background: var(--surface1); - border-bottom: 1px solid var(--border); - font-size: 0.85rem; - flex-shrink: 0; -} -.pdf-info { - flex: 1; - color: var(--text-dim); -} -.pdf-iframe { - flex: 1; - width: 100%; - border: none; - min-height: 70vh; -} - -/* ── PaneManager — Split View ── */ -.pane-grid { - display: grid; - height: 100%; - overflow: hidden; -} -.pane-container { - display: flex; - flex-direction: column; - overflow: hidden; - position: relative; -} -.pane-container.pane-active { - outline: 2px solid var(--accent); - outline-offset: -2px; - z-index: 1; -} -.pane-tab-bar { flex-shrink: 0; } -.pane-content { flex: 1; overflow-y: auto; } -.pane-resize-handle { - background: var(--border); - transition: background 150ms; - min-width: 4px; - min-height: 4px; - z-index: 2; -} -.pane-resize-handle:hover { - background: var(--accent); -} -.code-block-wrapper:hover .copy-code-btn { - opacity: 1; -} -.copy-code-btn { - position: absolute; - top: 8px; - right: 8px; - display: flex; - align-items: center; - gap: 4px; - padding: 4px 10px; - background: var(--bg-secondary); - border: 1px solid var(--border); - border-radius: var(--radius); - color: var(--text-secondary); - font-size: 11px; - font-family: var(--mono); - cursor: pointer; - opacity: 0; - transition: opacity 150ms ease, background 150ms ease, color 150ms ease; - z-index: 5; -} -.copy-code-btn:hover { - background: var(--accent); - color: #fff; - border-color: var(--accent); -} -.copy-code-btn.copied { - background: var(--accent-green); - color: #fff; - border-color: var(--accent-green); -} - -/* Mobile : toujours visible (pas de hover sur tactile) */ -@media (max-width: 768px) { - .copy-code-btn { - opacity: 1; - padding: 2px 8px; - font-size: 10px; - top: 4px; - right: 4px; - } -} diff --git a/desktop/frontend-static/sw.js b/desktop/frontend-static/sw.js deleted file mode 100644 index 073b93d..0000000 --- a/desktop/frontend-static/sw.js +++ /dev/null @@ -1,197 +0,0 @@ -/* ObsiGate Service Worker - PWA v2 with IndexedDB offline support */ - -const CACHE_VERSION = 'obsigate-v6-i18n'; -const STATIC_CACHE = CACHE_VERSION + '-static'; -const DYNAMIC_CACHE = CACHE_VERSION + '-dynamic'; -const MAX_DYNAMIC_CACHE_SIZE = 100; - -const STATIC_ASSETS = [ - '/', - '/static/index.html', - '/static/app.js', - '/static/style.css', - '/static/manifest.json', - '/static/js/viewer.js', - '/static/js/i18n.js', - '/static/js/auth.js', - '/static/js/dashboard.js', - '/static/js/app.js', - '/static/locales/en.json', - '/static/locales/fr.json' -]; - -/* ── Install ── */ -self.addEventListener('install', (event) => { - console.log('[SW] Installing v' + CACHE_VERSION); - event.waitUntil( - caches.open(STATIC_CACHE) - .then((cache) => { - console.log('[SW] Caching static assets'); - return cache.addAll(STATIC_ASSETS.map(url => new Request(url, { cache: 'reload' }))); - }) - .catch((err) => console.error('[SW] Cache error:', err)) - .then(() => self.skipWaiting()) - ); -}); - -/* ── Activate ── */ -self.addEventListener('activate', (event) => { - console.log('[SW] Activating...'); - event.waitUntil( - caches.keys() - .then((cacheNames) => { - return Promise.all( - cacheNames - .filter((name) => name.startsWith('obsigate-') && name !== STATIC_CACHE && name !== DYNAMIC_CACHE) - .map((name) => { - console.log('[SW] Deleting old cache:', name); - return caches.delete(name); - }) - ); - }) - .then(() => self.clients.claim()) - ); -}); - -/* ── Fetch ── */ -self.addEventListener('fetch', (event) => { - const { request } = event; - const url = new URL(request.url); - - if (request.method !== 'GET') return; - if (url.pathname === '/api/events') return; - if (url.pathname.startsWith('/api/auth/')) return; - - // API requests: Network first, tell client to use IndexedDB if offline - if (url.pathname.startsWith('/api/')) { - event.respondWith(networkFirstAPI(request)); - return; - } - - // Static assets: Cache first - event.respondWith(cacheFirstStatic(request, url)); -}); - -/* ── Network First for API ── */ -async function networkFirstAPI(request) { - try { - const response = await fetch(request); - - // Cache successful GETs in dynamic cache - if (response && response.status === 200) { - const cache = await caches.open(DYNAMIC_CACHE); - cache.put(request, response.clone()); - limitCacheSize(DYNAMIC_CACHE, MAX_DYNAMIC_CACHE_SIZE); - } - return response; - } catch (error) { - console.log('[SW] Offline — checking cache for:', request.url); - - // Try dynamic cache first - const cached = await caches.match(request); - if (cached) { - // Add offline header so the page can detect - const headers = new Headers(cached.headers); - headers.set('X-ObsiGate-Offline', 'true'); - return new Response(cached.body, { status: cached.status, statusText: cached.statusText, headers }); - } - - // Fallback: tell the page to use IndexedDB - return new Response(JSON.stringify({ - offline: true, - endpoint: new URL(request.url).pathname, - message: 'Vous etes hors-ligne. Les donnees locales sont utilisees.' - }), { - status: 200, - headers: { 'Content-Type': 'application/json', 'X-ObsiGate-Offline': 'true' } - }); - } -} - -/* ── Cache First for Static ── */ -async function cacheFirstStatic(request, url) { - const cached = await caches.match(request); - if (cached) return cached; - - try { - const response = await fetch(request); - if (response && response.status === 200) { - const cache = await caches.open(STATIC_CACHE); - cache.put(request, response.clone()); - } - return response; - } catch { - // Offline fallback for HTML navigation - if (request.mode === 'navigate' || url.pathname === '/' || url.pathname.endsWith('/')) { - const offlinePage = await caches.match('/static/index.html'); - if (offlinePage) return offlinePage; - } - return new Response('Offline', { status: 503 }); - } -} - -async function limitCacheSize(cacheName, maxSize) { - const cache = await caches.open(cacheName); - const keys = await cache.keys(); - if (keys.length > maxSize) { - for (let i = 0; i < keys.length - maxSize; i++) { - await cache.delete(keys[i]); - } - } -} - -/* ── Messages ── */ -self.addEventListener('message', (event) => { - const data = event.data; - if (!data || !data.type) return; - - switch (data.type) { - case 'SKIP_WAITING': - self.skipWaiting(); - break; - case 'CLEAR_CACHE': - event.waitUntil( - caches.keys().then(names => Promise.all(names.map(n => caches.delete(n)))) - ); - break; - case 'CLAIM_CLIENTS': - event.waitUntil(self.clients.claim()); - break; - } -}); - -/* ── Sync ── */ -self.addEventListener('sync', (event) => { - console.log('[SW] Background sync:', event.tag); - if (event.tag === 'obsigate-sync') { - event.waitUntil( - self.clients.matchAll().then(clients => { - clients.forEach(client => { - client.postMessage({ type: 'SYNC_TRIGGERED' }); - }); - }) - ); - } -}); - -/* ── Push ── */ -self.addEventListener('push', (event) => { - const options = { - body: event.data ? event.data.text() : 'Nouvelle mise a jour', - icon: '/static/icons/icon-192x192.svg', - badge: '/static/icons/icon-72x72.svg', - vibrate: [200, 100, 200], - actions: [ - { action: 'open', title: 'Ouvrir ObsiGate' }, - { action: 'close', title: 'Fermer' } - ] - }; - event.waitUntil(self.registration.showNotification('ObsiGate', options)); -}); - -self.addEventListener('notificationclick', (event) => { - event.notification.close(); - if (event.action === 'open') { - event.waitUntil(clients.openWindow('/')); - } -}); diff --git a/desktop/python-embed/LICENSE.txt b/desktop/python-embed/LICENSE.txt deleted file mode 100644 index 7a0193a..0000000 --- a/desktop/python-embed/LICENSE.txt +++ /dev/null @@ -1,702 +0,0 @@ -A. HISTORY OF THE SOFTWARE -========================== - -Python was created in the early 1990s by Guido van Rossum at Stichting -Mathematisch Centrum (CWI, see https://www.cwi.nl) in the Netherlands -as a successor of a language called ABC. Guido remains Python's -principal author, although it includes many contributions from others. - -In 1995, Guido continued his work on Python at the Corporation for -National Research Initiatives (CNRI, see https://www.cnri.reston.va.us) -in Reston, Virginia where he released several versions of the -software. - -In May 2000, Guido and the Python core development team moved to -BeOpen.com to form the BeOpen PythonLabs team. In October of the same -year, the PythonLabs team moved to Digital Creations, which became -Zope Corporation. In 2001, the Python Software Foundation (PSF, see -https://www.python.org/psf/) was formed, a non-profit organization -created specifically to own Python-related Intellectual Property. -Zope Corporation was a sponsoring member of the PSF. - -All Python releases are Open Source (see https://opensource.org for -the Open Source Definition). Historically, most, but not all, Python -releases have also been GPL-compatible; the table below summarizes -the various releases. - - Release Derived Year Owner GPL- - from compatible? (1) - - 0.9.0 thru 1.2 1991-1995 CWI yes - 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes - 1.6 1.5.2 2000 CNRI no - 2.0 1.6 2000 BeOpen.com no - 1.6.1 1.6 2001 CNRI yes (2) - 2.1 2.0+1.6.1 2001 PSF no - 2.0.1 2.0+1.6.1 2001 PSF yes - 2.1.1 2.1+2.0.1 2001 PSF yes - 2.1.2 2.1.1 2002 PSF yes - 2.1.3 2.1.2 2002 PSF yes - 2.2 and above 2.1.1 2001-now PSF yes - -Footnotes: - -(1) GPL-compatible doesn't mean that we're distributing Python under - the GPL. All Python licenses, unlike the GPL, let you distribute - a modified version without making your changes open source. The - GPL-compatible licenses make it possible to combine Python with - other software that is released under the GPL; the others don't. - -(2) According to Richard Stallman, 1.6.1 is not GPL-compatible, - because its license has a choice of law clause. According to - CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 - is "not incompatible" with the GPL. - -Thanks to the many outside volunteers who have worked under Guido's -direction to make these releases possible. - - -B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON -=============================================================== - -Python software and documentation are licensed under the -Python Software Foundation License Version 2. - -Starting with Python 3.8.6, examples, recipes, and other code in -the documentation are dual licensed under the PSF License Version 2 -and the Zero-Clause BSD license. - -Some software incorporated into Python is under different licenses. -The licenses are listed with code falling under that license. - - -PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 --------------------------------------------- - -1. This LICENSE AGREEMENT is between the Python Software Foundation -("PSF"), and the Individual or Organization ("Licensee") accessing and -otherwise using this software ("Python") in source or binary form and -its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF hereby -grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, -analyze, test, perform and/or display publicly, prepare derivative works, -distribute, and otherwise use Python alone or in any derivative version, -provided, however, that PSF's License Agreement and PSF's notice of copyright, -i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Python Software Foundation; -All Rights Reserved" are retained in Python alone or in any derivative version -prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python. - -4. PSF is making Python available to Licensee on an "AS IS" -basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any -relationship of agency, partnership, or joint venture between PSF and -Licensee. This License Agreement does not grant permission to use PSF -trademarks or trade name in a trademark sense to endorse or promote -products or services of Licensee, or any third party. - -8. By copying, installing or otherwise using Python, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 -------------------------------------------- - -BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 - -1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an -office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the -Individual or Organization ("Licensee") accessing and otherwise using -this software in source or binary form and its associated -documentation ("the Software"). - -2. Subject to the terms and conditions of this BeOpen Python License -Agreement, BeOpen hereby grants Licensee a non-exclusive, -royalty-free, world-wide license to reproduce, analyze, test, perform -and/or display publicly, prepare derivative works, distribute, and -otherwise use the Software alone or in any derivative version, -provided, however, that the BeOpen Python License is retained in the -Software, alone or in any derivative version prepared by Licensee. - -3. BeOpen is making the Software available to Licensee on an "AS IS" -basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE -SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS -AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY -DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -5. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -6. This License Agreement shall be governed by and interpreted in all -respects by the law of the State of California, excluding conflict of -law provisions. Nothing in this License Agreement shall be deemed to -create any relationship of agency, partnership, or joint venture -between BeOpen and Licensee. This License Agreement does not grant -permission to use BeOpen trademarks or trade names in a trademark -sense to endorse or promote products or services of Licensee, or any -third party. As an exception, the "BeOpen Python" logos available at -http://www.pythonlabs.com/logos.html may be used according to the -permissions granted on that web page. - -7. By copying, installing or otherwise using the software, Licensee -agrees to be bound by the terms and conditions of this License -Agreement. - - -CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 ---------------------------------------- - -1. This LICENSE AGREEMENT is between the Corporation for National -Research Initiatives, having an office at 1895 Preston White Drive, -Reston, VA 20191 ("CNRI"), and the Individual or Organization -("Licensee") accessing and otherwise using Python 1.6.1 software in -source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, CNRI -hereby grants Licensee a nonexclusive, royalty-free, world-wide -license to reproduce, analyze, test, perform and/or display publicly, -prepare derivative works, distribute, and otherwise use Python 1.6.1 -alone or in any derivative version, provided, however, that CNRI's -License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) -1995-2001 Corporation for National Research Initiatives; All Rights -Reserved" are retained in Python 1.6.1 alone or in any derivative -version prepared by Licensee. Alternately, in lieu of CNRI's License -Agreement, Licensee may substitute the following text (omitting the -quotes): "Python 1.6.1 is made available subject to the terms and -conditions in CNRI's License Agreement. This Agreement together with -Python 1.6.1 may be located on the internet using the following -unique, persistent identifier (known as a handle): 1895.22/1013. This -Agreement may also be obtained from a proxy server on the internet -using the following URL: http://hdl.handle.net/1895.22/1013". - -3. In the event Licensee prepares a derivative work that is based on -or incorporates Python 1.6.1 or any part thereof, and wants to make -the derivative work available to others as provided herein, then -Licensee hereby agrees to include in any such work a brief summary of -the changes made to Python 1.6.1. - -4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" -basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND -DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT -INFRINGE ANY THIRD PARTY RIGHTS. - -5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, -OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material -breach of its terms and conditions. - -7. This License Agreement shall be governed by the federal -intellectual property law of the United States, including without -limitation the federal copyright law, and, to the extent such -U.S. federal law does not apply, by the law of the Commonwealth of -Virginia, excluding Virginia's conflict of law provisions. -Notwithstanding the foregoing, with regard to derivative works based -on Python 1.6.1 that incorporate non-separable material that was -previously distributed under the GNU General Public License (GPL), the -law of the Commonwealth of Virginia shall govern this License -Agreement only as to issues arising under or with respect to -Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this -License Agreement shall be deemed to create any relationship of -agency, partnership, or joint venture between CNRI and Licensee. This -License Agreement does not grant permission to use CNRI trademarks or -trade name in a trademark sense to endorse or promote products or -services of Licensee, or any third party. - -8. By clicking on the "ACCEPT" button where indicated, or by copying, -installing or otherwise using Python 1.6.1, Licensee agrees to be -bound by the terms and conditions of this License Agreement. - - ACCEPT - - -CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 --------------------------------------------------- - -Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, -The Netherlands. All rights reserved. - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Stichting Mathematisch -Centrum or CWI not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO -THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE -FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON DOCUMENTATION ----------------------------------------------------------------------- - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - - - -Additional Conditions for this Windows binary build ---------------------------------------------------- - -This program is linked with and uses Microsoft Distributable Code, -copyrighted by Microsoft Corporation. The Microsoft Distributable Code -is embedded in each .exe, .dll and .pyd file as a result of running -the code through a linker. - -If you further distribute programs that include the Microsoft -Distributable Code, you must comply with the restrictions on -distribution specified by Microsoft. In particular, you must require -distributors and external end users to agree to terms that protect the -Microsoft Distributable Code at least as much as Microsoft's own -requirements for the Distributable Code. See Microsoft's documentation -(included in its developer tools and on its website at microsoft.com) -for specific details. - -Redistribution of the Windows binary build of the Python interpreter -complies with this agreement, provided that you do not: - -- alter any copyright, trademark or patent notice in Microsoft's -Distributable Code; - -- use Microsoft's trademarks in your programs' names or in a way that -suggests your programs come from or are endorsed by Microsoft; - -- distribute Microsoft's Distributable Code to run on a platform other -than Microsoft operating systems, run-time technologies or application -platforms; or - -- include Microsoft Distributable Code in malicious, deceptive or -unlawful programs. - -These restrictions apply only to the Microsoft Distributable Code as -defined above, not to Python itself or any programs running on the -Python interpreter. The redistribution of the Python interpreter and -libraries is governed by the Python Software License included with this -file, or by other licenses as marked. - - - --------------------------------------------------------------------------- - -This program, "bzip2", the associated library "libbzip2", and all -documentation, are copyright (C) 1996-2019 Julian R Seward. All -rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - -3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - -4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS -OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Julian Seward, jseward@acm.org -bzip2/libbzip2 version 1.0.8 of 13 July 2019 - --------------------------------------------------------------------------- - -libffi - Copyright (c) 1996-2022 Anthony Green, Red Hat, Inc and others. -See source files for details. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -``Software''), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - -This software is copyrighted by the Regents of the University of -California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState -Corporation and other parties. The following terms apply to all files -associated with the software unless explicitly disclaimed in -individual files. - -The authors hereby grant permission to use, copy, modify, distribute, -and license this software and its documentation for any purpose, provided -that existing copyright notices are retained in all copies and that this -notice is included verbatim in any distributions. No written agreement, -license, or royalty fee is required for any of the authorized uses. -Modifications to this software may be copyrighted by their authors -and need not follow the licensing terms described here, provided that -the new terms are clearly indicated on the first page of each file where -they apply. - -IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY -FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES -ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY -DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE -IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE -NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR -MODIFICATIONS. - -GOVERNMENT USE: If you are acquiring this software on behalf of the -U.S. government, the Government shall have only "Restricted Rights" -in the software and related documentation as defined in the Federal -Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you -are acquiring the software on behalf of the Department of Defense, the -software shall be classified as "Commercial Computer Software" and the -Government shall have only "Restricted Rights" as defined in Clause -252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the -authors grant the U.S. Government and others acting in its behalf -permission to use and distribute the software in accordance with the -terms specified in this license. - -This software is copyrighted by the Regents of the University of -California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState -Corporation, Apple Inc. and other parties. The following terms apply to -all files associated with the software unless explicitly disclaimed in -individual files. - -The authors hereby grant permission to use, copy, modify, distribute, -and license this software and its documentation for any purpose, provided -that existing copyright notices are retained in all copies and that this -notice is included verbatim in any distributions. No written agreement, -license, or royalty fee is required for any of the authorized uses. -Modifications to this software may be copyrighted by their authors -and need not follow the licensing terms described here, provided that -the new terms are clearly indicated on the first page of each file where -they apply. - -IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY -FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES -ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY -DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE -IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE -NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR -MODIFICATIONS. - -GOVERNMENT USE: If you are acquiring this software on behalf of the -U.S. government, the Government shall have only "Restricted Rights" -in the software and related documentation as defined in the Federal -Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you -are acquiring the software on behalf of the Department of Defense, the -software shall be classified as "Commercial Computer Software" and the -Government shall have only "Restricted Rights" as defined in Clause -252.227-7013 (b) (3) of DFARs. Notwithstanding the foregoing, the -authors grant the U.S. Government and others acting in its behalf -permission to use and distribute the software in accordance with the -terms specified in this license. - -Copyright (c) 1993-1999 Ioi Kim Lam. -Copyright (c) 2000-2001 Tix Project Group. -Copyright (c) 2004 ActiveState - -This software is copyrighted by the above entities -and other parties. The following terms apply to all files associated -with the software unless explicitly disclaimed in individual files. - -The authors hereby grant permission to use, copy, modify, distribute, -and license this software and its documentation for any purpose, provided -that existing copyright notices are retained in all copies and that this -notice is included verbatim in any distributions. No written agreement, -license, or royalty fee is required for any of the authorized uses. -Modifications to this software may be copyrighted by their authors -and need not follow the licensing terms described here, provided that -the new terms are clearly indicated on the first page of each file where -they apply. - -IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY -FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES -ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY -DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE -IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE -NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR -MODIFICATIONS. - -GOVERNMENT USE: If you are acquiring this software on behalf of the -U.S. government, the Government shall have only "Restricted Rights" -in the software and related documentation as defined in the Federal -Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you -are acquiring the software on behalf of the Department of Defense, the -software shall be classified as "Commercial Computer Software" and the -Government shall have only "Restricted Rights" as defined in Clause -252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the -authors grant the U.S. Government and others acting in its behalf -permission to use and distribute the software in accordance with the -terms specified in this license. - ----------------------------------------------------------------------- - -Parts of this software are based on the Tcl/Tk software copyrighted by -the Regents of the University of California, Sun Microsystems, Inc., -and other parties. The original license terms of the Tcl/Tk software -distribution is included in the file docs/license.tcltk. - -Parts of this software are based on the HTML Library software -copyrighted by Sun Microsystems, Inc. The original license terms of -the HTML Library software distribution is included in the file -docs/license.html_lib. - diff --git a/desktop/python-embed/_asyncio.pyd b/desktop/python-embed/_asyncio.pyd deleted file mode 100644 index b85d1a1e0e6cf56051fc150b14a87eadc46fb30a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65304 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

    F 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 diff --git a/desktop/python-embed/_bz2.pyd b/desktop/python-embed/_bz2.pyd deleted file mode 100644 index 1ea30685c07965f01db931c7a27d593bf0828715..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84760 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 G{r>{hT77Q- diff --git a/desktop/python-embed/_decimal.pyd b/desktop/python-embed/_decimal.pyd deleted file mode 100644 index 87d5a98a9d0ff56f064bf982bbe593d760edc800..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 255768 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�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%0A@}F-deD1w|d!=!|Jt2P&J?^^SY~*}L;B#MK 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 diff --git a/desktop/python-embed/_hashlib.pyd b/desktop/python-embed/_hashlib.pyd deleted file mode 100644 index 3a0b447a2a22b46c471bdf0b59056de3197cf090..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65304 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 fmO9UWE~a#=&e;;F-sa# diff --git a/desktop/python-embed/_lzma.pyd b/desktop/python-embed/_lzma.pyd deleted file mode 100644 index ac25d2a221b87d76d9790d2e7f8cfdde4a6b04a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159512 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 BII92v diff --git a/desktop/python-embed/_msi.pyd b/desktop/python-embed/_msi.pyd deleted file mode 100644 index 714866f7237e5c0b3de93c0796f242e8710d5609..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44824 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 #Y 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 CuJGLe diff --git a/desktop/python-embed/_multiprocessing.pyd b/desktop/python-embed/_multiprocessing.pyd deleted file mode 100644 index e74017f0fdb9de13de2a9f25605aafa5f17f77a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34584 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 diff --git a/desktop/python-embed/_overlapped.pyd b/desktop/python-embed/_overlapped.pyd deleted file mode 100644 index dc1475dbaf8c31d083095137c1c954c39d7e5ba6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51480 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 N{bC~#cWodc{SSpXl{)|c diff --git a/desktop/python-embed/_queue.pyd b/desktop/python-embed/_queue.pyd deleted file mode 100644 index 343b86f932730c5de28d2f2612da256a2f555ed3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32024 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 XzvgSb55GE**ZkYPb;`x^zX|wXO66eV diff --git a/desktop/python-embed/_socket.pyd b/desktop/python-embed/_socket.pyd deleted file mode 100644 index fcf2c3613b5c188cdf93bc14f5a953d41d091766..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79640 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 eMAnXC1_k7hsn3rUDx`1hP>T_uGIQ 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

    uIeRt`cGT6J}#9LmzP6K-)V9b^*ufcb$v!;5e=q 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 diff --git a/desktop/python-embed/_uuid.pyd b/desktop/python-embed/_uuid.pyd deleted file mode 100644 index 082d9ec0cfd5d24701d208476d37bac7c254b03e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25368 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 Tuc4Yw)HmCj6mRqo9Ps=fzJAi^ diff --git a/desktop/python-embed/_zoneinfo.pyd b/desktop/python-embed/_zoneinfo.pyd deleted file mode 100644 index f7cc46352d531b55822492292a440ef0fe84e745..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45848 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�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 diff --git a/desktop/python-embed/libcrypto-3.dll b/desktop/python-embed/libcrypto-3.dll deleted file mode 100644 index dd511fb26119f5d61c1225fb98ad3e3ded63de00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5191960 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 z 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 W6?t;|?R|dn?SFaZ{QtK7@c0AkE&ul6f*S9T zH$J=X%0<^cd+=6E_W9qKa>v}<_fBqWeC3~3_$-s}9+-Y#zIJi$*dbqY-a5=OwNJsm z^4(8Acj%`rb1r=RE0zzQ{?%P+mn>fE`Q`2Tmu+5Wac?tZob|gkmP^MxtBv3CmFIsF+Ir8z+t!Vr`cN@Ge~~|R z&a9H+2a9KVXLqq~nm6;2sW#Vxv!;~HnQqIxtN6j$_-w|*wsEs(&Ye1^XlC&fBRj5^ zs*V@a9Pj`ypV|89oNwtLRWL83el^)w6|iJVK;ZJt%W(Pd(FJ|svvN7Xy1R14a{lW;w9YC(n1%RUR#Km48y^ zE6c2 zZ@3QEKQs;RY@90ao<#oG&hPwr!1w?v9XeXKHaKPeJ>$zl2kSNltLK-x%R+nW>gl_q zDzu|+4}JFpLYwOj()VCEw7#yDzLB9&9oRI#^f6n|c|%=*-X|Qw)}V8Ksk0#TYRk=K z%=>|=(1Oz23WC)oE$f1)qsI>J%xc-F{8ho~sV&=-ADK*Q*`@s9VD-3`{qzsA2dnd1 z4y#~WusXNpgz}@b8(LNh`2iJD;PJIPWxA`8_3gj~%x?s5nt#vaDj_X&vaZ|#SqfH< zYC)xs*7*wbCsh1k-CbpTftv5FyRV8~RDDO?Ljih6f*p^9>3hrueq_`4gaZtD61*7I z;w)e>69SP9<4?WIx-ex-oWl`Yed->ka2p!3R>$Kah>*Ff(~WId^FFTD>U?{Rep z=>0b84u45ypkUXM%I!c zYN6+c_aK}3f%eB7Xvn(NtdU!)aUt5R4o!w^9}2*EB+ME}E-j>m8Rpit(>s#6goHpF zb3ul9j|@xd-XpDdNQRT~ZdTph_9|qSjsGWYAolAq0#IR=4^mj+lDhTuK8Q@nF;I1n zVlD!v*4=LpK(vI%qYGUA`!Ybvd;M5Ii!O>Tywx*HGD}$rIn_8cy zx5})#O`&%5PB_n!K9>*Y*?o80v32f#J2uWeY#$B+Jg7jsm$K!BY_)qS30_D-yB95p zn{Pe78twPhSEB!17J6cK*yXErYrlsQL^s&uNvm<;!}WMx;;wGI)RTryfAY9AFKvS- zZ7bf4TjojI<@T*K@^HS5Ib%!HS337!2^ht(^*>D78eH~=giqwRLwM5vp(MJ||UvH*89#+># zZf|0qP;5wUogRGf_<{)fC&hhg9aOxLOP12?b$dTq%k}@WIQhLpF^nki`dW+0&DS4T}<03|jh=`No_t0Or@?A-WNl>SY zq_PK)^i9wT5G_rHk>_+x+Q6Sf72djAwX!wP-iV1QkO?(QHfN z&6ZntnAy0}?zRsPR^L$9u2O!N6+1rrU5{^rK*>-hpl=SsJGE{*dA9dl77I0YOIa{pHlA;3W(m}tSH*JdIJ&yPD4Rqdsvz?h|C z0A0RgPJEVp@gFgf8v5*UmoKDc3TD?b1+rrmLm)eT1+wE;AUl2qvg5a437i?r;1s?L zXCCgx>UcrS3|tU1kr%`yOq(k^V63rrunO{My!&#;AK(jzAo%R*bSUfg&Z7Rdd9>e;U*dss1SF|(YQGPN zruX>j@#2A{o-~0eyYVm$D1vYW>feb5|HUEQ+9)1kV$YuF9_R8 zBLe>&L^r@XQ0p_RXcRY5U#}0n)Z#<~)YT%KfFJ4+K7ewnNW4Q6)J6DC=xJeU(DU8Y zeNd$s2Ox?xg-VD4n87vB0G3Z%rayzGt$3cj0{Du_-}{U_WGNpBBS9d!2t;vd%PwJC zyZ7d;r0`uLmi@v!X4pm!Zie=2S;_o{hxXRNa551Ru=K-M@{Ymu=N)ewH_)p&3P!5f(hn!!}Sw)riqgsI4S zrnET=+Rd~=G0@1cmL|M>a5!1DLlQ7<4qHAJS187aOOHEGWWb2~?*g761rl8vUt$tt ztY`I?8q5c5L*CPtV>eDrRLNnGzgw|`f(iE3QaYL4t{|n8nKX-t3R9SeKo22T_?=~t zEBwwEX^q7#jFHQ@|4Fb!p;h@)RwX7&8aLb^+6kf!0VYWgE+<<-=q`bx34D!FD}0R; zDtwI-%DT^t5h`)xgi72vp^W?QWGb7gg!q3bEe!3F*IU|vu1Z!RK(@MMR#MK**GCCfp>M(#?dMLZ);x;iix&-AuSiGV^@zf>P;hyFF=~I=Ml0 zG{DZ|vyt?>bs>S1Kf@icp%?1X?Z7(*3jDb-hzz}|qd-7CL4hynC=fVDp}m7H=POnfXcW%Dt%8|7FO~oi zyuZB)4yI@X1-=kNfj^I-z*lt?NDdGMzNDi-av%W(f&&H$Bt1f#jsg{J(6k0iI0>V( z1STd36iAlHU=rgPu*5*4UoIU0h+vEt5)CK_CyoL+XZs~0zooA7{bjD~fX8=Jna6kQ z5|8iBrS9r5W^_NgG>_Mw?z#@jtFJpP0PNsS!*0e+7FT5o2J}d=3@NG*`@%fm1|+x^ zmSm6~vwS0>IWu4)J-&NiM%?AtK{+JPSA*!+z>I$ddYw_rH!z;n?E^5m6Y%xk0E!%# z=Uav7neOTchV3gEwY-+`hP!>B^wt{0twmhmfsgti{uL_z-@7+NbSh&hF!jI`VWfy4 z_9d!L-$$MLnJeVPaYxpu8FAY{;svTk*{IRrgc@Z@jV?yi3{YrQ6&i&K4Na&}j;au* zd+r?$0tYApzkv!}lu#juBF_f$G7&cmB&H+&pUX@ zo=Tue-<@c^Y7lav3R#A?8?N?^T&wK}D9L;t~}SCKcaTWkx_nj-uiM71B&9 zvQ<89pu(Z3uu8}f5-~~@nE@hPiiiO!#L8m7p$Zv}V)Iq8=_&-(`4DWoT*b{K5jUzL zvp~c|MZ{NCNDhg}QA9W>HHwH~D#S%9zN7NV2Ng3E6`Bf}NGh&YWfp*nLPbS?6*7b6 zeqEJPh;rwta??}@o>ro{Y!X+HItjT!iv6ir>g<3bxCa0(0H@Q&>l?YvtX1IIA-J2j$sUSC=ktmZ^&^?YwCom*{mf9Sx}{H|EIny4x0p;F+a*@7(&)-G)-$nVO+V_S=q1-Fm4~DKpd6%{y z4P82SPiR>C$E_vWUi z(Bk@EF>ln3@`LQcl0BpG^^T^!!QJz}zc(ecq3J+ySMK*Xn=lerw%cSDsg<)BYC0kX zGUe1V|9c`t0>6LaI&ZF)Sxy1N?`=!q+_enOeJ{g#Xa$@{YTy)Yh4W;@?H>WDHRgYO zeRe(LvbE%E# z2YNZs%Yj}F{H<~zJAk8T1COlwTdm*e>ec=FYkcn~7BxA*o#xVJuXFh>aQSY|a8>@; zUWPE|p9t8;jJS08Q!a~h;im%MD@FkIHl-{bQ(0l>;MwKdhW(zdW4k;)EPUN;#kpwL zF-&-4tI^GvFTh89Fr&wSS_IfUm>T3vAOo=R=H^W7sc@Iqsemv7Fm15kUA|cbV3Wwr zIUe6(clie@pqZ;X%rJXxUK%D$PPjM^cr5Hj?lL2Y?{DB%u?(cMx{mEtg$^f)QYZpg zsEt{8((29OEIU($?>2{%ge(=_WDW-yrFw^R=UzKpE-WG&MD8(T@2?fZMdrKVO-UQX)?5R8Vku^;)}>DlxxtlN`EEcHJC(H?0P50u7i-8yrHdecA@%MZSo8~%pgzYqxLLMWwAZS zO(BvBDMrb2O}rr7J0}eE_?qQaEoS~ySvUfx*ZmX(GH+(aa(&BF<=r{fW)M0+2G+ z0tIY=86r{#M=f}|Et|72XFwj@j2)Q{XDp#AE;Q?1gHF|6)m$hIORy|c&jV>U~tN( ztq%;J=FxImvFrIr>u+sPCGuFySO1x5JbuWxbF<`CSlmWNSdb(BW^qpjcYWG=!sXip zJ|4+KmH`P~bHoMzdJq8DRf*k{sCNeA{sy(S9AV+L60<%yWmW6V!zEr$~-2~jx*X%V&t|-%xcLk zN20Bfko9p|*W>2K;RaLdg_Ko7=pKo=RcA06`LSYiTv0F=oqs0Aj92_SB?PUMI9XD* zYO;4o&3Hx4`%=c{I5nF=jm==&K@;0rC1%9Lwqpj{3|+x|A5dklk+R=mzGGF{HIjaV z#8G8$k&qoyHcC|qcNm;FW#WXQyUoOjH3laP-N9Ub6Jxtc;(i;GlATiC-gsU2qSP#- zu1Q2h;&0JwOaT`WQL05cP%P`Pu=k*04efRzG$C8(L+@>8e|zw zAjMB}gNTq+eH+{bSiPPjYLPw9b zxpjTM-#9;$6hE=fv)6h6j9BLwdfGN8hMtPuF5ks2-~Px0AUDpY9=enRe7%#W-r;#ow(-OBmOTq0IKe#| z7k79EPk?#DZ=b*CFYc=j@Clccc=1)+cHVL`H-Lwoc;J_I=i(Y7e2!ad=T#$fYw>_v zSK9fh>AAQ82p@;j+7Iv{49`(|BJl9*(Q}*WwDESDR64k{2kxCVy7y+m#W!)`o#LRE zpL+HFFrQw2<`qZH>E$P0y+6VV&hN@lNrvp9!*8mp&#>~d4NWWQyhA5QhaYxsT21GD zI{d0_VGTcH+*BQt)~gF+(yCQFjv4T29&N!YL#SPqZz`Nn1d&(pxV zxEjAwz&!yU#{#lYe=f%ZxK{XtyL=1868CYu$r=9G_x-%NWQ;dYxGP^l@#13)U{HX; zQyugQcX1s&yu#g*0(ynJ^TFL$&klEmhcUincq;pWPj2o_Fj!+Hg3RMK%Q(ww!NcJy ze4TkDwH4tu6%O1NA5eu6E`x-;G;GR`kE=L%5L}*@w%0toij86N(mpYdvVeg5s_c)& zm|L20YOS{T->_Ij;wx`Q9VTGFG8wlxPq%q0y|}~qalmqXzu2csi0>7Vke=$cSNd2i zjpHG2#(hE%yOmvuU2w|o*1oRFOYGUFXzj*kFkrkDYzFvah>k6RCw8|^vq`uB%h{RY z2jJTsLzN~x*(7h9r@L{57xOyhT2p--D^N{CI;ydy6rsN=`NHwLPg|dc{L`@Hv~CqE z4|qrRNM!;NvW_7-t7;@<6GMJOWGT^VC2%_fbc%E93}lo?+EK zuV~$YQOTKDxfF<^Vdbzxek(S}N3cuY(FVtr0VjVroQaum3Uc7gaKR~@2xs05To14u z4C!jA?)3ZVjrGqnvX8mGwfa2H?f&!{!VtkC>wwB;*Ba9~E?+dJ>ING!R5O!G8_xD@l1_o?5Rfh6_i0wn~kM>zyWG5)@VJIeLa;w zDPuEK{(`38Q~8@R`S~rEbUl^-StdVka6#8o`F0t8jP~wn!!7NyeG*X1G7#bGvvr0G zmU6$*5V#8;S94+dYAiOx$bxLM*l#LXAC z;7U%)-9V>!aD)&YH`wX?SI|3hm(;v_oqeY8cnrbzR_w5SUY`TZwY-_Z!u!YZ9Uy@( zH^Y5wYX?)8+l8si?ZVXM8m7+Wdrg%FO9`_lrV}PFS4o{e& z-Z8ZC?$$|aYGjk4ig&lZWCMG7QqiXmAmtTCjJsQ()7wA{+$?3_ObYt-xPp%B=lQVH zn@rldUHt8=>}aX%($koE4;ba~<*|L;$2NFI0Jx09cCxkZV;eobNy9xOHn@)goJ_^8 zs}J4B>O8(#*yi?;``BiWuO!PeqS1Zq1CMV$c7q*qAKT&?aom&E&odOLVkl6>P@syT zKovuQDux183@yz$4K+sN#H0`V`-le#WC%_B0Rf?}eQD5iRt7G*($T5D|I3AgI)Ckm z(B+?%5u1BQ-{=Arej5^VrVX@ILAW*5*!-?zI3Na0&k2yjy|L^((2GNL21-V5WdA}ew(vLlE04K zbYjs!4i6?#f!935YnaC-Xe*F;X@WN3wPO1`4+e>4$U%Cgp)aukvf8P%rF?(g<>U58 ztTl1tBV#*Htu5Kl>mw`h0A086z{~j2MqX>zMm}Y?Vz54j7dei^!~k4;{1@*1yvT7R z5F=ca4)-;C8B)RXmW)0yww=u(`{4Pog81z-mA~hFWUp6rAdrz!AC4Ek@L*qdFLHqT z#RmJx;RCSUjXMsY@TWlhv`nx$Q`np-Y|a!m$|@;+}yie?sUuBz3+QD(93~d4)k)M zmjk^VNWuZ&=Ou(pYpMb7umE~3PQ^8*x%@v^j8GhNtNDNIy$M{*+y6iQ?iNB!$h9*F z5s9&6Z z6s~*k=idM4_kDbL=soY{oY#4s*LiJcdmXvPR!g_in4B)28k^G67=0HHO-&7ZS6?fQ z$?rnj(qmG(NbA3qUdC+WMQO~F&eHmM(wMYwq#`VZxhIWz+DR(9ER9Jwmx@kHMM(;E zn)I}VEx}NTo>4c!QlWlLJq2rp=nZudswzb1*eU^qD2cw?DMab?-BBUBNZ*|lqHENj za8`(3u(4s59>c>deSqx%mOjMR2j@)EcYk0<`Gce}85RTp8~kz@k{K4S1v4z(ARScz zU!`iR5A;!eQ;O}9NQ3WIZ-9J9sR+}5!MWI;n#mH1k_=fePKVW6CfTe^vb8c~`{v8p zY)rB>HDojYa<-Z#*=!BjEWVu0)+Ad^L$(rM&eqfmL zNCUQ~Kza*4!wpL?54{5uosx>KOJ~Lr_o72#>`zFs0!&?bZf_|k6C8a|H`p7g$HmeB z_gOZ|jkd%|qUhqK;4clwYe-_y;lnW_0v%3_X)j5_Q+vr{PS8I^&>wG=&(Y!^aK1$F z9b9yDSb`Se#Vg=XY>o3OXm1>Ce3D}c1C8j@c<*FsB;WC&ZZ7)2;6^rIA;q0P4PRhY zmE2ZHORF#+h7$*fK{0lPUX<)~G{Ro;BY0`4-Uup5iyf>fX;rBjNu}xlTjx|)_Mu=E zqr}#Z-aAP}ltM%)Y$=7hCgxfpTNIneT8h}24&hfporag!B^#Qe!K zYtcVss_`E?vsT#dYlrOa+7Ra!4EISunmqvu225k{v_)`a&IWYJuehJBhkh zV^2)ibhsv%vmS#M_)Lom1hXqxVuE@h-asW`{-bc3N0xmPJ8?ZUea>T@=}pD(hF=OLUA6l#ofkbIX^h_VzS zj0|FR^+QCild8=y>F|tAePBs2p0QM$&4oNexJ$G2CTt$g2p@}P-PIO)eljB+yW#21 zBQoFv20os#f#)0ej>uP7c7WViUw|d4iVnGfid!XC~ zypNmW{V{+7#1-a<3&u!Mh`*x4OTn!6&^I8tRE@A%>Rk647BAf+EwbI!k~fxAM_K-* zP~^P9Nl%|d%6zHl1~m{;s;!X9=8d%eIcfa_k4U%_WiNv=*(_It&MfqfyE^2&rSx<( z4TfQQF9Fkh7;_qju_wP&EC$b%s)r)fT0_%NYk!`9!Dg8LD_Ebu4ea_U=ENH9KW5Hv z(krkH;U6)jd*t-<)_;dHrC6X(3tVnU)nWsy5|>G7o(&81i8ajMqX{kORvOt6@lKzm z8|OzTV*;q3n@L}dTo0y}=yT{zVLN^R4GjfRdiIs)XOv_V0+d9#P?tgp0C-*kia=+W znm`A#CeZn>z}ch(iJswTQUqG|8H7nNt2J@TKU5XN1dK^BOqNCY4B6{Ux*?JsKM>;? zcXgjEJNFs^FRQvo4$iiAj||AJ z>RvEUioD2pJ&6u5(B?AH9I-1;dxaJdaa$L|O z4r&uGpA&MTXf|I5kK76!Hl+>D=}SJ3KROI?umvrDu)vXU>GAm1r<66^b1O=L1Jfvl zN66gVvATlzrLf;e}MB)sAyf(m&JUnni5d79-6`OXsP-+ zjJe$YE<6DWdavk^G{H`0pYE;+P(-J9ELLK%M-PpSg1QVWF?kcGV_`fHm!#`0fRIK! zj)v1Ax4&cXGGrQCduDh$Jf38MH6X12!uuDn#(1ftI6m-H(Ca`41uhUZ2$r?-Epv(b zP`A`299*Sb;gXWj>ZyJ0^73Vxny}RHl`c~c?UFPmw?w)yHNh<}-(6EvfF;o~(=P`7 zEmzlvL%WH(;U7%1N*$Ar#EwOsg8mkBKN+rac zXef3kfp;`D%erei3JB9P3{yeSS#+U7Z0*wFh0!5+IR1_xgEt!CPl*SW5M0p>oTloQ zN&HcXZY7m)KM{TWWYjnrC*dXIZE`9PGabFb^mK60s1#h3m_?2ehOYZ-*1A~ZVgC6~ z*zY3zL(D^wI_)omXVB<2htbC2pKW97^g4W*Mt`r+bQ{_m3{*xQX=RIHpAysswU$Ms znNjmsCDeExp#G_2y3I$}!@rekrdncwxl}{*yXyG32gkBX#`$i{nrKP(91t*7zdCE2 zwW87!+OLOk6$Jhy;QZ#EiB+*uMXH%7WK+kf?E01_r7NH{ow9P+WHVcN=*6#xFa3=D|;hE`{MtZPp*cr4Vt0dd-ag9fw zhZgr>b(X6&d;cWPcS+X7s)+MySXpDhm2hXQMZ1Bn6Xxw$ULMbT^kNE+Igi^@_6AJc zn_oJb0u=dGI6C%)$9gyqJ(VqqG+;e8Q<{HCFsD126{fX8TY05Cg?YB32G&&s=Rll` zwl&+Ipsqq|N~HFg^2iRXm8AA(XrEPW5jN0am8Uw(&yp1bVW2wPjq{B_d$Cs_9=&?X z9)@SKie<2e4A!&?V{4i;CQHO4K9=7*^p1sBQ_HgNvEkX&5+o_YbU`s5 zk*jOS)x)8G$3p)G8}x5Ad5vLEzoVgk$Kw^rOdTxXhWb^aWhNQa@0n1nO}_^Xz)E^Y zrU56j!cY{dU$dw`r+@#f&P6mqVdze2WTn5Rb`{ETA)}OmBPUGx&xWUqKKzD@G zN>Y<}K*6q3wX+=y(f$AQT80u0zYdN4SI5D=7XFn2Un%gvM}a@l|0o#$rUCBI@)-GU z?j+^XM$@hh*!OXmcq;7QQs0qAxtE?#rKy^~F_wraoklItp=IOTnhoJ76x$%NC=wTU zYZ^b_DvNl4j#^L#2k+uO{`hT|f{EHuctDpQ+b#tYFCc@eYY^VxfOhP?6imEIZx%3s z0wu-{^q4lBNGGAI7SrlPq{Q?d_HP0Zy}G6VZSkZF*&UUU8$K85p7m1~pEi)BV?HTeJ~C+V}|6f z&bP4f?1Fg}8rJ=T$riSL+8vTeKB1I}jP4N}^b8`9gl|f@X;ZRB6eM>I$DoHhBs)C? zH@(*31{3AU1NY#Dje+p_S?kG7TMzj&k+5qtegw16 zRWhBu8bzaGSeztdL#k`!(bNG}KbPCzGZ|8?%!X8VD(GW+VhPwrpwWeJ)P z>`c?ZhT-i3`}&c7VUwzu ztjxq@6w7EVoTi97n@$lcBF7cZ5F^J&(~F%+85^cmWsx(ON;ZIJ6Q)HV^RtEgA_71z zoE|lF#!?h5v(Hde%9oYRm)f81uBlmGuC6Q9G{$@<&4ALVyR$6+Jm&1M zxf$c^nA22;RZW|X7)@V}AH~+6!Tmv>`WqUfQm4^f8@d}$cTMST6y4RMyCHN}6?Y_M zY+m_+RIR6#uy%4BK_N`NokgzRUw5(!{432EAv0BKgk%hHNO9LpmpcKzLn?NLH;0@I zc7UGGk!3$&OY0Ey@)l-Eo2SwXTCl{2ii{lG9H|m1HIhC>q)U7uanUF^mJ(}fC@Tdu zRhVC)A3zc0q{Bh12{ZW=-3FF|MdK-itsYz+EW?7MD$MUtj8vAEL658{U?PG^Rl6jtUZ%wq!bW+3^>G1JKU=_H0f6ygR$+7tN-0_ZtA{iqm*e9f7|PQGGSy{R1SpSe zj*_L3{VhK+|MUf-gVu)1k#-`|Q~5=xZ_ZPn$b&5d%`}#U zE*Cl*@EKz;Bw4S&kdV>{EoSRFDkQ7qXnPlEC#AH(hYmLDI^pYaX`v4DgFZX zazHtHTY742`{B?dY%gi*h0}t%D9U0LYkwT0^qOM#X5T}as@Tp?`EqDMNTp{`xBX~c z2xh?fj24EBI2NqG&@`i+v=XG%!a*A8ZB1cY!JzU;x2nj9>2c@us>S@q0)O(;IAxlG z&MCxcR7xRIsh>g$N0}8?#w_EU)ZCrBUdBp2bh8JfErOh)Ji+K8c{#gh$R+@rE4nZQF2JS;1_J~pzthw3;~Lr z@rC#@6mkJz;tN91L6f>v<=u>UW?Brg!h9bv5g%!Wk0fJUV9dUOGhOWXjKu@1{X-FE z9LN>Y1UiFwv}(^<+9AN!QV_YQzh&PyygyAO5&-6E!g zC7OZ7cBBwL5hD*wE$#45Fe@95=Et#X*m?oP&cWCfTV6+SFG;g+&@cAj<(Bx^?M#RK zU~!#^BT9?w5O@a>cMxia#n?%a*H4w#&y?4PioYeVR9{{R%kwH>d0wSyRiSU#3O%NB z6N|6L+sM0qMdEqB7hq?ZzX1<6D z1#^D0j8k8KF!Loyb^~>jJuy#^+@EF-RP1mxJbBYZ0Y9lEP>u>m6DXr_>Awz%Xs%13 z^xi|ae|Dw|K%xmq0s%>(octUY;AAp5(X36sIKzdds|3cHzz7)_Hi8E*jttD7o!QbA z&TL6FCyWzYaEJyYmZHf5PCrZZZ)iy(&LF6iLJE%_CRR1B`Ln|cPFlN(5kD-a{nP@^ zKe5b@tx5aCwSGm``LUH~SmsxzP(QQp|M%8!BEme@Zeoh2B-U>d6|AL|GT0){@7EgDKsJ zF+B?zbCxqpY+%dZ7(CJ*JZ>&zYhS^;e|qt2oNqeV-gF5p zy7gAj*oH-|##OHT3fBVhAlVSHWwO>JI29P9eqq%sOH+Ieb5R*dp(V|%s61N8OykAr zHHvp$O#GMs8|z^m^gp|dQiVihcjlR=DRc~A((2>=Kp}Ka6 zX8sX{3;aV`;x5HLZ)>TMdOn?!esbQef>XXtJ?-5sYpFS^^0I~=!*!8>wKjU#y&#!J2R_eSsx z{uLWPaMv^~PhJxm0<&D{_9py~TL&YpI%A6mbd|~tx=Q6Hq>Ce6pm$Vm&^szOAG!oV zZG;17_+`$a=Wy5&?YF=IJ)%bnQ3mbh6rm4>Q45H7I*vLxmgQ>6mdVF3u}p}2@T+mt zKsF@*` zlA@-#$?AUmwgNu%ULK-fI-_rmUYw^j0^9;O!fdED!=@_BAIl)(M2j6baf7`%$KC*A zpkil4FvPsLIgb z3pGW9uc|2;j)iE@)`L5=dt^72*cnCg;ZBoTG5l_YCn&}a#W=Ed;CC5hFa%KlUvZX) zNzKnt%?-5VgQ#Ai%^rS4ON=K>v}5`B=DC6Gw>;JFu+kp0Z;w%$6H0TAi~Tk0lpJRj zG4Szmu{*Nvv2+RSMN(Ys#;jdLCQ#51LsJO1jvNG9ce&@kkX$Pno!R*r5TrR~TgVQlN@C@YYJh>VyOx~8Kl>PMY z!G634AUvuM!lU{lJZcaaWU^G_VBl?O4XC?*(X>#ZD!Fh%Y_I#|{vJcXNf#P`FA^=h zczoLT#`v@*u_g`iX-)R*Y!*`c60Rm@E|90ZNif<_M`>iuOUICwPizt>^LL*8`dqYR zV0iX_&+gxkVsSEM#*qM?Kr}{T9nxQFkF$>asM0KLDR%vQBw03~1S*M=8I983@WTRR z2aM{3^}or+GssjYOfsSC#vtQNlW+L}=~6V>|IwfUHvP_y#*ri7CJe2}Ah$HO)sr6w zPI{90~8sl zDNIe$=qejzg^pyBj8mjWp*$r7^L^GW_UaMFBAl{f5q`ToLKt9>V1*Dr>{AB&ggoAM z6eKs&n;nnDXG>(?VEX#d)Wax89z1(_2L)ho&W%PJKUGkl^4LiNTd(f#T&x%=a$)P4 zw_PE6hH@S{5Q0FA$1K@c(5N0LYyh%>bG)%wM&%rpCM3t1Ds{*7JyGi_ji0fB!alZ6 z?izVHNCGn-tTO|m6^uWAJnk5aF-8pgnGQeFUP&6O!QNS(=L+|i6_uZY_|6Zr4D!Rj z!9J}2IKDH2$kj@S=a_!B{y8EK$zKpj#y=~kvfRFpovQut*2>wj3ke2NrH&xeDr*cV={=t&C! zL-tC~l#85bLZhz1E>e3IPzMwta(rq0kN5*bh)6>SBc2dxbZ9vnUj+YrafFcyLm9lR zBLuco9mT3Q@(!7vp?azDl7%#yH=oSE+Hn^Iv7g`G&v3*dk^GFnOUw zKX?+@Mg@&m51aypHwM!=(elU%(1lZ>AbPQ#zFROUfPuv*xu$|#<7K9fk9lShabKVj z=S1X|RS4XY1a4=J-KYj(Ep~RQJSb2ef7Zp=@Q5h+`7YftMqmnNc8N zVn+NkDs}#;;1T6vS>Md(mc;y;65o^Qjd(-@H{-A-*0B6ep;<|cBh}2drQd=9IwUAq ze~0_RRcHd0b2wfUuJ;zGq)~WLxYk>s>ah+l3fGPcR0H-DhY?*IMnZ8IDaB!A7K6bR z2Vq?tgs?aW$6_Fyor}ZhQ5=R34?{H|=%e{x(}hLd!a-MM_b9sdUWc(bPzkq#_TZN2 z!`34cUD$eJqDSG1;BL_@ZvxAkLV4MXL79{{!I&2x_`G;snAeDGP8uEJFAPSQu8@%vnvWV5;y-eN@UKPd zqV+3(ZNH*m)=c1Jx@WQFC-yA*U<=5ZBo@_cQu!jABrX1L>}G76;m#eV){sWTIj%QW@Rb5zDe#p7Un%ha7zGZ8 zqnlIlAYLpum)ac#;U)jVCDH{C=UgHc7A}!}EnOmqSjp8C-!z1R-eTT@ z!fsckp=t~;kDviwnr+5cgdWEj72>bCh|0T&TrFHgLoHoI{j8$Ih}R+#m6H4j$uh+#HrJyZX>l@kyJI$OG9kRv5=4ubCkow~K(c-d6m!l=3M2YB( zxPH92?9Izad=lJ}=8GX^zbKw##P|vxQb$YF=Ok*}+%od>KO>LtczN{3$_<64RhR#+ zJm!FMAN~a%&IH^y|9ZQpqLk-F+x=gtOA1PP^sm?D21>d8uh%63rCj;f>v9IAoG)4z z$YV5<$8RBy79qBOD2~G+j+oyOlX^|!TU4Tsk*MP(>I8{8*(i^nwtq(BCsAYl!7~%_ z;%%M5y788cgOP)E8v^Ur*Ge`spA2qDZwVrM!$#WRMKrxA17legxof6dxu_Fd)HlW1 ziQ?>}0!zum5(1VjVA%myQx}l}<`1w%fGz54CD*ieK!_sP;ZgVzt80To7XJdTLfN@m z{p;<^ta#D(EneY&p>F>*8*g9?!JK4_n=3TCh)ZNKDMDGy1EHd9jG}CkOzjdbQxBQ1 zh;)fkMD|@NS7Sah1$!XRAr?jp>=$bxD;pz?c_@&TO_oKvtdm6!*{V?A01yEdo*B~s z7C;IB4{-JX&fzbliAI_;d|9>mvg)C%dVE>6`Lb{*ixBOk<5SSj0_qsmIf$HsI9e=~9oUix6dD)yW^iaReME z9!>=w4#S6sQ-O!$3^>xm!#^}w-+{W-)^rd9}L>b`agoN2AVY1W@)??SewW2eB@1uQEoi=E^Tz}88!NCnus zFWCC7EanN=`cffVzm&y11zW#YM23Q`!w$>Y@l~IN6Ad_L_~xt4Hy>kbzWKlnBpwN9 zz8gFnG~-#W5?G}Y&vMOpmP-K}fOQEUz#)7La0nm3A$-8PVFuRythjPK>r&kzW>j~B zm{Hv!W>j~uZeIiIeirAyz`BGp_J|VBP&4UJGlVmK2xqWvn3ShsJsuw>CVX2!`U#&N zz-ItocZdMNX-*=^!+{7893Q~(=V=Hyq^b;XNL2w2sj48 z=8!&AL@t|;pTico{P}JozoOxD>l@Tj=R2tUeq6UNc)NT+>ePeBXL+VIZ>u|1QKu{tLoC4*zG(n$?tRO8=Yw%KiE)_x$)#)*qMvcko^g*KKi>T~t$b93g*8Ox0wizNMBI2RYL zb?erfxy_rA^jQX%k-=G6S$T4vp2)Jh7FVklCl-qrbBh-vYyG+0+_{`ir~8Hb)Dh0{rBGkxPSl@ zJy*@C)!gC3hgWf{Rsn@y-gEEYa|;(P+{5kJ15~Dma3LXFdV0D&XKxRb>SS`6ncT&T z7iV*`X9Km)_qcoaI7dgvbKJReK=F1fu2n0}+uM60H*q3R9U905269@hb{n^C8&EEL znY(u-sR%s<126#DxfM?TXHR1a&B&J zYq&LQP^BTgx!%3GPMtcv;$FQ%)o$uJy`D2OGrPoHx`ZkYJjtCr$z8j4Z7Mf)DyrJk zmb10x`t|FV%B7~F$^kx{j}NC%C`NOmN2BWM?cDb5T)A@P)^Y3Bfds48bL-dBig{no z*B7LC--qkdhr_r}ZLW50kYrB^my*IYYu0Q8H(~@x6JpI-TXPjFR%DE2Z*RYm+qjVv z3WcFuXedaPxqw@+fZMxw?-TCH6Oe3nX|8l>?uQ?KxWnDK1Jd1_$IY9^$>s70E+PUX zJa>V+aDj`Bjg8`>qCm=4!CY`KH)F<(EG{bxB%QdHTf3GkQKG~N?!*a@Hn11hs~30Z z(4iaLjT<2GwlmzBGhB-nElzQ#PJz^yXL2)Va#gBSQF2NpNN!Pyt5k`*e*OAzZuoGJ z-X@JpOXCI%7_f!gvIR}h{wMCIpSWSehW*C<_8XewZey--W3EPx8o69x5(KIb5bCV}?0)e0;SF$9UXw6gZ=~M38Z@(SSjUSJu>V1W~a)ql}wdxLT z#||{vtNGmg`CPqv^)#GDgQn9@;3iDqBofIH?#K}|;iVidCx_d&Z{JRC=T0=`$u?Y@ zHr#;&2byqAnxILicH}yC0FC%sD%AmX?-DTv8I6IQ1BJ>=?Io>(*{u zw{B=^pUPb2%G`$!A9iuOcA?2fPvRy`;(GMx5zd8&qv^NLg79+*2?@_3^k9K?jUen? zSXkI&2sv0`{Tv847a1AZ8bS@0@U?<4b1PP?5JQN;8hvySUT)B!K}#UCV3FF@AgtW7 zWy|V9NWm&8c#62izOCMNz4Aq4AKABOO8adB}AA#}t;=@2$fDwSS@ zkb#vpIzqU(?CflB2o+c=R10C^l9Q9GLx{jy3+_XBICFFJcnA$x?1>wMg}Zg@RwoDv zSgo`fgoEqSrOP!41z7G*KL`W2bm>wBgaE8JuN;`48$5WhADA927;zrV&VBREH_gE0 zV8sg+!Q7m?ySorf4VH}B3ufj-BGC_EVz6eg9L&pM(Pb={7A%@I1I)_3e*L-xm=vtK z_7IqpQ>j!fz?5Lw6IH;B+=B-Xu7e4|y1fQ~`MA}qR}TZzfrW3>0JCuo8#b&7CIc&< z5rDb4wr$&f3#I}~pQ;LG;yQHbP!CK5)}AQ=^Ki?TFW(2I0gEdSfLXZi-McRWlYrGL zS%NvZx$J~w5`lrS_pL|{uK8k_s>yYE(@ks%5{ z4MO8`hX|E)2eG*^W5$R;WQfw! zQ6Mho>gxI$M1@F=SAm$^(W6HnfQS&SE2}{~u0ewa4M8-B*p9X!7T2|F*A5^OL~Z_Z z5Qp2aVMBKi1tO<84q|Zc-o0}G5g>XKrl9g%sZyoBL!}{tN5-MDT;INZzegn@iaBpl zIqt=a7Y9)(h~&;ZRE8^4ri>RV0nu!;63BBhnQRP@hKM$C1+tvKzyDDn2~q9X0LXDp zPEK8c6h!vr1|Y+2+O+8%kbvkqmqOv3ot<4@6bcbedV#{YY15{aK_L+3V=@5e&YnH% z51ecO2WpzE&nuus z+G_&L8gYLt%sXkh9cVtXrmJAS$O?o){gHMo3G+o>M1Qy&9IVYcG%IoGBA5Zeh8A>Kr-4N$YxI^Th@4C z2(c!v90m7)yp%dnvm}*O!9K)2;~;M2&HMs!A#2ebW|p}10n7qv(>X9}q;<-{43jnQ z4K+_*MJCvhto$0NPtuYj!OrAuJ%hNBRow`-C$DQa%m7-C`w{LLY3=7wSES9uAzq}l znt=_-8ygF@C#l~Gwk7Yy9_odxNgJ4X@|u2zStM<$g*!rC*j%`6q!kq~_auEHs9oar zJeX_Jj(#wUq^$lC`}8GeuIl66S-vo>Zti^77O$lcZ(7ftyEGCLLl&QdS0T4fB5C&X9Ln z3+@Mbe|z92lGmVwn3J{Ez-*KCo)2**t5zQ7jI3QXm_71h=D~dn!MApaPP?L z+XnZLtfm#*X3{oOVD8Dgs{pk~+DrvCMcTX`)Gc`rPvNeTcJYFFBI|Y^ZZT=kTM%oq zYMtOVlb3S_W|FK^MVL|YCN1FZkhdBFw~xHGK5*B`dOAWalU14lvrAsf{&f&ORNW40 zjV~XC0?Y_$d06QdKW=3|711tVa~{#Z3#D?ywA~a6UjPR!o47G)7RKJfte+*)fR3q zdCQm4Js_|AJ-QR5Rgc2mqh3V@)F1UWTwpfH%bN*vP2OTK+$Hk51IaCgmp&WrBYAZ{ zL7kFzeF3vYR>mD}8+pqo;r^2~aDW*gtr-J1k-P>om}T->pTJ!pE#3g#4zhAmxW{Du ze}KC|UfU6L2dLNdE4m}3g{Q%6k++x&GfiI1MYwt7t)74zK)r=~=njx~I38wzyvxQg z@8tDffSXLck^s2F%wJqEP>U|AGw~D+hH@Gik#h0RcMAqyb+#d2SKEN#}uVE0nKjcNMKsSPV zDSEh{)C(I3_m;fdo#-BrH`@{JI(boYbQ8&2Fo#(uZ?iSrVY2$K;f_!*vp(D=@)i%n z4W!=P5V-qfb;rOxqu%6VbU&&0cNN_X@;>XrT_^8If^H=B`g+2Rr(VG+xGUuCgrWON zy~cLvK2q-^0`463GH=5zre4u@m}}~dPKVn_Uh^clE#y7+L$`svyAtS5k+)U@-Ab~? zo8S(Uw_O?TH1z^o!M&kgQ*G*H!$j4DnI`W(2krv(T6)18lUFH(J5Ieo8@ON88%cv3 zN#61AFyGWmx`Xa8^}-*ayGp&Y^>9-;nC=v~8`Qg60P{}0ftPT@$;-V4w~l&$Q{lEy zZ{QfZv*ZOlL^qLxYIa8Vk$U5vpPnC(Q8Yb@(MRX!z82JeC&fMt!R!;?m_}`us-H_E zo;zbdMYLSgbEe!LQD|@)?t^Fy70T=%$km9W_X4|bUdAg%;WH0;E|176cAk+ zabFOoe5*>jMCoj>RzvcOoS+!nJA zNRR0W7tvr_lj;3{6xx#6$`)T}vlLR`Ks*4&?0>Pzeg!78_-E6s{+zSp!zIcBzCUxn>Ho<;cV7xa9I5t+UX~Jy~!_XtsG#nYlaaD+vL;e zyf7#moA`RYde2|8kIAv|7#;%O-iSmZ!U{=`IMdI=Frf@ZBLK?4gVz}9xn2PvWu3uT%x zj*-lm(VWiXBaW4;+hMPzCH7rnOXD!CzZebP^0Jd^hB=z9!00wCaAZKh=wT+?CO&(x zxe=eD`z6p;(K5C3WSM$p4mj-N1EeN+7VeL*FdQlsjC0&f&vf!n#mVO>a`ogJvdERR zAw(9rbsc^bky}&P&z@BFb2t+}I1n8RNP;kw%8rUEdJKA6NpM-w@xnjE7yC5YBE|wc z=xP^$<9Rs$Ji*(5H(s5ky(~BjD`Ekkq&sFF@jS5=s$q%m?)>uvTRi9Bc?h3=qK)CZ z;dz1uea8k62tWSR190!3DOdZT`u?bX5ERAagyJMvcZ1dauTmmPrk-LaQ)eDoh3p?* zOE=5ZFQp=gazAiINx9ksjL{DvNQXMfHGbH-2G&C8NhrL?5l~KGH>do{Eshy?fuNbc zZUgy$Y~j~ebiPvHD+Rt%;41~bQs65E{%0uw_pZo4IKUtMqj%`Ja_ECp|GqKj%u1HBC{d=YW$E$)t8#e!29G82SO$;fsa(^4#h*>T z(S33Ji>D{tO#czyrvLuxGvzH#AF4ai!dQQV{^H8u536xGEBuwiABAuc;1AvN|LAYz z`t1G`f<;ID#V~Je^b7JwXFe)6zK?dMp`qKF8Y5f|}2dW}sLW3Y$ zF)dJG^Z-}%FmS~YY0@I+e;g(P93u)GArc%V8b~nog2k0`TN?>_%UD%8*tRAj6wJ6S z!O%i03APV7NwATiBaNgu|4uDK0qj^9p=(s19(2S)j82&T4c2R$V>Ne*I3~_oY>pNG z>EakI?%qg5r^GSQR$}u!iRh9zCI)wgbe09_aA!zYsvun{6eL6uwm`xTI5ZWTV^H9w zIOY_fCP_r^#4)FFmn9Kh6UW2?YQ98tPaJa+cZPI;YDkAWLps1Wq{AK7o9FOQZb?KB zdCapVqKiD1A0(pdJY+*UKry7logp2d7}62GcEGnO@D&1ITd_F?FVc7_BuGTBc+B5Q zM0a^C^%Bu(o-&4XfNDsGJ3~6aH>4|-e?c&3B|5xB6QT`m_;5z!v&iF8gtfg*BMv=E zP&3awN$or{h8lWiENf|VYH4$7X>)36bF{R?99>X}IkmJowX``}8gLMpN*a;pESN>T za8XIoPz#ZVC3cKRL|BL`^01MJu>Mvwv?f^4RVWepIZ8z1T1i9`og|_e9a*3<0fmm` z`EUmKFtSvnw*|t`aD@o)eCrP9VFc1MJ zBEwlQM+&}9AHwfniL|gqzu7`6N=B#I68&fZqdMUU;HXacT$4!wAX3f1w17!91I;=L z4qDU}9JHy4u+(Ov*!hw=`O^Fgp=nahep^~Ag)nXj2P-W7Y@4`{4V0JeW@_B2a2@yPohF`>j#^Z0`G9?v_Tf!BQ zyFQZl)|t5^@5)X&>{o>&5oH}G6YtnWI>5I zS25^pJ6w{NM44v$2ca(^=5@tGL*85nj21T?)J+iwL*eyUv% zFSILIu_P{577C5CnJA{~d`T%VV|?fnvA~Yn-fl{&OjFmC?P$CaOpIaY&&Cfu5B}L| z;GdPmKU-Y{jm3v?k)6S%=M7xEQvD=gs+R}{_!>7wtw^~h*^H}NFXn$ct)gES0RmD> zSY2>?lWrOHl!$!Ii@5$A&ooAk`}QN=2?tsnAb~T)#6h@AqC2n;<0U8VBANpXg#;3M zjmr%r0B?yIbKw?8Y7vLwImrg!iGwD*wW7N_pMwncbK)-j5#(xA2!mXTL9SK+xfBnX zaj8oIn}VC7Jy0BYig?B$T#JbdC|XYchEHI_ z5)5YYgn0&hV)HmgNkT&!LD@7Mm zd821U0>st32L#Z~hvYGcga?doM~rVrjBiJbZ%2%8=T%&wKH||Y%NGvN#aSmf10hxj zb{5PTjb(^XHba=dw#k~WdeDHh3AHR^pnKV&B zk~yCwb0tY8kZwE-NH-o0q+tPYfdzn&*6Q|_m)3S5))e07lWM+WCk2fO+)HYo#Z6d7Zr!A$hv)bKp-IRmCU3e_-HY zFDG1Qn(8eB&s5V>DwDlzPvBpm61L<81dt@+_-)iuiP=vo^%`C7A*(KtF3D8jb-F-5 z>Jgb;pHB68Ll?qdnMI{!6;>*rp0k;%%_>?c;2jMY6;BsfK4z#`yXfIi>7P-3KG5Yc zRf?xkVWoJ+V3pDrt<=-cfro{4;?ORi0?)T_VWoJsW|e}Rn)2Bb@}v?ma|hJ)ytG2$ zleEH{BAo(vDu^)71RlO*?v?N8j?Dd-mvniLN97q@0%DO|30enGLj;o154=YZn4s&K zpzE2S>mle+KFk&|=L7l3*5C)mhTvVn#g|cvc*d6ij=4&uG5_T`9s{1>0$e1503v?i z3)}^wa(dDqdgu=nEKZ@TEE5e!YJw?9NBk(?_!*$*AS-Gm5sV==8Y zO$4)qxWWXqf!$LMh4-oK2k%pf;L`$KD_bC-L)b{>qUOLHw#BE3yot1C8OTtQyQ=I* z)>7q2S%ajSgW*gA>flxqh&upr6@R%%Gszigs5G*&hB8(Ck((8)QXw~seol}G38EQ5 z+(H#}*XZ*1@Sq0OF?EHIn7a2oB0LhP0YlzcvUKJ%Mw&U%=+~qzKu^kGj|CCqKrCY) zD`GwBNIrgW4TLrZaUqvz6oYh1Y#q~DBdejZe}=S#4H|%V|5c8H*#hK83zBb6JKa%; zK!r9zItV=V4)7d6-Rfs_2c}Is3H*2;#MnRk3+4ZrrezKCsWvS}O2O=2gbE>#$PtVk zO!4nS__JoF+EALA<<#i6{qm2bn3p#6OJx{~xSLq%dj6knW5Oj>X%Mg?dICA~}tX z%zPHjDosOd)Rp^|x^gxOO)tJHSEZmUXYl&$3|^m|!Rxalug{LWK0EUI?8xi0Bd-sA zKU_Z1_alOT*+2cy-A!%IB<&Pst;A>f`Pz5NYTBvrH{)WaA~d(b-;5Jafm=t{bA7c_ z$ibxhr0uwe6`=d%eB8qn;0jBi%|&utkUCc-4#yqR=Bi{-xI@ZZRnK*}c53Aj+X@GJ45F8-(xCBautaU=vP z0|DknqQtuC)r<8jOv`VlkJh%(pVc<6@@hv>(@x-bAC8p?*eY&5*Vw^)q@XT>cNL;dhp?WJ@KK+%9a7M1`k5{;2L7< zsGZ__Sv%VIy*77Dj5ZD6Vj2^;#(~$hxdFGdxd2uTjt%Gt25zC3rJ$zcGvi{a`Cg3^ zxA4`+iK~ryjJq)xLAL-MI4STt-UR^7YJvB`)pfO(^ z^H_U!Omy|%8dw)VbmsI|7VZX$}-&2ZGV)44ipb9Jsg zwAFNeKH8f)zk<~7RBg5IFfyQ>s!|GZr*y=f${CmbJ@DAy2X~%G&FmNM>)@p~rJh8o zRg~Jz8Fy|ya5u^accYA{3tS5=24K@lnYtDtQ`cfHX=ZXQgs_@W0U$yy`KV|#7<}Br z`A^%898sU5#K#p7%wA34;Y9#KM_U3)`qY}72tez@I}vzCPDDRux$Dd(^YCXWjY|F* zq6ubKVt6oz0L9g0sN_Pa0~Ma0jK>Y`08j&~r)hylaSd3YfB$1n_;Z*W(fhc$L%JF0 zYGJ4hrVkihr;saXu*A8=mSOuN(9}Fo0|2W^U zfweLoD&Yaq;qr6NfRoA4b+ZOy$Es z!j^}r{254S*f3QPft;Lztg!oel=6T(nl9#LRt^4 z4I?`rrj)J2h0s(Ino1z2B)pV_lG4iu?|mqlKP980l~gp;OP-R-QBo1g$v%XGJK+!p zP4A5BbX%Xeu3-b)0|6oP2hxk3&!_DK`~SP{QC#d0?y0sl%+MqF%PPN%H}3%?dt zT{9umN}D$!!A7e|k0xj$ZDkn#WiW+vCcL!LzQsg~c24?PQ&3M#LA@vdHD^L*DFRgu z=^3c@1)ww&UX~(I)lkY=U~X%R3n{BGj2odU7^LvgHiMJ0OP3WFtKhP=4dAV8*5${= zx^Vd@;R%pU1hTKJv>6i;3E4y=vN|A}3}jzhX&+;t9)%~Hg32-lr7r+AXTqye1d5Pl zpa@wWlxD)~QUr>SO-8+AKtcl|t>I-HFw(P@{wc6J3#^QELgkEDJqK2az{-d)N-+hc z2MG&6JpoocD3IJhCy<mmUS`VpcriWBC(0irCi93X!71SjlxvZLQ({bRoH#HbH7+JF5dDZ+gi5Wzr;uHt_NpG@d_fO! z*6Jb7LwxhJ3g6S(J8*C=kb_eK*~BFRbF_Eh;M@s(5;wfEs}?v_cFh3Zfv!5>9q5|h zf@*S|)d%;(Yq_4seJ$5VEubaf3y?^`vbJTp{{kO%5%24+NXQ5EDV zhjKD>{e;@bx}m6Kkvweyy+4)XP308kX#n@Dwax>2j-0ML@VAV(&4BYXL*+?%+$hf| zV>#p~!Bhz5tig;&+HI@~qA?iw4uXhyvR0VqW)F9G7s{DESo05T@Frq7IU4*tiU22N z^Lg+ih!{-|8$QTLJ+Ww95o9UJlAaL066#D%# zKEQ7U%Q8cCg0cu^-=wzH9Hh48@xzWO{`g>G6}$!U;l`$|K)Sz5pW^tH)3I{E=gWlz z`LE*({0}jt^r{sELNL1;kH514|2(+9z@Hw0Km7oIqVILw{?qtB*8Rvz(CUu+P)YxJ zeE{Mo22!s&K_CUQ+u=(5iyyvySpDdc_!mFCvQ49{Z~u1v8t8sxCAQXmzm7`&=j)61 z{fQMZL$#2K2Bh1@JO;l801k`;19h25C5?DU+DiA-9Lrxj-S}>1&2KU zI@=R9VQ}HLslmzYRj^E|38$q@|MHHfe_+Ft^IYSGr-+Y^y)o+JKSK`}btS`AH^D3^ zrqn@`Xb^yo4HB!nTN=Mbu(N=15T+)?GDoI4Oa?3aW=xtn?bk{ZAmjh+s^+g1|4MRh$ovLX^T*FoT)Sg^#g&^AHcPZA z=HZy_H=}Gc<|XO{cW8g9)1#KhvNqp8J}gPvrg@ICe)_rVO)DR7X0f>Z`>oYFEErU# z=OpdqMltCgQC)WCzn>Xq>7LVQ&&uD<&AT&cm*0$#{DWP_ENPg&CE{$I!SX%T^}{T8 zxpf}!eVRk{7M8OnmpVW1apN(WSI=t}xt2SyCnPwg{;7k27xxKmeZv1TDDh`Qv9^Y*fFn0Lif%10py|dpA8yvTLL5<^Ky^kzi zHR5@cRqVus?FVWuJyX9#WQpaa&RTmOed@m2G2MQC`eU8HHrT(;)EV=(Ik)~c?Q*kY z6W0a1`%UWH)~%g$=NAF3JVSQ(-LQ&cK%fx3V-R`hNH_Fm>T;-b?&lYa^Vd-W0%SL@$tyXFe zG;tmKp=oB5%&3Ls>W|!4J97A;NwQ|Ww{2Yew(`**FNL*ySU2;S&+*yQI#!%`ujHgx z6`%J@6?!yWIPPqycX^?X4`2cX3)2**-4u@#;w>@ z{QW15PTW%ckcDVqtN6Ef@9r4t)b_>N#L~9??nj)Pbnm`Lw?W5h-mJLOs%^i>_^ib8 zRr~_)E_nA{J-he?^?NUy{#I4`xsIP~=F=y}oa-Tf}@8MLwMhKHqAsIsNw zD*7~xIMwGwl`0OWE9SKf-u-UufFVB|YIdMeY}UJo)L!CY`H2NZVM*e{aH8S&8{gyWvX-)hQB{mc4S#~_*e&hm(Y}117vR_noe)7yITK{`J(WS z*ZQpPvZ2?t8ZTeX8(Fq{wUa?@ek?y=ZwKGFzQPAOvwhhaBi0V?c=cSZ(krG_DYNsS z?ZlV)&Gbz}+r8Z5(SK?{nZX-l=Kb(=iEE3ndgTwVNp(CCTH;tl)p9CZkLC#{Ls~Yh zcr|_Mwq5NFQmCvAK0Zd-CdjODV2tB3l{ndVh7u)zyqc8jT^#KwzOEVykySFmvI zw_Zmh5{KOUA>6{_{UH6p7ndIl;bu=3*VN70eJ(%0%JVB5{Dy8@&_z3JQ9_Ddd*9;z zP|JO-W1h<$`h~rTa2vVreu!g-E&~I4Gzt9RJ1XYQ&1cV#Jf8bt-<7qmhIKp^5xq-L zV^iaus?OhpPTi<-JNxqL+~|pp%I2*roD!^Rvgl#`cR!u&bTlV%PRX)kHVqJ^rA|7X zXW=bweQe&ArJMBi6=RxNjX2P{edSwK($vnlWK_~tvuSNguBROvS(T;NZx_O)`)T_0At#RrGx^{3^YKG%I;kLx`*_j|a0zD)M4 zf?4RfB`q>XPh2o9IDV*hh}Tc^+TPe%ZR4grqsC_ZxIaeu%j=gdML#Ti=+LCw$n>tG zmfQI*->*Nb>E5H=n{E|{pI`o>#i6ra^GjCr{~^2INzKw}mf>|WTJCx@%qev5jj0XK zK6#&|nvRqHN6RY=`cf7yJ}7G_v&3L)_v4?+@Kko=WI& zOrAd3^74viE$()|;cwloS)B__s~qawtNY@uKReo;s~?=+`~Ib92g?;JlDEGaGgg(h zzSGvro!fP)<=>=x`03m&Ki58F)l91Pcc0vAfV21c{o7jJ_d7Rc|B#{K0~VKSzx?>i z2S=)yHwtoJD(&PW^~&{o@WXuJ;9$Sxl^d(R-{5BJ7WLDx>66-xUcR8lgAPra*sN^Z z?bnqp_tv!Czka0WewoMmjTfe#Zhzt08*RrA2YVg(&Mx7%G8Q$Pe|P?>`|1-VYxfL2 zDBje5b=zB`u1%=p)AOQBIoHVizN1EW%zp5silf`p?2dQJ`DAxo>;Lxq{qsKT&56@2 z{h{S%kD2u|!-0Xw-N~^q#=kHwHrYRPsE_i)o<3sJG584|i?oDx)N97$~ zVYW*@U`*g|n_BiAJt?SOySH6+$$_08l(zh#jC90m$qZ+QRlBOMSw3x3?4o6hueb1R z<>DvkXH$8e`Ah%q(|2E-b7VpPk-Otc@3h)0$@KSsE_xaBeS7ulAbU$I7u|i|ncO$5!0&$Tnx{ezmXJHv2=X z>u$X^U}z_mwq%Xp6BeBs*S~+F^|?o7PIhv?8ZdHn>-Os|Ed70V`r}G^`)`wGc`P}# zuIGcJ(Pdm3ZVtRt;m5Ml1C|%R(@t~c`f94EzH@1Fu;h(NKkrtDXw#Q&yf<&-@J0vI zJBBTg*st$#L#XV0YuD4Jt^+DR{;hM?*7=-ow_(2yco98Z5r4Ajf{W5LL6sKudvS;&4<^o^HPdfPoI}lN z9{1mkIP7L=TW$2?=(1Lwe{win%m4bLj`thfD=QF2gim)Dl39!R;T9AEEZ zyUG>fUw95POZF^dy>g-N;Efw@?K$YSYQ`A{Mef0iH~ZJ}YB}lDH23-D&-G=q&34&m zTpIkV_vy_)*Lrxa@A`$!w>iqa9>jLjzZ-Nha?OaT4f4~%{03a!-J|L23d>uszGUMQ zRdyfOy;In4kq<9zeO)qafo)!wSDx>J=g-@JLK{BQE2Ko!uA7IJR@>7ldCr1+(m*@YD(Cdw zEQd)4p4@DzKiB^H&8Qc$y$3>_kN!Ar-73-G$tewTb_^UxB)R| zeRp)V@3McOU#)H~Ln5;KM(;b*e`L;~7^jV$%vbnqiLVse(XM2>Gi|nc`j$EUYT)?i zzX-?Xskfwu{II-x`D=A=p6^?#UZwcm)2uy~uD-G)V@S`nGc6kB-3c6*b7FPHQ@bWP zid&6cXMW>Ybts`yM5En`OM3E1FQJ`^tRn0?Tth4uQx3FFm!FN zi*G}>#tv>NPCKoele9CdPS>)_>XsgTyZ3C1r}>SBO|;vWAkVi?KICcnBzZ?_=?X*b z7Eg~DIB3M1MqxG$Z+t&9d-2=JiZ<`uUd<@AG^u)(@1zN_M+B35`B&QhUcF_^yS-Qa zAH2`lvSWsQ^5Ki+tPed{6&e2HiREh~o1RR)t8;B{bAIgjL)|KU=X-LgIO+P?5nVde zeEwaJF87AkJ{n#2!Ii4rn$JnEb*tN^E`!S*FQ2%vwr%hhkFsq?dRHG>v**iUzBT=4 zb$YP*hi3A(8zLUIxNhMki5T~Kal`0bmtRK5m3KH~7kbL9<-n+}j~^$rQf1Gd?muEc zW6jho-`4l)?RGd)|HqTZS9dpSG*}}LtZDe_)eMayppVn?)+?sCzFHjDWsUdEooBXY zs2vvVY31jrY0>`qh3OE%i)Vrb$7Wbxdzu)uFn0S$-=~telo@;5RI9aV z(yLDC%a%RsGOlm+h<=VwbC0PTJQ<`bbz<|27BMzwT;0p3m%HP5Xp3z2i@|s8tFF^7 z+y89;&y9YZ_fzPL_^OY?{l{F2ee+uWvWr=21DmOu8P4Lkg=1d#TNeMi&M^t+V>74Q z>@mZ4_Y85j>Ts56I#m3+3Uia1BxydPJJC`5W6gy~@hh@`%Z)Q$h9AOt9KlN$L zGo2d`ays4rnZAb8FSYX?R-9Gx{CAheIIe6N)93@3i0ZfRgE8&I}`uIef9Mj2Olc0UHC>b!h3?ZV~u@XeB)|l zh;~&QKDBf2pm&|$dmnGsZ$}le+o*m^Wo=7-zuk54HIFN!FAq=Hnsk+`+h+RZ4bK{_ zICrS`odq>^*vlZ$KtSIT_XRU5Y;!_L3< z?bA0S#ck?;5dGG!=BNh?mETnULHXMSxz&~U(DFIQTCe}5Y5uNy>w2E5xO`Vn&)+S| z#I;O)bgZ=5EQ|9Na#i*8QEg^>I&Z7%*Vn7efr~SGXI&Wou64xfpC#@;j9#6dTrKC_ z^>VGRya?~t(QU&q$t}OxBM-h#wx1V%x<DKJ`$3tI2I%KU3~^+IuZDu;KQc`7^oa!X&46A6!R|ez!1C z8o2q~ksGJp_ozJZbyVlBon|y$ekXd_`cBi;L-IQA$qRn6`NP`zv4<>5Z7)&(ZJhxZ zvw9CzEJ~NHZFgZw?6^Q#8K<{BgTCMLd#B(sHnPJSry1s1$*x{|T6TYN+5chuw!FB# zulMcA+q1>2$GEum4k1h42KIaMYr9vWS?nwm%v-Mdwt(LH1X*9TUE-|eQI5=<*eFQD^5{uywm=?I5YkeW6KTsX2b__Pigo5heRfUJ(jMPZtO6rjW| zVr_VOjXJC#zODK*FfF=Tffu4NW%Z=nLMNRdyAP^W=Zkcp$+;eOzA!{Dx zHMB=bI`vi3<4(-igR4 zK%f+|E@t9aM+4zEn2yBgigc`iVkmTn@&;=dB0$3N3Iudt!_+OTSIO%9aqF5uBkaUg zg4eoF>~?#KVeMJ7U`lW8CP{P><1LX(e~ljESz2)XSz1@(4!kYx-qi7OxF&h)xg;w+ z301z$vyAw^3uN8oubK1EMeTMkFyUW3J^N%g^kOw{Ew)iH81q_t^W~h^#|ypH4~b^% zAZxGv3{+!a>}OnakIVVx!dbFVtHzl>noo1Mg}kSu)f3G4S#}}C1+&3`R4Tzv)MQis z{zVgLUId4|e~B+xvHp&KSu>K=x4+)4)hsxfnE3U zLBf@(V!;YqMpnhdyCDe@m(Mee!XPzq08xzTTw12IS`XbV9f#~}i|3-7e+wTaUn)Az zG=xebZ^ZQ_VSj=qz+O~H+`b}e++4e{pkJ;fkGZ-0FKCn2)7RyZ=zjt-cy^$37kx|d zVcp-rvzLVUNKcF^!0y8LA?8*$^mA3JNVz2#K%x`Ca)pOuMY97Ogh4uG>MKW}fSSe% zCoUrN_EaAAC2a{bk){8S%SfgGe^Rz-+^mOAw9JL#H{f*zQqSE`dgS-to-e0XaC`M33Je(&raYtz35y?;g=um!-qs z5dZA4pvcK?Nd-VC%+_x1bB#|Mu6wPuxvC1_9r3hb*YfYwo7OUW54MOxac8cGBj=$v zv|*GLjIIh-iAOyj+HshFz!;H+c;Yqoc-s3ltQ}P0K{k(bU*y`rItYlCI z{Xm7rDL2I@adsl_j!Z2L1X_5ZfS)?jSp#KKD3!&St*oJR0j&x8T)$NdDOxQEgn*kt zXB-ctaEHO%E_GZwrNbqNFCVW_p2} z@#$+%$!Bt}>9uRXd;Kko$Hj7{@^Wyv;>A-9$PvrxGFe0aox<88JZT6-ow>a?55k!! zwlC)PB+hM{g*8aWYP~t`SgP8CKMz(AgGRNEZ@-=RKhIs zI}Nq6CKM^Rx@?65IqvlYt|tA5y5znB%$ByC)(?UP1Q-%ih3OIkX~N&737QWU`hRa` z7naSuGtC3VqcC^6=f={lJ}+-?Ma4e#$ynV z6h5DZ{`}4R?6ao;!I%3i@xm~1Je#D>h-BI6PXsMS!JvYHF4a>@>FJRJ)7`d&2^w^< zNPDY*e=*Z1)D;fw9%p14+a3Ikl3SeAUtP?TF{5-gJ=K-Tu8;r;>_ILtFleyt%%FH8 zke12&GFbv0+Gq{9()%(D!KOj;+D4JrplI(KIiU-#I!kwrW2Lyp*Q5)Gy$ACg5jB7r z$GtPazQc%!JA3)5UeLycysl_H>lry2or<`_;|`0&NCz-2!A7SCe7pvA^H*(dd_ze5 z8ma2fhZWabB~rY>2n6ki}Lx(?!>!j^hK(^@L!yJ&IpiJcw4 zvkJCDdU6hN?@?UjAwru8c2dgUS)o@Yd_cyHl~@CjHG{1VGTc?1SGk=EcD!NV(>4d> z+l+TVz!|0!kD_kHq#@aDv`3~dGbE*UUEEu&kr-Jc0o=#BavDniQ-t4QVd4duUnV=| z-$lSWr`uDl8#F(PT4H;H%xS`oi4o&Ef+rf+AYtiMqxrOt&vlspBlt>yn<_+IS5G1% zc_zl}o;yt(vEApO`y$$rVWtFZO)_w!7i~9Qw$l)oSK~x5@R*G49B?9JzUySe9M&^; zQC)vD!zQTCxkOggNL8X$t>DIhryxRv9b~5pUP`0o4CL5}KL+NmVgbECB z*uCS(`n`f=Uo?$wQ0m3Sp})_Bfd-amO!2zYLJ8Fk1B5vyW2P2IoP)RIz-`{=l=tz~ z&ZjD3)b!9??Eb7-@$;2Z2L?WsQZ`;HP&;KI9~S0u3Rt|PSNwD}Qxd%4-4&3)s@HVU zvPXMM1YM!?=-6^V?FahSf7G|`v9G=D`JXFqivD0X6&A%96Krhozvh;DanPa;5CnQn z&ZXiDn@*9T&&8wISK}sE6Dzwa!|az4-H5I+e}4^Z{yw|?8V#})IY3x&CaMO_N0;2E zX~}mY71&jHhn1$hDzk`DIHI13og55yiz3-K+8A7$5xeil#oP87$QuoRTae}lOE`5% zhRvuustd)(;9Zcy`#{dHQW+z9a|VQPCf-BOVxkhM!FF5g%-uMgvR4UWkiN5fRi>vFZ+H<^|W%gHd0 z=*SiuVMaVRb*=`ct1M78n`o*>Pqv#)t`v~?dmqO!oN6y1T>ft8uLJpV|M%GuA3bU}Cp+QzAHS7)%KHIFrO}j`Kx@2uY;>zztl0KYASyLy3cab zYY%w#1>y;t`A}Oy#tmM5tY43gL{+{rHWB4=EkNwkcW1N)SDk~F(d$Dd&tD^>fD>ui|Z@|8DrfrG3RZsWi544_+ z`2I?}ux1_R$i8(g3ot3~w4}WPTB>UT-l)2ZKtz9_{k~NH^D2729gCa2a!R*Psmf98 zmzIZPOL~*J)rThRAf1|g6!7(KPvmnK0BH>A67;-^9u`7@BG7v{D*v|pRW~_MWAAP4 zR{ay0Y!Fj@f@IHA!FnGQl2h>GI`K^dMd)zYs$O7!km*qH5?<@(VzvH1rh35;S;#-+>Fu1eSm zk*2DM#~TM{1Iy;GsaNVP0jzjEv>V~yQL5K}j6sHSS{e6u33tExkAv&2XJN>WEdfuv zsD%>hKdU~P12u@&!UT{o_#|EKUg`f6c1v!lq&_0O68_%|Q<`(O9SDOIUDT>lZ4Hd-EhuoZ&EB&Ff-SeuO0xZjZVYlQ~1 zVpiFl1YTgrg3msq?l#a3vsN*~tZ@OQE*F4G>Li`;?~dGd#&RD{?nFIa+^P)bj~$zr zruc3ECXINP9Ey-&!0vA*TlolXPRZyZ!Y71bWm*(jIWu8BH)BBhXv3S$pi+u0;~UX} zkj0^wCwqtXCELsOn}K?RNdgJp*wIfaUk;gc=Y1+-8&O4hprsFlEreKQzI3@TrqJ^j zWQ^Z%ZRA3AAT@w|BgpLJfBsQ&nyi{$%QTVYaa{!PGzq&AP94kJwb|uUk^J701*w;f z`O`*uCzB}tb0S9vB)u}>hOV|A3{mUuXHZ%2#RzwIo&uK=&B)>yUNHH)TnS+;+17vXvOkJ;dUhU#DbWEl3_OVb)4)G@#} zNB-DFA_!l3uAlVP45akOk+KillHCn+!P#jphiTVIR1i*ehudOy9g!r8b{3~#5E%Sn z(TZyJsL@jB9wQfIWxXpGAF-=Dz2|KW_($W&h;QC+!<^ZhM|D^nP-zD=&`#xex`S?c zH1qJ6dWIxP&f(kS7fHBauu)&Vd77|1Kmb!W*h3fp_~1X=+o^9=*pztfzb`=}X(1;1 zk&=75+u%D^G_s!zz__Sv0yuWPscJy&p*=8VpoSE}#4hH?9x1M2J~Nr$k_0MZ;EsB` zoebE2+pYm@ywfh+>~y{e5?aGGA7`IN8p}Y{$M%HJPVH>bLk|fpocm#gw4Ebwc|B=< zlnuRiDET(0?ob&lDcQ6Kvk}}@LvcWDa&viP<#(>i;SZCZOl!D zxT5Q*LWZ|Cn&|jn-#Ul(jvNdJal_NQDM3LEk1=@r3p?3roTDKo_ZR7@!gQUN zC zi9nmih0cfO&AP<;K&yV2jR<6skh5SXw#D>OQ`HSLk0UtJ$uS+HkEHZfPoV%w zud_oLISr&0-Ej?g7p~UbPIVI!bPsNEAP_^0!j-`PF35RiGAXRk^sTclc6z%3({RZwW)2T@ zFCWKn%p+?nYhhee*NY0Y%g-o9B6qSXGnRw@n#o!M*(Z?%JL6+3pwtx88AaGA=Mcll zx`e#5gNe%z7)WC{VIsvW3ocBw^b{CSqubw9s)6D6jB#1#@Q>Bcs0X#v6x$5>*xC!l zjz_&$s`=$m;+MfGRmcnE`0ln%R0jOf8uG|2bDbuEW62!H`AL5V1hV_=lebpNaV6>9 z_t<**qt?Efz2i-iKb^tm0H{Er^pehv2d_619!>OxQcTtfi@;M^NtfUCpX9ZneP44@ zxQ}WxYiHe>+qN>Zq#9AQpooiARm|1fQipg6y;9BCoIA7@YiXjwpv4P+?_nRo)DmtK zp67!)R0rXl70SPC*>mg&KV?ZRy>c7l@}z+7JL~!DP(IA#CM{^?{eh3T<1KiYj-X-BgG^i2;-3GcJIvog0^9~l5M(+ z^%0JX#C0PpOw25g`fT{(QhI+4Ggkhd3e%MRH2G0fYb1>=0BTMok%|4O=VT zTW@#2T0G?}1$#AMaX@l!dOyE$7dKh5pGpiw98l7SKvS@X;Zg-eGE8D2$b7%I+s*nS z&ZbpC?>Cr;%P2xxan?`$*4Bsb4x!q@erPkImg~R+L?U8!=9}@0gwZl~^j~v8>G;qE z@i7U&6K*~_7(f2nYTnE-2NLDaYBquMl6@9nsUpH8jPWUT_}2Mi6tPnSz?UOILx6zq z+=)#y&VxfLx?}9wpey-YH|faEz;wRIh(e3|kwaY&FOk+~NimTdMr@gT+5%2G@8YU9 zl;tg#1E7kwMb*Ym4aZI>R2?~C(6Z9=l1>r+*44#n|1C(gwEz#k#WTP4rEgi`x*VsL zR$EyRx8BPAvN%bUafHqMOxl8?;lDQx^9AgfN-&rP8_sdzoA8jVXz=E|0x%VCUI;vprFl-Ti*JWZxfe$B{@U8bv;%{5Ae~)wd)3P)El@Hg}xjI!y z+ms%{$STJy?z_Ofjl)`bk4Hc*N#q*}Ro*KFlrz17^2D=N>D$O-%y&VM&zX7w!4CmV z+r4{~A)73_3$XdD5jGb`jl6IvZ*_gF2);}jqCwSXs`S|gM9;!miMHsY-SLP`+GfzI z>Rr=%W$^^YXUcd)AP3xj2F?Py;Q9@rO}Q)SEmz!xm(bJt`$ z=$(U$YZ)+l<-sM$ky?t}ysGeS=6{PxY|g0kc&y8Cr!~$TSUIxxn~q3>5wL96aG*g0 zSSA~;2Ayo$QjBEXF#7?w(VzQLETBx8hA>ud7cr9tt80Z90D&t#Zlq&b$Vi{)$6=nS zb-0RUv=@a-hi@rvR>m9r-2B8g?`@Eyp(j$_MTtRTS6}I$-fY?ZfgZ^q-hf2fe&pL) zw&HC$4>t**y~phEOFdYaat0mcS8Gr7gc)m9c(B$35=pkOlik}V343T2G&DM!sUYl8 zVPv`ud>APIf7_Gn-HYUAB#i$6j@Qf)`SKJc0|q7GPamP{R-r#6LCqqH#^i&t^o`}D zKX^HdS(w6j3793N;;uDP-6sMLwS;294TCrn7J2oh%0Cj)Yl=&4_(sL~il%NOHjQBV zb7<4S6Kz9{mE?BKuYjLC2;BwWoO}-w_AYM#ZYILZlHE`Uyp-z4# zn~YSs&lNgZ^AgZYH6dSg0sU6iUY*Og|vAm?UO9T6Q^X4bS6|3(7pK%{tqnP&<{&2rrK)8qY(|ELapI zsOj!tyo>COLZF&*0-wiJ)%7xE?A09DU*Uq!IxupkV+EXXsIO`_pT}Rk+|r88(+qXX zpW8n$j<6U+F9rV;AZ0B+&xBC-3Dr&%`0%}cm|ODG^6)$KH`r98&vC7Way9fOlKv;S zSVw|gTdULG!IY3wI?`P+Xgy+PdgH)_;F{rka(P@=wKfgkmNRN$e*dv1$g}IAQ`8C+ zg_K)k3k*Zr+C0CK#@d!T4ut|oYBH=9rSKfdx>b>Q}Q)UH6KH#K_Ru>c_}M|6DTHuvpK_fm~PK=ub ziTtVbG|v~GS~csw5dM*D4jwT-k(jHJH~`YZsp*V9!Q6W#?mNYZiI*)KIuyFin&^Cz zfU-SO$}FR>gE!Pril2yFZ_$@Xvjjd+=<@Xlcy8N_bdH=C@Eo~nU>zYyQcj2101}1j z)znD&3WWLQ9@KU~>KC;~JSGmpUS4Q0{Ya#FpfLvdcyC|jMq{3*v5=>T=%1E=eGC?2 zxf@AA)Gzr|CUuouBV1&rd(NZ2uEk9Bw`d-VCxc@5(0Ze6 z$3D1fzVxOa`8+;O96WlUv%UZfMeq2BK1>Y&v%=yqTfYeYlnbC5Qtu>^sx!edU1;Sp zyB6O#MD^xaY2c}7#_Pq+_pe$>UlWTrMW&Sa&wk#nUwV z)T**fGm3>^C>`@G52Q+>?{jE7H@gumvNQrzqjXH|-DU$VUGl~5+GwfyLNT^yXb@mF z)V9}XEN#sPLMem{2~YQ^?y+ch1Qd1R+z5wE-aVY`0sBtC1-1 z6uKAY(-~rurh<{v8Ou?wl=0zQOs5CGn1zqWyz$E-@>p?g7|sCWA!~#?T_+JOFsA!8 zo0}t`HeBLgK-mS~U9-N}4KjWouq&`l>L8N|D|R#4LAd;9_!o;2HGYG;AxP4nFIAFDlc%gk4##V*8!>t1JzA?s) zP43&hZ`_*+1&gl?vMV*r@;%maT2M{*2=v5}OKpd_Et?{qbA;g>O53Z0mvvA{7)$8h zw!9C8+-II(ZX+dQ*v2-K*)iAzUDOi#JFe=DM&d?C&iEzd9`p4ib-@IHx5Hwsk8Po> zH2G4IYFfb!!4eMbU0x&ctbIq?>;^o;1_0`^GKao)6VnU~F?c`E4JH((Q$q5RhpvSnJhrO8E5&_c@m*Hj{aaJZ7X_ z>o+_gP4WHxE&JP{+^N_yn~&6Y@XtW2)j|u>gR>aGUxav{?+~c@@SVE7Q#Y?b`TZRe z{M-w>BgRJFyx_$d_ z>^|%^MYd~W9O6`$qfQVfbHihe=A(zan%fCM*HJS_r%e-J<0PjK77KE)DNOXAt?sM_ z6VK2srYULSjCDd;E2(C;lH0|WUO53E_zLa7Jz zk`l5iof|yST+ehI$A0aTw85nDNZf~r@ew*pF#j+(wtSOVJX(x3DJTMo1jKy;d5?KJ zcRA@mt!}htP{XcDlLNfD*<{Eja#0b-lf{=%+co{wVUeF%vke07D$k ze5VNqtj;&{R(>REzKCLD8}c-d1;eMvbjtmm1fG%V8~yBU_>mcojcD@Cex~@)MBfMI z5YSi)OW%dr^!OwU#WeU=t^vQGR_}J{b0fo{td(O^6ADaoswWUNywz)7*0u4{?dv@v zB%V_%aUH4->`a-|WzQXE9XNw3K*v;jFYOv%?xo$MZ;iAKLUCS$(6>+?u~69&QaXQvh+c(L{q`erEZWuSH~_ zLg0MNI=qe66ooCITUrY!}sH*s(|0G}k-G&sU=pf@F}kF^w^!oXo)Wy3?zr<9=y)+SlpigS04IRot7 zCS;`h?_+w zqWcw*!}zUV!VuSu;=mcsqBy>0B2fNJoF^*OxZxxYFtvMGf67zAw}#$4y<>fFvk%j# z9@1dFl3$Rlt5lkMw*TjtFlut?_xUz zaeCAWpj4L|m^;I8-)54JZWuJ*u7}*JGC|Tx;pi+4x^9#i{L4p*uk*EHX6yb(G&j2n zVYT|sv0U>R4(6Rixek976x;YY*1usqTgQ_?W>P}Q`s7ahJjiQ zsi`f}_jCvG4V#M0c&4~T|1873BIm-{r2=v@^|f)oxlR0OFMq|A;Q?KCOw-!7HAaxj zKhX<*j95B$QxbJyEiA8rmnmG>+Sj>(#M$@2jXqNdt~82+5rZ8u2+PD36dn?eg);b; zUkU()9^9wybYdl4wpm~dz;#f$&gz@&D0ulD*Qz}icX*SiwH$@NJa1$Hl*NOvQq#sz z&oHe!>bz@70!YxB9^Qi-%oLdQKf*H{u*Jz%HbJUyq#bOjQDrgSbRfS* zk8E`xdv1n1YweX3*e7>#=iGv}Lqa*S^ALu0PDQwiq;h?Qgw8|44>!NtaSbwi%J<-S zH~O0YKT><@;L#ZYLVb({%lMbMgt5CfD$QFcrXO9TN$lKF%QTkaWINt!@ou;#r<4o` z`Ru0v&_K<0fQyB&+7DeBMA9cNjl$4dv_glfKU&*VE2pj z!*Lx60$XC657jf4VcyBOL$~Y$AV=q2R1$TxvK-EI$?u(??=rmrYEMdcB9DY~_l2XZ zj#c>c7T4NS`EkUPurzzC$4g`xY2YyR8q-HOQ{JtcMS%RE?eT;Fc_7Ua0^~4yLdv`soqiK!5Qr zBXYMD(c!@MGET4*Vl3>cjOBzq*oaos+i``JObPWWrh*1`8Gipyd_bDxcW|;yA>;5* zN5xqW|Hw2OrZk@xryIOdmJt6dL^W80w>_6WLbi)*LFfEP z+~e12jG5Lk(5~Fd1c0yGJOv%tLIE3q#tvgy{E4xYjx2VsG?@+(1f<6Oq?)2rNSTnK z9^lv+ftKjk@vHniH!TxR4W%J75n-t5V`xdxWxS&XVcrak?~b4RNoHCCS|phSA^#VEdXH&54c=G53$^KWyR%*{#la$f@!;pXePXxTY2bD zv5#jSH1*WAxuSi0zViWQ1!z5?;#u05Qkr=Irj896QYme?LF^2od@BEcvj1W*H=Xf$ z(qYClnPRPlB0$1_DEpwkT*I zS0fSO*O!p0>=fh)@}l{yR#TBD+R576byXHgp~QQ%^;x_NkSuAST5St_3a!ua2Nbi7Z?vs=!y-E)zO zXn&CEIaH^W)6mmw90Kj{*2L_RnlpE5u=%M8O2&wB6>G|eSdocDXqmzg?}BdaDWX|e zPOs}_<2dscu4k=YhZEBbvzZ2p#!%q;WVaV|fFMNx*TYi@ z=;z-!f+ja1OP#kX6@EeLEzjq693Ny^%+CwzSuh?az3fwR{e4VghGEK2B`#GjoNk6q z%})5s5Jrvm33rxrv;ld-V-ZWC^NX8_;5L%|3fjiY?2)iSm(tN%Z>$}=ZucCiQyu1j z=N=!^5~L78chBz=y2FPpb`3?}v`aT1tBn{9^5S@2?}fPZ(2kbl4_6d(j#j`%Aq5u! zIAdWk{)!Aw;^*NQ+IZ^T|8=TNQHouB@@LzEa8pokhE1e4PnR0PJPJ#4zfN8-q6K3JT%1cc`Z#Y|?-auE#hfXIhK zjku|{sC*4oM7hxv2^Yj4{Dlly8P&#Ai#FQ9_dF5R&V>gnk8m_vGxl%>h(F8~XE)+T zk1WSf`V2@Lno&nV0){9c@N%;ztR9%q$m@lt%BR$+=~&;}4aHO0j}KY>%wc1l7s=*C zYhvkg&t&T&5MkMW^N6yZe!D(~=Z?y1VYg~-SOc`zISbL34eMVXchiR!dZJ~523~2c!3kXz031(dR9RBiqrN1Ro`j~xO z;sn6OV6U119KT^TbQBf37oTrl%5G1vH2K2b9?P00p=je|lce1YP41>PgyY0uVR zpgEHOqJ7b3BROdbg~`gFZEAe&{8#Y2EM~Rv#mL3OBu~2B*o`qI|7j}-b<5~r0gQ4U z?z1C&14Moa3JT#BWk!V=h6+8)CP;nO5#rd0IVhbAZuXk9s9ZC_vA!W*C@uUD`9h2_icy3#!$8kd+$VH5*})q*8hGHH;RiTrSm>^g$IO9F zCsT%_gj<7e@(;rT)Hpp2dqV`aJ%XWJn2P+fBm=$!$$l@mGfHUBVb?b9eZMK64&MP< zJy-@4^8#XME@FH`pbfDF$a`uB52~8KLr#y6`%dX4ZNfeJx5+h%#RLDAll$f1&XmLJ zLpXk?VBTSam1W+}MKzhB_9A@Jx^dPdHp~I5j>2i7cPRQ}c7w1k1o>W)G7G9x&!aCp zdY!~^TkCtWf8qtvG#C!H4OeJSh?fY~tit=&;7kc4QT1Pep*MhYoDuJ9yRmcHx(4;` zFvRxUN)Yekd;a7AC{_jvESlZxJ_M47!+|=52$8k3&Tg$DeJRa3z!SKi*`>V&ZsEs{ zmP-%~e0ek|5EW5;=b{nJfMf2KQ(DTFLWiTyRfbFjefmw+QfQR52eL{Z=OV+f7B*dmf-xWf0`N# zvH|U$H%hlo)XM2FZD#3H%p@gyF91uAJ7_6tApG<}dJQ1L%!)HQdh|Nab%_$^`=mK# z&wo6_6dc3OD>A;vn|Zc=BlbpS>GYlvn<>{+r6ziN@)4C`M7o(>#^hukx0C&S->!~JjBDov zm?|&2Gc*P0x(s=Jg_SHlpe5(X?e*BrcErV49sa5BQn?1vsT2PWTX$SMFu7OYx)L8WCnz+rQNEEkeLf0-1_D1eOlXM0^MG!w%1jAIF|5V|z0(Cl#YD3T}A%Pl0 zEvicH?GbN?tFt)Gw+>1Jrk>PSSYGJ&y>qwH6dzoh#F|w~E8kQ;8oortkr<@y1lOt) zh{v^F?0b^UG>VMm7KJ?PX=YSQ63BWR?D$PtmiQGIWq2ZaoTtWzz1>!u@S*~)^BgaV zthG544gZ~k$7!|lJ*4UWWazoDP6oSoLCW|~W1l4b5-3^}nrLtMtiHE8USHDzC+x4A zk*Z}vWlRMqLjGO@1cR}p$KE-X=CFrorLIyvt@gO|6N(y_%#)J)2ThYqU7i&`DZH!+ zvFT7ODbZAM=4I;$K3umjiS_SKlN?Eu;xD)hyJD}2dN-`tpX7y>kQBAo8GlIxdz#9t zKhb&`3hgx;)^5l?As%3B@pcT(x%`pZ;U}xtdr&Bzds~!aRiznxCz$-Iq3}a%kz1uY zy-zztkH}(aWiBh0%CHU2)To^kPi&1F-333nB$x{r_urg%x5rnm-9MtcA|;a>@gMv4AQ=>nvhp$w%6+0{7dMLp zlljMK9Ikk=nwVO@YaLHkSdjWjPTn8W6>jV&{O5LZa|6yy0>9RYd2I+}dD+cOM(}c4 zF;;g+W;L9UC2`$#YrF>>jY6P@m%PTboonm;QqF!*GE~X35@n_Q2EFLefpOUt>PEZ9 z7t>8RB(_pHAnHL>`@(%r?hW_6!{{hxZUHMdB6SM3XV#zx;!ZRQ8+8TG?B0tJNSeS7 zM$SFhPCZL*Zv4`jZ84@pOa#wXiHV)5w_iT4R78J#lD@0^A+hGNb^tTs`%oAt6#$8s z?1422^>_bu?cK3y1yK;IkFoH4@6Vj5G3`8+2|$tSU-(fmtw`;NhZ~k! z&`We(o{4v-Dkz82-aJ3hkJ=96F@3O5yLEnQJcJXTI@@matm%M1usCzNsj+jd(t80Cd9U-@sC)VfiZ6aH@$5#?TV|5nhkpccJjj$u3W}Me3fLzh#Kd@i9oc7WG1j& zqveR(F2{z3@e52{KGlMzVw*kcG1Mvx^j=__&_$NU0>Zj+=VlvfI`9>t#7&PCI#w+H zjHeP!ptBYCIw2F(ND6;bvVjZW6s43Y7}=^2Q^~!zVte4(-G;zh@^25HckW(g z|IE<|@qO=Gd0$6G%mVj@`Y5VD2Ok0t1qtSo#;A{fXes9DEb2D!nn7{Bn%XE}%;6pv zbM;Ze8vasK^p~kWZX^HrU!8QN$+j`r!s1Zl9WIA_1LO=I*+62&%k^|=cd*|1C^sCI zhq_RG7$rJdCY1QrLp?CYnRkKDmR6o&aRdrcdoW%)_MZf+$3C(Cu=&m84Ec|p7jfy; zua^3n22J+%q7opTUcb-)z|D&_A22`W_(z=znVx6|I@Ci?FP>;01PPLm7AjOt2dAK% z)sv#GWq`(tMgC#Xi~x`T8^1FUwrz^QSe0}sG|<(-S^Twh;1%L$_URJ$<^TeQy$n+Q zh$W&vw5%xtF39lzOySX-bDqXoVoPX;iMh;{9Oi}ElVs4N0=r!;JQr)|I@2oh-I!o`WfP;c-8ESgry^w2}4<6=D3oy^Uq>6jQ6S~#Jl!slzr_<&R<+@e_SY<8*{US4DjcHk*XBnnY6|Q-c9+=7eVy?Ml z#xyByG1k+r>t#+}0<%;kC1S(l1c4h9#N}b@%N~K;)KSs7vr)A31)1Lkw-3C-JzHNHqR~cR1f84i@ zk4=3zc4$iVRtz{L<3PvS^EWMEuH8QiQ$kYR|EOh`hYqJ=V z6GprON>EXD>vey|`s*stR*QtzE2$5|<^q_#geO&+ZP{>In-+sV>coYRD1wj%yCanP zxuuu>62AT~7?HVgNnqNAMu-<K!6b_IEIc(n&fmdz7*cFhzY8l#~>l7H(xKE2(;<({|kez@$DTrcX|W zqArAq+ed71g14VXVb|B+65RH(;8rY}J7-<^*D8j-MijDw58c?X1IEh(@%c0iMj4*h z7z11`^Y|A*sJe)Vi+3h+z}z=Hk0%ct9O)a<5XPYQ;An(=)ZoDEtrH^fo0*HWLK1zd z3zk4aNL^;j8~a@Q>(+dPiw)7#npUpDhbCv^4I;72@gcq6KWIDz=U~)%PHKYCOUt6s zOPJ;L5pH|_w_rh4m$E+!K$;j9eICjvlz#u9BAbv%1R3GHficU5PNJFcIa-`n)eTm zQ^Frbm$0)0W(k=1l-JKmGHyc=V`)z!LA|H6CqXH!;2P4k12-Ad!c+pAC(x3~%2L1w zGxM>i?~==>YNf|F4S*#WS|U^}G&c-56O!-J)n+ZMlEz~U1Ich&15)wiOx-15!3KQa z`Ei;-9~8UfkrX0ZZO*ixgUrT5{4Hx;l96TbNtk6AV$<0-ODPr`&~d3$j0FzWQJ=!8 z;b9oMafP=DQ9b#{&|EFDNRzuWhNp!3=m@>*TDqqDQ`o2O<@0^=e^_zKXqJZ@QUw}s z&N~y;x#YeM{Zq|QEf(*i#nu%e$RUykx}E<%nH;EHOI|G6;tL_B<@>gZ$M?c&vUIM zq~sq<2&VRd&=y^t0FW&B?&wc2H6p5>s?|mV^5c;ltOuXk3PfRwmUtH8rXCuz2YmOz zRN?!9SAKZA)=C^7#ndmoqboSTvV%@S16CT@wmG`>#T0nhOb zv?D&7eYA1ulyh@4St0qHW)!_wzhn>^4BxI@h9!|FgVPJQKC9a7G@n~Nysun!Uw-Z5 zkpgcX)Ks5oNn4?()ZuVf80Uwq>Uvo72o2WLb8eootq7|EEamVKhiS4_J3WFw3v07s4UC{j+D9FMpwLb*RBbq9G(} zDv=`aN|YzQWc~zLD#m5xt=Et6ra8U;jXOXTs!XWw#9R+6L@FD(p*DA!&llrJw-yfR z&c9+Cjlg&y3vuFlkloFj3`$i@DK+E9yj>r#Fdag7wJa4bcqEHxs=5L-y>X6UXP|Z7 zv?L$&PUR(G{a)UUus>7@q$Nm5-jyQEWtfc_AEMt5ZgDq?LdRe8t)iEfPshW`_jx>| z0h(pg4_RBHZ)t`i8`ag5=wbVLUHmFFv- z5>t?2G!;84+v;3lfOBw6+n%9G3TM;OkH~}@4yw3617h?`*BA0WQ)O+Rh=(r9!{oBs8}iYw8@f zt2{(__owLMzUD99De)_`J8!!KFrkL+%l6HI*KCfF)A0jQnsGAjO9reC^~Uc*QW?SA zYRe+wxCjckz=W!Q8;sEWZN1UMGTtZT3r_5v5`#P@9h_&YnEy`p&bK_suXetsFNk34 zh5pMZ6Z?fFiQ0`}&+XGx!EW-pIvZe5#Qpu@D+_(~d+vV|AuYW#sHl;(EjF)HlUAT& zRoo_T$5C3}KYiqf9k9yDRg+))dTv*k&;=Xth{M_&!Z+u9(?n@aZN-67r;@TIu)>flXksxl77OUl{LXmDQ9e*sI1 zW}U!&@=9s&+0Bb^y4A|V_9|StTWPw|T#u!|GtEE+^5< zuS-*c$e#(0Wvt4k$B=Wf1fDiV&+2DnP)X3|;>_&LH=<)3NIDdN z?bxd+K!^*lyvO6eC`#Bv1_==CJ3$c9t7tY~h}JYZ_$)&L+rI9cabUCeGJ5{e+BbM? z@UWmkRH;{?U{H0`;^}Zna3GKyCsWlc%?nE6GcWj8|9MbW@;~CfoF!Oa>nAid7Gl;& z>BR1DCo2OG+Quuk(Nikt@ZC{^ak}RqBz7Q0lZ_DoI{%M0mgGqa6(%jt0BdjrKQ^`~ z4A7RbSVmgbx_pbD?EF=PY<`AuEnkTY>5TLF?Hl6@Tm ztigvJ7oXt6>z=BC6fl)}k@^(jlHrmY1%Feu?CFw^--C1vDa^95L>92#Dq2Mmrz{Mi zfmUcsmLoR6&Y7JRPwH_p?l^sGYKC~)9XPl&E z=n|>J93_gG(p}bc3pj8n$~4@XjDY)L^*AZfIkewy zyk0uovJN3l{;{!zbaJkS;Q$0K28cWBZd@(nktCAkOV@PuZSz%aamoe`v%FyP* zCJ>804SgQs#=ADmTMmT9ENM@teO^S8lBknWP9f9iixXt?j&(iBR5 zEdA>+Z@?Km-bCiN)Hoj;+e$XhU3D5M{^MJZ1w1OUw~V9yHv+@bEEm2PE_#+QDPbPJG30VNr*NrC|rxZfv*=D@P4@396JUO=fryRA(MgpLUvYc zT3i99R&YLb^h63@-rL-0sEiTCTcyq*OjRJ-*qYYF6mECI%9~j&V!pXOoD98*`Pe72A&>{7y6#rCYzqs7moo z5mn``muu|B{Y^?Y)EHE#ERVuWb$B1d(pt2rjCKlIR`E)o;gD4;wt4}0-MukX(cmd zkj#Z8)Kq!OAqCc(4YOD6fp-X^PreIE}$OYkIU$8j9C7ly#mww(y2 z!UGB0F+W{S7;+&AoH)h|z+3Hn-NKJ2Ve1tj8rJwXYKT&fF0C_}=Wlpd#2O({EY3{+ zvzP?JB(e~jt>v|i(ocHWki##^It9^;X>C&*=?5(lPu2;#p7MgZ&Tlz<87zAhJS6L8 zdqFKc;x`R5KiO9dNb8Ldd7;Rpv*nx_%if41aMY+oxe<~93pTS0gp#K6BzyX4rrbL< zd;r7A-u%`e+80kcp)bB)VkmRL+Zwj9q9ImMslR2307m~H#yJUTNgU}Hhkep57?(M0 z>NQZ#TJH;C!m64jR5{&%JU_b_?>YLzUt75lY3`cfLlE`i{AE^Wr=M)q&SBef*sNvZ z5NXbzt}cOsX_yIs&c+eGDcN8Hxl$Lqa*)+ZT9+{yEWq2rpGfthE8y#p4DFeaoBAf-l$4_&rE35KlE#_lA#JVfY0tGD}riN05A`hz5dvm^+P;+ zK)QmQB>v^fhD>y0B*(4~o^oQ5l;~0QhZP3vY($ek1B5Q2xcc96C% z%3`xMxP8+C^v?YK;?ThQ4v^V6w(rf!?~9sd(Q+&CD!t5fSG+dGGY*F|`w1DcFv?o; zefOe|!}arlzbo*?bb&>Fudbyf1+G*)L%OQch{aZFfZKJK?R~TDz>0Gq(@`JHX70BA zC3X#95EmV0tak0uz4O5ylkr3D8Dbs5WtW|TU_N}+TXZ{=<3&)pymXviDuSl9^)iup~J(0OiPe^?L0=6O%pqxJjM0 zrz|HULZrmFgGU+5J>&ut?EySNPR>Mr;U|%qZTqdWGj+d)?#h;`CFU=X_I>24<>Wv$ zw~Q4^8+#pqGHIjYC!Wc1<(Ki<5WsfJK(4@NF^R$m!}3^p>(ia@rm=YlF#K&Ir#1%P zeqyuGZ0&x-du-18P9czKjRh+Cb>n6wcX>>0SUS=gcJZZ*H>{{-6#Rw_Wl^Flgjdu~ zdNWBQLgwRTYgg8)F}Fh%uW7^n%b5Por2D={pOD&zwG%BdLHp@qW&Y0b?^)`RruIzy z1$sv?%su@N3t=Q$gK(6&g2pP7pAeF0VsfXWEA;9diAdg}}ip@3QtnlY2{vmhf?oeDbXxApAZbN}rua z^8}YFa6+f};0&bev$jP2>d@f9!6~0}`Cd?+VH!t~06r#sotB(m!85+EgN1VBTaw`M z1h3Y%qY<4Nb-5;G=hEa#nr*VhE{*&40@?It>trF3mSM$XKmaiBfWc63>+rLs>N6aT zDA;d+2i9nO=nwU~OV#=JvL|MZtU523B|E|B5OjA`_+Uyahivaq%o|b@Mx-<NT|Ve@q&pCR@aM|XQX}%5Iaiq+E0n%bgkzSe8briCHj{@usIBS@W+8=c4{`7=Ct221x~L|R9XrAdt}tf0FGxCgXA`#O*RX)QJ$ zoup*%%Yl|Yqq4LwGy3K1XX6l`bDOCEX(d@w|EU}_!$HvEsV1fv?%fSoDTOwurOo4g zoq-HT^PJCOAciII?Xc|-!1^LJ^scd_6E#6GFiW{2+bZCa$6KW8q3Mb}nPVIt&C_hH zii&8?#iyK7iBqC-<*MV(Ec+g!0ytzV;8+7g$!;47rv$Zqo%*rS1~W%=#4>G!STvrW zH*tJXK+5(G6JKRzFF#Q8@rXojQg*52eiyxGgwbOYk`u|D9YNq}uro~3*inDqEDGAS zUQd~O8L>PM9O>#qD8;6gJf(gKrpf-ZPw5)e~;{aO%a7L{p zujj};l!Xe=7OWMDxdgC7C%QP?I_?!jGxzkzv0Bh#9*^Hc>b9eHodtff~d zqw@N9SzAji1@A)8zVMNC262DrpT|z}BFb}|$Qz$Z=AQaDeJ3VX6&i#PCp54_!V{(e zED46jD^^?+9rp19ixn5j!h#*RJ}qpP$v*LIk4nEPz&o^ZkJn4Hcd&vCHjg3puhO|y zjcjtI3j4q5nd#dK+$!g}@0?VZkP$Kaof21d7WqeL@`U+|-M0+0--qM4yqxcGQKvHf z!9O;eILAMKm!Q46^eeA!5so|&_q}MV{wDR_w`B0+(E|Fj;Drdo8l5c^KznXl919$h zFauVbgQFIqHu?ecNNw)f&j%3>IN?i$SlH@Cd7aeM%PzqYLGQvTI_$CI?DZBljRe$I zV-7M+S&wQBpVG`x_H8kV3FO_64|)+YY`mLlqQzXknsN3cm-}G#&pcT@e=VW1A(jTZ zB-$9ua@leJ!^b4i4Lpc@y z$-M7V8VnOMaks^=_haC{G0c>yPJNmeuveOxC>cM_Q$-E zttDdJB5l3HxsC%^w#X;C`_{0{0A0jl5H}NO41GW|EsR@H*w0?OjGk$a%h=Zl#`s4= zjN1S{y9$L7EE%1&?ETuPAV4qfMSv7|z0Y84L9bNfb;PJijiFcz-Zqsr`r?!hiW~Rs)xXbRU4e+Z0b3-l3Wuzm4fF62k&T7LN1XAb7^!A3CEJ2S#@5+n^F(C zgR^x>B+#=^M{-@35m-Z{^HIl*oOEZL7x14w(*DgD|3~5|ATu}t#Cg2G^WuQwmV^q3 z(7hJ~_ECXWDm|Y(CK2c?EwdHAHX$7;_`<+#gxk-bc*_p@T$)=`*X_QbMe&-}mIt4X z?A*4RS-8cgF`wY#`R_$-(@T}^-0`0DJe&V)2=h$iYY#S~Ig!-ch#kGZ4a~Tf9#SQK z%fI*K!I+(aC={|s1DX{&u{_f0ddlP&bo% zYh$ZT(I?zU8NNs0+L+OuBm$y=sf1-U=!Y|jIvCwCH3@QD$dDi58(J%+;vW9elb364 z?Bc&Ag5ISHz4X@hoL`@JRLfZuk@K;xhTF|aR$9&`KY2A1G9E(@RRW=j!f#BtbK1|H zRoBEi?io0jgo0{d^5#_@wO9M{kYR9N;(X(zu_|outOh5~U7a;fh8A<>d>CtUjl9l3YpX85#nRJ z%?p2*s1mB|Gh`;j_aTc}S&GnQt1=tuvnC}_^zI^91F3=va&`gF9Ri+MJ&#%VP%J&x zvHy4k-v`Zc6}@PHi_LJB*H5a$Fn`_}luP~SB@qC5GTiGOJ@B7DI=$SsWt`?cd89Tc zDAPL~)We`@@7`;o2g$fIwV&TE+m{`H;_!Nh;c0?O+`bK2JyBR3Y*&*`?rSe&gmg2r zdABxg)8?YQo8vQRw1x%z_Y*mZHyKC2X7?3SINVhjvy)=Qa{ghEgidWi(Gzk6QFyDf zzLv>A@L_I$L<}8^V+}EF&@NKZx<5gR;)Xu}g3ESVXrsK%3-<>NVO7MWoFQQLZ|n}C z&WD@xeHgMW;+9_}xkOB(2h3rK90$*DC^|Glgm4#GQ}RbwoyvgvPY@EE!Vn) z%8=1z;9TZdt)Gz-`!R0I@r!XmJU?8}2JmT#XhlsXA?Hl_)GJeGbLnOK{hgyl39;xK zTRX3dE1Y3t^WJRQ&t(sI5j|Dd}`%u55nY>L+Q=%o745R*{!qM@#MH>7trJ*70b~M*po+_NI zONTX1durE~S>xG)5$?@J06p;s61gPq8bMk#mzOR@X3z|kpH#5r7Io15*Re0hoMVKL2U_U$y5mCnqrllDtRpMwH(o*EA$shZR5ptnuY?a+-N0>%B(d+V(Gsn#)<;|R_$AK#;BHVvd zj+l|trfJXEb}fZQBt!qj|K?`}seVtfm$zK5wzpR@Q9Y0lpFB!Mg(Nq;X|2i9*hI@I zYb2A}IIPRacO9ZYwL*@O0X5{mn@(ZFR(f#y|F=`))bZow44|+^?-YtH2K{qOSF6}S(N4VBiwofnxo zl^6{qp6L!YVP-_Rw5;5G1za-aFVTEv=Q~c9A+?vHA9g(m+vkBm`W3wf^5#34F^r$V z6q_bViB}`psd9}*A?yalq=UuFESLVQ(TLH0m7=ck5;NGYi!C-KgS2ca??YS}jzZoI z6UI+1g}i2}#nC%E8-bKfaS{j!bs+ z^}27ate_DT(%{Bp71&A&+JAWZC@_GGkQ_-Q)dydBOb)tN5>%JU&S#PIgP=KiOZF^n zLch>Ia#iD1CE`T!#0G6{sbLO?hux@XN7dvA)G6noocnY1oEjQUzl#@?=7#j|N zw4Kg^=ICf%7TB5+satq|zBQNP54QrITMYCAQ|JWlHIkNmqbp<9G$71IUt3hHma=m1 zRbsG_dmmivt0Cw!yT{>q3Kv12Iw-URyIMyo{g3kD4YV{wI?tQ|G2B#n8WDj-qo;C7 z;|<8#sol8tbX3qouo`<45uPy|0zbf9?aoxE0MuIQ%aq5W3bqx%aP((B32Q%o$?5*h za$$7ZwzSF%!MO&QwfxcoJ4bKcp^07?h1A5h4j+@|IRsn!)V)ANO}Ku(G;VkpRJ>Vo zogw9bV-VMv)lmbiAf!z?%Vt3=Cm-H%${PNH+Yd|i*z$R9beld`OE$-UZa`2={YF2~ zb$i&D3vI(3T%j#TAMv9*QQdd3t0u3|d1Td*cxbgM_;Vp6a;a!%D;Z`VjIcYq?^uJ; zrrQymvN~;%u$L#EQIO(@k?sj1~pUoZYd|>t4`_o)md{;8-CL%jjTm3c3#6|`PY2)qbfdfP?e+u9B z%9J=fBoR9Y9I;zqd}2y!x4nI^ze^86{1YMN zv^!Czcm}tl+(Q}Lo+?V}lGrV7+ZG~Z0+e{wpR~|Lo30U^#@ldC5nowXOc~vG6mr6M z?6e3XyqxuD+t;+kmA5kGLSy{IxR6rgnj)lYIK1ou(n8u@`__-+po`p7BY5feXzGOv znjg{DDuPz*mTidkym2}eqjaKg;d2TZi z43CBJV7^0H+~`gmZGhNcdL z_G}#pa3FT9*F}ahwK3WN=75TuQe$tC0X}biEm%kn=zPj#*60uGDGWQb=X+xp@Ma~; zb_U3Gn%R;_vazgok463nAI!Pude{d^YAJK?8SslDUvaCnE!Q$|fjR2U^T6Y)+%8BT z3tTdWyR>$%J7tsz5a4By)Rx6}jwxNMJC(gX8K%QFcA4ZxvXs*G-gP8vD7jcHvMYvw z%{e)_pok-x@H)r>Fihdg>YE?nZGr^Xt&V7{YKl%udn)OTaPMx4b#vXebwfN`a#Hh4 z>S!pDhb$ii5PB&I@0Gr>u?mLssl_9%8B5PyQ91bV#A-11m!r&nJg}srXs$#|bfVay zv!D~rX?V3(QXUGee4ZV7GtEC`>R;fpbX}mroTC4F{oIkWb3#+0MH^5a)CW^fx@ zRx{XJj1BxZnDw;7%n$IKr>Glbn~*u*-#sKKbg_m90>qT1g91ftQW`}Px065HYK}uW zoy`pY>EmIt{loNn;5<$=fF|*zFMJJ$;u(RfAQ$~f)8v7dvjCwQvmPUp z(r6(AyO*4IO8^B&$l)13OPz*H4C(K;Ma;XVp^Ec_+riuYvK7l&JLqN6Ki?Epx)F#U z2C3GcNdTYkzu+Iua*BSfdAUmp62)3dUzO1R^6;XkmGN}Z&+)n!ow@-d)QKSScX~+r z(&2a9vHqU0oPw6gAvtMQ>APoOYyoLhj8;U#VRVHz{WEKMfxc{ND~o^VSoToWVzdDp ze;ht`8xmd{8|u%KOO_T>9XL`nxoO_bhyWZQSI4i0no%O@-Kfqry_Glw;|-Tph2g;n zc3zV;C8^(Mf{UXrGFJ-5)V26dfOmPn;N&-!K4ThsDz(#Q&o5gZ!XA7`wO_<%*|9p)u-pa-K z&Ng`*WY_h(p)Pli?l7{I8?hy<=q{;c_r|vvI{Zwq&Sr_s3hzvmCj<~oLs!YO%RKo% zq@i({oT*sjp%>f2TY|jVs4j-IMN;4aBK!O6aFG>OAn+DphP# z-aMmfr%gX>&Esv#3nTWmzWoO0v6-rNmen6viXF(ee$oNR2JDl{hRxEI=UG1t6upjFxV~?Q2N)3#dqDo zpBG$N6BT)-U#YWVk7!0vxv*6*|0G*`kR|binl)aTF8jQjereCzhvSxQ=+?o|m0YKl zEj(^=Wg&mktO1ZbELT65Y+<$P9YYo(r7V7n5Y&0^#95f`U&gr9K#I6xz1DSn8N?~w zwCisNxAJXjCK2EAOX|=PmF&q3Yfr);6PA^w0pZ}WYpkmI@4LkpgUO~^I9@=zWsjH# zkHI-KVUcd87M}z#*9{IE`XDHO>FOvYK6FC%zvnWTt@x6t(6D?fBr* zhC&_MYSo{L4k7`PpbyJugR4-;rv8DHzJt43@<9=UM}^l8M#T?~7F#lac8 zZ=C0#Nw~d^q={G$YoAVhpoGvrT@>CYs}TW%!_1A~GyW+_4x@9sKqRfD^vahHNx#B| z-WblIXT}MSD2+!%7>2k@HbAiL&O-V?csCnkTGIV#5`Bw&q#hr3lxAWaNEa>){HI^4 zJ)&;mg-8%dk~3h~%+~_c^kZo+3|xk4-{1E(V}~lhwLC^D3hojwzvr9cu!z~ZW&$9h z@Ylg3kpq7CCzyY;nCXx)F7d9=x5fc=oWTmQj=zl;I^cVymdZs8@ss=H)De{)P}KhXa9Te?0D1K z7}|GMneB(is!J9(1dHkcNM3pVb0DoS^mFUwj!hM0u?~EX5ZLU52$%*^UzWgb4%xW( zME)@bWVvWsqx>}el1|S+O=e44oIQB9fWK6fln@FsI{pFYfU-FX8cJ3gjoXI>GCkEc z6k@|xWo>Q=^?qGN;=rRLy!kM4fK={!I{kvKBBsxwn+Dg#nR*2}gUJ;mgiBxOixMxV zW||j+(9Ltq&0T%RFEH*FR)C7QB7+dC=Z{ng`^|6?Q4OosimTZqX?n%>VF=5vkaEBG zprnNN4atX}gaaL~&lQ}LjKPoH6zo{QSZIFE`(xbQq{uovf z7Xh3ryC#_oDx!9N;Kuwp$C^W47FUrDRM=yXYGOJy2BRnGVU$(bgnz!^;wGCr0r8hK zmpkn0Pc6JY2~PRI6@vw@Gbi%(YCtm|#s=~#4176PMDe{{(%`zh$`{a%E(TM9!Z-;5 z<7mys=r@z8y57eQJAyG$2;T+YSSx}X9)q^Sr7wgOT+TGQK7N<}m~)6;4Z;>9{e40W zy_$oKv(7FhBbEPb)5npsDmU@crm>v!;~`>J+Rs-F>&(Mf%PYV^g;|S#~0@|g}lu` zst=tuEqY~I^yYMb>cqc0u-^i@7iY@zgUb5e)OjGGhDx z*qsttbp^j!v_~5#YIbKk`Z~SAcRH6Tc!0AB2L)v^qcXB4jK4u0?sAgWIQlB%|2{=o z1c&Oge62%)&Sti1e)_>KlVoBjA~4d@Z0-0qXZ}W-MZ1N{o&XKMQ0yUkhf-LA3zT|O z52q9aFrucZAwaquKL9+GcJ5AsP+ht_`0V`KpuqFAlSqM6`PWVINMb>BVciM)aSA@%P^U(6Xsl_%Pri&QTcXHnX#@DCTy9>Nwj{>PWx}mnvZtaDT^q7Kf zuGS^Siygq}q8$q>gVE0L@khirqbuE#l#|B{fclQ0z8w{lOCEFz-uUwjf)jlY9NdB# z|H|gwgkTwx@8fRyMRM8K8pojCDZY)IF`K!9dvQ4G(1!92S0^@8V8706qZ|Cq34n8a z{3gTxv;HcYvx-0@Vxb%Vw_f~wB$950%#*~6!RG?;0Vl_iAatt}Mk~J{#GL3Qs=|IV zkajVp0LNbfeM6tV(%j>3ZiV|6GZYBLn)M1&CnG|Rns{FM{h-CZRx01;w_TnU-+eCv z_mBR;%CYM1lV}k|H;foSfact1*@~*@ewmWII_G%~`q9s1Ap9&dXEYgQu--A8GwRDb zD%B{PamM9poh!(6?&gm2x?a#H2`G?poh;AJf{6mN-99x93n?z!{dc)b{+|5{WRSUA zy9gonf_LI3(pKI70)+|iOSQ3~EQ)njcai>uQlnxk!$8rTjA~T8?Fg`3uM?n09`fis z2O#ICysjLn7q}`5;bVW|2xY69xcS|q+oyCedvYlZGYQTh95a5;U$hsQYeMT>ltVXp z<{3R>Tooex7<5!f$2{8_t((LoWO8&2DpnN8G3!sUrGetphab*5R+-rWlG=8{U4^~{~wPgo?yC>JFGvHUsaU`UeZeI)_r!q>(x@dRY==`vkA zDhMb~Op5Dh$1c-ahPH6~6B{!EtS6gUmBB=N11t!=V8joG8Uf9K$wgPT3&TZT(X%3bC_@p`QBvXS3SPbcmVcDt&c`Q<3WNs0jUSGyDU z96;m?2_oHzK*rlo+4-3-A*1!V08^JmTs(6Z3St6u32`}0;glWb@ zQ``_l0~mYumIMehLY7=TSBQHl048ovu?}GogVc=xY^x-g`Pau zfy-Z$RI8U>3VG=VZL4cK&kD20O%d)37xS@t6y)BopFNJR3YCkBQ_I`4`f)h%ZnN}V zKuKDS2+Qg8@f|<2X453io4`fnTp+lYJ7NEmx=Ce{;uhwwP0m5X+4HvV7H+37`#hCf zV9K~8-=F*c!u~4NiUPN(FbgLcP{|tGi z9EU;@_P_C)=7F7H>B&#h0F{M_+ZVJSyL-=(?VhwxF;E9^ zFQx1gpmjwmaU(pQE3o@8uUAzy<#FeCd=@p@8gNzIy8sUdfrkt4{tg6|S(lR+1$H$5iYeY)CGv7Ki~T1gQOo4|GbNVEjg(+>w7~ zxc)dPzvk57mL3=w zk1O^X1$@&}g_cD53+tGv>7km{u%Aza;1js7=2+D~m;{*CWy-*CmM#CKZr&m*b30<# zU#SaZ*Mb){rel#|pF>dYtnMfL3jzReWU0Zn6d!T+Vzgh{%VpTFd|C#SsYB8Z%K;6x2w=9kw0@9?VM$$ z0k06LLaU6{d*H@GILHdub~yT1E9L}?f2fBa>tpypok46C|(k0E7#6& zhUg|sc(l_S!yn||rV+mihO9a(ssM0AcB}mgg&Cdy zM#0pw{iW8uHR+sOez24!=x#KxAXA<<4@#|NyyG#8U?xa>CK785aq&!*artJ+Q5B*J z4U@;tv8W@xhKX4fABHYP`JDMLuA=G;G(45v*fWzZE_G5hCT;MBh56;w6-Kqn_o$S= z*6^BYw+foYGxu5vy0Z#&QlOkTB#Pcd#LJ*rvSahKkM z=1&bZc=ff=VX`|T&msx?g5AW7aJ=_cN^BDSCgjPu>+uZz`9 z(_7`{!R;S~Rp*ulmKIhy(O+;PU$O)Plwhc$uwnQ^Z-L2t4uTRA&z4HI3KC)%5yAp5h+gvCfo=ZLhgKv1zJ)0lyCDS<%Orhjx7DimU(RRv7yVE)C3AGAwR zQ*1(merHA2?IjCFmh8*c)m{Ub|15~`sqV-NRo7} zc1aTrnGmCug*OUDeW>l*_>ZGS9)i$%e_C)^5VlPn?U%;6<|;|uqt%PEZaVIgOScQm zXPscOx`OU-Zi)WHf8)326K=)w@5*n|G@g|hn?-A#h-Rx7B~RV&z2LNG@d4y!^JRpU zX~4car>khAS|JQ1dkKdW5(bc#7&9`AH_=o6;m&hS%V9$d6Aq|QUn?Q?eow@%z$dRVgmzvh|lE14_E;MBb+{etVNvUg2SEMHltlXo#b*s7jSCyj8cTV5cut z^wWm@HHWhN6y>JKSEQZz0b8rb@qB^it&MdsfT%iD1*Pk z$b|`5MX%}y-^)ci$ps&c#;i*2f_X)N+gvD!xeNN2w;HCf(zgOj`%HvWgP5q+X1N=(^#`1 zh$*!~-tJcJa)v@~Ba)S~TR?Gd{T4GA(f5Ily<6M*`C{1uS`1zta3m988^2BN{SIQ+ zH3xLjz7hb8^uxmA1e!!uG^d^7p2Rk&k@VgyR+kWPM_(#vkHXN1|JWsQVcmwiS0vhx zl!kJjD37~}G`&mNnYHQ=>tNA@MvkHz)f)83FdXIJt4dEL6Ge+yW~GWcNmkwwin?G; zXlm7U*l=loe!uqnQLL$;))G7jqmYNXRAlStYCW>9>w1uyxjI~Es0;LK0#HTg@t(~B z$S0t4do@PyPkfS!nj{h#2n_bN;gP^j-n(uR#DtCGO5F6{;f47wPuo{N-rb=_)Hg$x zH1>C%g`gMmd-W3?jwc22k0-9~bOY}Mqgwi%(MMiy{41EPf8%`s+w~PUVbNM3D4tS@ zcqwNdC3ueM8iY}Bax$zOCw)^G`1KIg5k2ay6M4>qQVWr4%;v*Z2bY$o zssaAIV6h!JRw+BD1fWHm7)Py*-PyR+NYD+ezrrp(ef2u4G_TWpAT9i&Z|x0LW|9E( zpA)&&ABR4hamV`?ZI+~SrB1Taa|)-?3^!?KvdYEcG$Eg6zXl5h=SGm;9=1s7`&lMt zmr(#ypv5Es@$J;hSjYx!-Q-3l-oQAmj0k}*GvbQYYmj~$N24c>4YEJ1Rt-yQ6Wd@$ zwd9TcrV$=G67QLJqw4?LM0~+&&Ud*$MenR&uc&iTNrEaIIZY_Lp6CdJ6=O)0LaE&X*VoBp@(_}O7K>5ZE4u4gis2GCB%xl=Lv88R-V#GVbEKQf?uvx++IU#tPyk(z-;v= zr7Scg{aysslns2ga5V}{ESeq0`nbq^0*d~|<6__?eFOEs<-Y}p;P*22Z)_eX6Qy=9 zBfzHIRVMTva4o}EiFi>8q05VM?sHKrwh;uTUMq>X&`y?4{B*kklY@4lo+gIG{I11i zVgivqyDs<)<}p>@)R*_ISK{yPjiFgvBe8BUKUmMLU@b`rJyR!K5SIDgwM&tZKFUP|4tdQbg>p()7Zmx)cB#i@X z*3WQF`AQ~DfPTLebMFGUy#nnsL*h-fkJ&X=DBxiPbc2&#HpsFQK~nbKKZ7iG>cLjI zM=oycPNWZFWxf>Hqforqv@1r{ns8ScsTKx}f@z`Q{Nu4d>1aL+}& zwi~1*it23|@xmlb&>9s7RA_r!+I`Z=V)pOMh&4i%E@|xti%-Rrg$)f&$UFccK;FOS zcok?UQ~y;EPJ3FJ?6uXvNTXDmC=^wlOTTy5`&gz`p_?5^gc_*VZWsUwOkpr9nbb?d z0KFm6nA)Mg#D2(4Q-8cP+&6UgUrN`ZejT`$!DtB5rhtJ_|FJhc7!rFseG@RV<7|As3=EiPl}&7`kzJJ z{V_t8oZJ=mn^BFp&Sp+0q6K!%p5mY{Ucbb11UhF>d!ev3np`(vvFQ!`M z$zV^7S%`WxPYxRt>AZ-!`89-n`I@$M1TtdU5CUvRk&z;92Rt-*{6yK?Aa%VPtHJ&( zYic+NW!%1HitogGU4TGUg>wD<5$%?fINEjyW^^{a)u}cAU9?nu))AE2^`uDA_i8cg zyTCt8jk_wbq2ST$r-xsu3wMq9P9DqYD%@N&GmHa-%mH>1&(06HIU6nkd}yRQ!!@nY zkp048mRx6A@1veV7vPS_k2az&Y8hc?4AU+#TfG;U8PdV0lGn@>SoB&1ERB? zlbGP%tMUSDU_LBted9y+A5wG`lJcYc;@8BpfhPv+Pa!}+~aOdB6p0z^2@VrvqmmTPl{7g#9;67}kVMe?Mh5NyzAXY4dp9HGZL`y5^ zKo!-+tIk&O#ufb#XE1Ud+hZ%`TE6jDNi*i>@dj{86fy9K<5zn`mftVCY5Nk2<8#yN zcn?D5d@BVeBDmqba&(!_)aKgs(h0t9;ZrUvxl=Cm4;aRwG%Nzlo5jLLEJFF#1303n z6kJdDuNWwcpb&t+u2nx-HE~#d31-c3>!OfY7|k@{mu;Qt z>U_>egxzp!EYx!X#kfkl-B}(^^E}@Y#si?mwgeT*xrC$R@EAF7AvFMOn7zEx!an{e zlF`{l^^3zJ)=Z>T#?e}iD^M8cY&Pe=pzgGU{49<>M9=PA9pLyNWdqqoz>b&>)RNJ| zv)=@oRm{#ztP8QG4kYEu>@}>QrTE)23m5>GY3rqOc~qdhCdvU=cB5MIN2U&);8)Be z-7gN8R=IKMf>ykU0=T?x=$anc=H@vWpNv1qWCdsgRym?F8CBvaoCGU%ljy@(p{C`| z0}Eq9mIP~ME#V!!<6}-$M@#ol1Vy5@8OH~zjpPc`Bu~Tb!N^v1^P^zX00(xzN1Ec~ zDuN^!8oNyU@rk2#;v)6MXqh9bv2tWT2ENMbU#AIr9I9B-9VhCXE|e z3`?38@sj=BLM@Ubzf7#Lu4AvFkp_3@=^ff3fZ6w&=j+c3m<-_K>%0k7AJsqi1Z zF&Mu=>3}c2=x>p{uWX?M!IX^P2!mON4;N4WfS0S%;$89qvPHaRWM;fWv-J=l zuUP&<@$w2lE)U;JU#Q-{gEXn?zXOxdvG4;H2*;Hhpe~mXx;@F{L+PgTIJB*jzDG7@ zzvV)Ay8yJ8LV|;EYZG5ZgjIl54xOIX$MM|GNUL^kB`SgBsZ$dq>t*1u0tBZA#E*o# z+uD*;e~qNoT&9%bx^$C5)FH$iUpwY}k!E5phtBF!t~W&T1u1fS2)j@BY95Ag2NLS- zSP)50WJ?{&IJV;ub%GpOIA8>~@{D6pWBz)y$p2$rO&jJQ;yOzkmYqUJhP~};(VKn{ z3}Jf|ClM+&a6%5n&t&HR7kxs@HXa(_-cXuf+%+P0iUut9Q{Oh#2%6sabKt8O;X1UX_b)aQht2U*&OB0Ws=}S4R`G4un6Yv4#hf`kIDv0l zVZ3YZKHlg!MWvAqk*hd$$5_31(pbE`Y^(zx6v5N}`fZIscXo&sW;s(9pfjLvatrJgoIKiAn{1Q)3<>oL#G|fD zPvh|^5z^c0X*B43ARbC*QOx-sJIEwEDIT;7Y#tLm7Z){ccaW7v02w0r=4~_%nCBvz z-So>;HHT4(@yjR176XC6GB6uulTA&7MmcdOe;|Or%`mjr2rOYL--fhLdK03w_v{Cp z?V%awB*e%QKcMOkablI9LIZ;^Pbv=;RR=?WfL|0W;NbEh^yeAZO?@ z@x8xsq-J7?8s@zSSb~K*ZFvIe)<3sA+)>dPVv&k=JY+I`t)hi?%{HVWDY6Bf+v8xC zqT7DRlw`;2(!Af1tniJ05JjL@>rHbi(Zg9ECqf;?!lis@abL@Oc?HH$AIq>#)7IGz z?J4WRgGNVN{^dq|M3=ShR!L`ZAaO%F7F+MdNCNFI`jb#O_A&AblV{1I$`rwucc)^0 ztS9b(Zc^-uvREeO=Hc-E$+NI{VPn3KUv1!0cdyS;&h8km?35pFfXeOAWGFO|#+QTR z;%$=>DeD%)LR#RuU}_nXcgNA0b!$fBO`<_bUAL-q(@F3jP%VZ9keJVOdFu|;7M~Tt z*v$)uGZ4ehlpx5O#K*;jVueP#thR-nRzzXM)_fg_@Rv3U z8N+>{)ku{w^~T7nN!MnXk$oVF9Njla5M>!OXfMbRRDLc3l)k7ujFrOLMPZjQTwqi^ zXaNCrz&|t+TUo^?aUFjrfs}msxDeYKTIQ&-eP=~8&fTiaFYHi5Dgn0S^(m5gFD@Ovf5k!%K^FwUZ~$jD0| zC(2oSvi&aONC>6sBhntPzvnJXKDq5Zszm0BFvWA#6~Jm{dNBu=ml`9^h{#w;Tn*;I zLGg2AkYVM0JGGUSnd{!VjfFN`o~5!!yNp8U^xU%;17>3Z z($m(@fTi2ky^w4lu*LJY+fv-30^!u&j^^-f>zQ|3co%uMhI3KO!zPZT7i5UpUNkZ9 z)(7OYkm*Ab6C*uma0-zH!Ogj7aqxJ?!5h~qL!i6ub zT&>fDr}Y!|!IITxmo(4%d+a;QBR(_DvjihRms`pswgFit@9F>2BGkOhC9HSpZ#}e*O8I=S1@}U+svM?(S<-Z{f2TS4Yzv0l&_$w4aJ}MlYjpOWhQkml| zU7VgI0JX`eJn#dC2S?KkQu+<{8>}5s^Ufu?IM3N|4&#KH1If>kC?X z7*#=?GV3Bo(D#wEaPgiAN%ScAnaXK;G5u|qq%0nLU;|amS2{?l;#D^s0Q|(Iyd~s@aRz{Hhbnpb$?Y6N02W)_YHX3MtIj`mbTMh60|PKx?lDr2n6Q zt5|cuipK3O62pE?@=j2mzZVf$Dn68#l3f8VkOF7On^94y$T`}jyLKLxl-itT`RN$c zxMq#@YD=Uh)E9IRGWsWA-kqstj>lxVQ%Zxt76mXPVE;IsW&D@O#aLWkwF=+Gi-WS6 zP?$KvFU9U9<8`P;a@ojA^woqsO zEyuLu_|)H@;gI&Q7Q{8Z6HJW>xfq_yxD|>K5v)Nd2Jjf8nDz8l^NBBD;J*xd7chQf z<9at`6JbYp2{bB$1<+pmvJFoz1d%)aUSG=iaP7wZPmIi|Ewu|>WaJ+m0LhE>mX!r^ z5l+1D$Wnx$nB&r*O8wqRPY^o(TY+C*h$BBl<(I2EL+F{0FZTrI)Z|pL0KNZn;pJ*x zv(PPaWRXaqvRB9+c8FVMJU%iws6Cex-D^Ak+H)Qni#)7+F;wQPmqfF17gD(jV7|EM z->{xQF0>CZLOIuGYB(s&F+`1xR3#+EU6?}g&!;lJ#FL@*U`^r1anQ)s>w^m`{jsNj zI=bjH>|2)8I-9dUba`QohO_!&wEg^P(a*1@;GEZ)wA1)ME#&bW+*PvS!^Ui$`vi2P zX>T2t=0|(8Naf5r>r_bv)PzEHj7PV!xgU?DVkw}lo0Gdrk>Bt3vOF&$XY=3Y{MAYlK7l)ImtKZ)2?KTA;8iI zd$8S*m(IG&8*h%AkznoCgi7oA!HSUwkl63q)eWjaN%+NL{bvf~FS4^Oe-)xz;g_7s zD2|W(qPYsaoY_J3To@08xv}UtZ;2$1(qlDh6B|q6**Lbb*p7XWAVo*tswbwQ@R{yE_ zbZ_TTujncN829Xd=@k>xG*Sv2FDbF&sJ6i%cQU9t^{2=z3A!SqY?V!HbSO&J1CNr^ z&}M=c{!xG|gFM?bo6)r6qHSEv++fU15DG5VT_pV>3u56NtEVH;lQ;{mld>G=Ua^B$ zxA%)isX`RSqgq7Q727-#hSnBAtEZ7@VT@U%=A_7S&2QKG<#!N~A*^epPjKfTYWv)Q z9W;HuIp}$V6f%iu+s&FMF&p?B;)nQ(mhl9Khr9thn zti}4+2Rz6OrdeWQhq2DRa~tVSuM+Ti4J!v7Zqy4q&xcP8*k*XVo1`{stfKne@eH zviz>ocsbC9S0h)og0%BM%c2DYG6;43p$4rdcj4_@d*9KKWBPBX@s% zcM+^(fPZ%=tyyQa4*yigWtc)nMQ?%H^%Le@A&@j~BwCLd~Ya6V~0fWcYRM)IIDiJAm31+!Ux|5k%YxsfH z`I)EQ$tJ4)`ogHOa|ERYB|BBGX%r(fq}JCKeIognJ*_qBwK0cnXxQ$h@6_;cEaioY?jR+;9qnw5GIIB}Tv@yi;{nMoGZ=k}g;cY=iavnk}PBZZqIQ1j|FOrUtP9 zash?`3&$NfSQ{el6}cqa7o$7y{hGx8xEEQ*-iJ`o)8u1C%ffjHS($h%jy;o=5c~$GZ=T6fa}D#goZ9>4(g5J zHnV3~?lkZLw(rr;K@-01GbcP;0w$V(Ua^SZP?M&C>E@380);nXHjhU`+zLHmN}41DqjT=IVZX2SC&Z~?=pO+B=EmHUih&+qIOHy;)N zO6$=!1*!#xY` zWiLUuMf7?1ok3+faoiW2!I4Fj*I;I;oYOpUC;}dKET7BI3St(Md`*p@Aye*zA z!iTbYBEhm~qH%Q}_6FjdcLZ^{Ya1QQtqKx2sI1kps;<1?dMOj1`&;Ku!KKGydhvtB z0IK#`Hy13H>p738$%fRS>mFWg0pEJVwhBoHilW;`p`vAxQSR0tY$O#2fzz?kXi&Le zfpm-k=doh{fb;sX^#dL(%k$l_fA89-k^HDRwd!HD`SS<2-Gij}ef|;RP{lxRKL+v# z&8M7)b}2PB-muz1SLKC2__aN(*z;b}sZIi)fnsk4;%{W7^v=S$vP$DE`d^k^6&?UB zr^B0}unrr;6NOu5H$XQ=#st5%vM)Kt%?NHy!$p?YAMg+1@m9EJHvR#D`%S>mA&^s| z?cl4%28#dblzM`wn!DMsJ1r3X1?=VIAnH!092#Hie(k+{GR8c#rY|88sXEW&ceR@b zG&<_lYmC4z;9xnr<=6Nd6p+KxZSj~J5P;csa>D!4uQ>|F5sXsJQIJ$*fYTpEK#J<`Xihrpm|kMhcK zL`QK{*TU>Fw@yl*>^ALd%CWsWlx&iCMe^Y_Mb-wa;`i#Pgo|I@nIzL}li*iQ&<=h* z1rnWIFywXs-AkhIXCJvIr8MeB?40mQn&-!xi)EolQ?Yd~uQhLZ(rY!uQ9zJ+m8@N5 zI>V#gX(ppeQHU-)P+dXYQ#Usgq2G8$bSf@hloy6;nKDPAx%C`)xWO?ntCQl77{% zq6PQa1eQoi>OeC}9lkHUOtkdzMO%J#%u05HuV43%)?>Ju&!!X?F38u^Qba-Rci>CDQBEvfKAdQL{CS?P8}H z4h%N`P(epdUo-*8*Loe{ z0APEeM91&m*v9}`z!XRenI6@4>67l-{b*wiVMftGVrhulJ&D8T1hPhHI%;M5%!?5e z&Be4Ol(n%~Hvd9E8*r1)gh$G2<>O$D=8qL$-X|G9)%ecOxk?Rl3ZxMOvE7Oa?oQD> zr*EBcNm59MRQ>Qi5~vnq)=4;2`RBAP!*f)4o(&1oE-nWJpPea_iunqnY7F)~)5Wrz zCv_CMGMWc-N_WcwGJd@+#OTCJ?PLw@%G3rL55lt|9Tx`_0=U;`GSLLeCe$X;^d$#y zHy5dk;>s_9x?$t(}mDNjsLkJ{<|NT!T z{ygMy5b_~|MwOO!L2^E>ED*Vff?fYzmhnA46fH;Cc%XKp$pA5j0wyuqz;B|1P~_k0 zx}wcXTV5D)yk>unOVC1Of-GxTOKee8pTX7cep^W_7+|5_sd~*$mD#O?ILGX$1EfKa zvzy|5v47|wu&c#nOKHdM#2JLa7(L~aM;z~SMx5r7U1%2CT9_la%y@WvC&5x# zr{`{ETRHWmjgsJf-vCcVq)c@&!U@6CqI&dk$xh6iUFQeI!$k%I$vuj`w`1H(v|VPL z;5VYiL1>{3)=&}~-w5tyn{VHV@PBzob2vQ#=s#u}Gn~l$LSN}!e*tH8<>+R32SXU! z{Q1s-_sMkO5}Vo`6F4e$1B# z#JBA9te3N=B0fO2s9pfXCIp3&mQJRXGG1_2q^4QCsv^8XSzkzFlk8_ZBe@@4F$xwMlLBhLAK2HVskN+ST9|H_r1-I&420AZkY zyc?DFoRi3@U=?4I;F&&c0MA-CB4d_H*DbpBYPD)ai^cJ@x!{8)DNv*T>Ke36!{Wh* zm76~x7mExv(dq}1Rc!>8fBO}pW-D~RQT|>sPzaO&MqZv*Pn;z$+IA|rhg>u7>u=!X zorunZU}OgD0BLh4;lDKlD!vdwG{rUA(XAlO0=Tzmb#=(*_W*g9Rdw*vtPfAQ=s0!b z{R6M_q5k|Gh;`VZ5nk`|;=wMkrnAMS1;)E8JsB+vnltYHUou9B44x#XwkOJG!|@ys z1>}9a56PQa$eS_{q2Z#$bEBz~1Fg3*LbfTbeHO5OSM{=rx0C_%1Qv@lDd?}1stZCx zWkKE8`*)h-WVxjdwc2jS)6hJg!qj9L(N=us+JG<2|K-1^2Xi}&aFMFPyJhPRzbGu` zQK7d@qi=yTwQQ&Zl%ibVIZ-anr6xgVf=n)Wm z&t;(oiI|0i4aInIwt?QWHHtOs4SboG(!o{8Izn^{#oC7rSg%ZTX;`1QvMBo~PKP$R zqnSGQ^CggxEW5YWse~A5pBZ!mcYY-!zJB8GI0pyeLiEytkk3{>pU((~VF}@BpK-DI zgTZ8jp3JWyYBrTRAnYF$iw137>}u%*PnnAME$*;I5+~@&oU>0qMSMmUA8*%Bg-v zry4Ol1enHJ8{%B&GUz=LGE(Y#OEKGqu4RmTFbM5vMygyE=LR|K)3l34aIuEDo599D zE=}zO1Fl9$^Ti^UpKPF&c99Akt4tSje{72`ZJiF3m138CpH#uP7}JF~ahC)#MI!z{ zq^L`SjYe*Hy1%mJAJ`W0ac$dVBNbC_wzXM&jJuMdK_(l<5)1vO@caTu@i88-h*XIO z{X&?uQkiXy*Kq+-tOwb0wT_5N8BI*2qTptJ0lL{gw$l8ri1^6H?|2a!h)UXPZ?~5t zY_v-;e;64k?OkT|OaL@Zb~prA>Zu7w2zVD#q`MvxaS?GvM+R}W$>*_td#wj`4|71g z&)U&@t;fdLj2Ad^rm_Ly3%~LdoUdooRyB1XW~DKBOArd?*?GHJ%2+$6X{C}=#7oKc zm{#agdQnx^t*)g#WQBwqSSr;F?HY0uuYiRAw7DN$y73b+Oe8Ul`Srf6T`DTPbwlVQ zGc4V)lvPTrqZfX8w9fmBlA#%Dh~!1`I_OHLwQ@$)d5LG~`5C+>_n=O{`{+_J(AhwJ zaJL=x*3aPP_G8(EFk`QNW>wsr&Fyd1L@q1&w{sLLmQJ=gF8jayarSPHKz+N3N*3Hr zW6TA;^FFdGq;$LNjY6{9fD)F4EI_;V17T8ES~Y?7EBbV1lmMufFIGDuplxlTOim@L z(-}rSf>YgQ-W|gY&gre9#eTGn?{IecuohDy*1T}%qtY}Ll+E->Z>J6%$Kz{2Hx1+Wmphk}Ef?O47wn>I zNpDdFDdXo*tu}HoX=?TF=Yyg-<;2gl;TY#PCw1;auV^fj_oBT3J#daj0#)^4urH67 z+~utm$S6vXp~<9H3`dPquhZ>}JsDrTnicbo5FlS9H!65>KO!Co7y9+U$Pg?0uqQ_a zWkBk~0wJfr!;0TzMOl`uolr9%5SSB+(eXcIiD~d!{MV7a?lsu2>iTL4jR%~ugmLC z(Iyfzhg{27U$%_-hfYD=3|=9oVB0_xh^A#|!Dp&ct412{lMrOiPCvD;mB1QR1a>a4 zYiiB7CJRnW)K!Wmarv34`Q?P(rx7K@j=*VdSB)N6#O2P3rBP{^qqOu*jfc$`H4sY4|3RuKT%K}JiY*oE z$4va773p0MZI1=3@9B}7p3$jCtJ_Q!b^=A${)`RY{w%InLly6&^%>tV22u|;g5!Lj zbtP9=zlg~N+qP`fSZp2E7b$wnApMc#_!K|`!V!9Ming}Pe6Mf#h65m);Qq|Ui(ED8 ze!EKlc71xj72D_Qy{7^LpV(A@pl4(=8NsOzzgE6}gJNeyB*?fy*dU9Jy)sXwxZ6kt zdJ;AQvSX%9-Glm(G$0s9afgUfimIy0t4+zFBd>}K%#jQZB0p*@$23Y5G7{el!n_;a z4x-vZFK!hDpmYrILBvapOLMlRM!%%VR(k`LKvzXwSma?+bDu)yG-vJlF_LWVaK3h- zSP{PgHGGW*@ii4;(xL$Q?rY=z3h(j;lw_eGB)kfyLqDwKuGOakkWd>}^FO6FXtcp6 zd4qV1`6L#{Gev48RAQFle$WfMdh-2SZCw0h&)0W)&G1pj6=^i}n1>RO_1RyG9r&mX zD|c!711=0EL=tqP;X67G&o*GW2JbT#d~WuTA7@oe8mHTH#xqe8lzK72=yMRIzQ8oc z_SBiCs9^!n9yExI=OvJRFOK-E7+lRVzIWF%zy0Z6>(bX;2nrPuAhY`{a4qPJ$c5YM z;ILX~<3 zre)D8euQ*tnF*lTbktlCCMwNpr4~a?Z_&dQrUJKx+p1;BKg_Vv2hMZaYdCm8tysbk zDcJNECe6=+PZDq!Y443*FU-sg!?;i-aDrM_jvDG}g?m|)tFiAdg1e66B<#E>SqM!_ zkGkvv1YL{Ov;ex)e875sA}Q7Xja_dzzcCC=)L~6;UK1WVa;^KB-r)qJCxsMS&Mu7in$GgMzCd(8y;QQT&QW_JINJH0L-$Z z>^fbp`$n;v9uLno5@*4M!k#p#`>lY<7V;C&-iW~qp7*#k$&?xmL*};L}K%H7k*z)%35ivxzWu^I(i6V;_gDjHu%M6#{^F6CDd-$llLUu8W zWw;j)fKq=g0~$q?zj@`#9R*Y3qEzm{E-ft zk8FL*M)bApw>iNj_DHxHVjKbJy1FATtSH%HrRRtR;wCbOwBb?kT6e7+?gsaH|N29& zDca!aE@cv=LBY^VUm0(I5+3+8F9%Pn#wikkL@;+0e0x@gqvY`#wSo{(F)xY&@+;Jg zsBRyiq{$dqekItIKK2%yQM3^Hj@`cysSV(BiS4Q64_tT9N$no)%C}yuI;>aP^rwx9 zGZ49HW?T+j6hfdXs= zVKneUa$y=JRvq-dRmlm`fD1>ktp?J{0^jaW$6k@k*YHHT5fODWP|`NbQ{P^7ah4lZ zXfqPF+*G6`pvbJ6)@DWYe&@zU>1&kWm8sE2nQ_0b8#1;Bt(^Lph^w z7gy?MVR+nuNLhV}`Q^bNxX;-7UTfYMP}P%=7qZS)tP3)ItvP`X{4C%iQMIa_*!E#Y zd=UxyWXs_JEjHavoIXyQFlw<$>Z`Y(m-@xV;t+k(v9x;LuOr05VZB(>hL`vhX6spW zZ+~lnT}pcnHVIFpG2~2<3Bxj=CydzR?aGSQrOuT<3OZ%>Xf}JI>wFfJHi_wva^$Ta zn2BOF35uY|0&&P8T_X-LfV+Et`@YdtUQlO>l@bvMsi5y4g-vP@e%21y9Yd)RK)Bg# zFmuX$eCsf`v(YKt`XJM@H~w3Tg@arjCAO2%OutguQWMi3${bO^`;eqpVa7IwxrsQY zka^+2-iIn_s^tKkv-ged4FR>F&s4~O8+$0~_@H*UzGe>1b~G{d*HB40jj&}7J*LK= zM^mZp2^vD@ne>sEu7YORr(6)ZSgSNU+dATBDOkL~>dZ$(u8H+(^?Q6~oRQbu^&YiRlCC* zPqcR$)DV{5OQ_^!ouC|Q3i8-s@IvRDfAal1DrKK@Jv&^sy|$mOf9$s0UF%wIw(k@t zUzt)}L}`v)>E0lA;t57AY#SEWDSkEEaK- zJ9R@NXfM~CA75Iu$|;uHMY5|S7FU^>*FOo{2gNdM1Fur{E>2vI0R?!>@P<(1i>uUg z3c)91f_|5?8D;l91)T3*%jj?F0JAq+;*I;yNyw7=1KYc4LFlJLE+meXZ{74!`s9sT zMD%~BC22{C4e3xS=jM=OA1mWXX2uLgJ{MORtFn+qa4>bwyBlJ09NWDOslZ*<%@v+G zUQoAsc~{F#LulxzENZ$ntzf}6Gv45_{Yw>)v)JpI@4M{l5f}58J8Z=Ln9d&$q%9vo zv{%z~m$|lEwiWcf$cHWQ?!x1VI@tNJZinlYYiUCJ3hRTg+Re8u%S7k`!QMW-r&)Zy_nM^bo3oO8VB@- zhz~m>8K~$%eLtAFZqLFahH!rIsGiC@8{tP4w<>=u`q#kR9V+_PJt_xxds;BG ztO-|6on$Ub-AZm!7a6dkQ_aLmv>-4eCdD1YqPl8yC_qddDP)j?F;NNGTJBNtNWXzr z7<*ZN<;+6VR7kMFI(%`#lfc7$SY>4^^duz9dalcsS(V$0Gg=$@QDAje=E$+oxG1_G zab}PT!L~O+*A;*&BRcEX&2S{`kzs%E;>o~>mG`zC4XDg$SG8&UQu>NRRDZ7VO$$$I zwE3setqgD70~oWW4zx9{>Q$vrjz|_xE;vs9?(q_yVoWtZ8Y1S!G?&ilR=3<1>&L>y;N_utEmOoIzgyh2%3f?1`y*TS6N;V>N7v-Rh@g19r)7XNK zP8X3A-sb?umoD9P!J$x?aK$xHt}>uOkd|u*qINq|{mcI7!q*$8yVhs>oeAcS)w0=z zN(L=7i#p?*FH%W%z&of(AKzOC3~55_R5<9a;ef}TXct7keJXfBuRjj_1i&nY5#OFJ z@UpYFp`Z_53h{vKHi;vqtT37l^a2IHJortDF)V1rfkt#DoDLXPSC}pdM;J!XdA{HQ zy?6>p9%lz5lk4kHK`QRnz8k~{p^9%nPL zDNLZi*yO~SZaX;=>xa6&lZQ-~^RJuV7%T;pbOSkY0FjfT!^M>gdgD(ccWP_NVYVTf z!UAE>9u(H`s>4$+vOAtom62By)glCRSt(%cds8Af2pjN;a^N*?ea-)F*lmo&lpp$> z59@*-yU2aHE*s{z;GQu~*EBBvQd+i}_d5{7QlpRS{;OJS|Ca@G$@TA#zP|`Ykf-Jx z2-ZoW{KPshfgb?k<++-?B%A0i0XSzY0+FE;r!ZZdJ?N7U?}YH_8&q`oVBt}Zn$eb$siU(DC%O&CJqHbq<; zRkaGHO4Aaui7wSq0QKr`sT2#l5)E|kAx?g0xnLmhBE=nZ_bq4S5{ofyGJApp_&JnH z0yzw0xZhHgF_);8%c^{aqwQfiiq^{i#CNdbSPc3ZsZC>DR6U6zUh$f?dG8Rbi-0{n zyi_+V_(caWtH_FFN_@6BC&7Xt=Ri4j#IsN2n1@EbcROGBrx)^l1l%pzSzg7|IV6ou z=IC{#+|Cx8%7+cjB&YrjRHa${1#Nd(1Q=(-%q(at0zX(4p17*?}Eqwyn_>+Yti$*6`9tw;$CS(SIv;GcZ~CP^((6 z@B15Zek#8!?>~4lImf>F_6wiVD5{z&kEE+g)lp*wL3m-55lBEfSiOp*z-aIHL-* z)8_c&PaJR$VvfHIrPHOMyY}F&z|ZBqcuKucjKD_ReuT2gW38M+qPoi}{17Oow9Y*P z+9nR<8Ki?I-~*kA!)zt@%>7w~(i{lV6OHlU*ALYB4IevmxdHR!wW9OI!i>~UFgp4> z1w*GAp9)-NhmK{*J=g3he+b(nkUmx9tQE8<&MOJya3f0Sv9>}qa``5oEw?Ua?!F0e zld;f=GU0Rjv4t{@C)t5UZd_FL} z7SF-${YM&0gUl|gIydFUVsrnH^~GM;P9|^|)MmihMtTXlhexp>45c+j)ZOX&FTN5H4v+2C2}oWE zdfKB(K|9^5^(OJGNsvmo=xa@C)OfSGGPh$HYt~hjZr-56DqL`fy|tLoQqLiY(hsIz zp%raYCyO4q%vQL|OrN-l4G$?7BHPkLU+oOhz5s|B6hn(!a~-5eL&)xB14i_xfD2Gyc1Kqq-0fki#TSR*^r-KF# zeM?F5?ElmjG#($fqGtaNgd}ake6tFr+0gfn;%`ua8RCCTG9wo6#XMtDn|4(+4SSujYaw(%_w_>#4RjxNfqNk8Cg{x&~3|%5+~}sZw_Jt?>lQA8mAJj6P}2iTo!rde2>xcbad=k&S#H7T=he?PIG+$}g7R zeWyfR5~FfJG$e+K-33+Q^^AxQZ%VG z1*!j5hlgxZobx>J?TYMjF*r29;O|}ss30O_0%T&GFYxG(Tz|k?>j1VOq2_- zqKGa~xm6dKpoX**o~3a>yGN|koue;V;5%l26IEM3=E>Br{0AnoZZz&vHkP-nFYJY| z`h6zd8fm!lJ10bJwDLej*Dz(!!ty@n=mp8@F4O>uoBtx6AeRNw%P%bI6yEv|bn6)P zuBa3FAIGB4^#8kb{Ch}Xv$hOq78miF_nyuy8xqsA9-ubJ^S^rsd0%QA>rl_T1fbS3 zjHDg*WPKKsrAHPZ5R-otXkd0F(Ues7#S)Qgyve6=uc_2w9%EHsZO_y(txE*vq^ms$sp=9yTBgH4y-fP5z>hXv5};Jg;l#2Lbs zUB2#;B%HBa9g?$eO+djd8A8*D`7+VmgiM8wd!ZlJCf*2id=s|ZX2jZNqBgeIIGP*3 zzJmtK^?u_N&=0@M&E=qFS@vx=sxV&Zv+Kf${$L<)?q*>N{WGBOK|kBvCy0>7RtzMa zioYFXx81E>CO|7@YdXILD^i<`N3s4LZAP0$gcM?FVXB{x-vUVmwhd9gxI6;Nd&B4) zHz7vj|6VdI5&vXT_UN)7mwRn@uZu@Ifz;;Km5W;>so$yY#sjH8rn?* z+w=UdHC0;fZ`b`%BDrv^QwY^5DvOlW<2Tz4;7wQb@hFQjEcCU(gMd57ljM&b@7TRz z+(BSs`<99??kAm!PWN4Elq`T+V0`_|IXGpF)b4slDLPLyl$dS09>q!Nf!^}M<)v!| z>e{o%$Osgs$UmRn&<2nA-+BtpbvyMO!MoLmy!*_0yPx9yt$QYpMWI&0IpAnEv>aXi z7krERCSNNCs(G&_6vf()V90knZZer=K^rK(b~+jBDr zL+P3^B)&1)E&1oDmEeog_XC9?c$h%wFQvRq!YTgRZ71twdL5Qj&45C_9e;@kHssaP zID~hofiE_Y7KNx%O@3W*Ssk&};~74fh}UAL>c>d(@vE>fr{#nFQ`TXKoUZ3?m{ip717{}A0cBs>QZG?+->iL2Mi)eWe|OXQ^$>ltpC)Tzj?U#R=6wV>_o`Dt z-A{E9p{tv;a5uVHS5aX)LaO-d35$~ZLCv8>B3U+xOq;=u05L$$zq%X_aW=2xk$$M- zqBK3^OxPb`T|2bSSvT&-hLK^6$6JY7a=FV1IGphxOLX3NBkmm26Mqjvbr^uXm%0=T21N6QPv5iS$(Hw=bDA))9|K zL!_drr)dEI4g!_0)JYu+5{}>^SCo~4BGaUJIODeG3Ia%-0&e3_x2ZS#M_Aw)IG(aB zfp+-t7dq086Rm^}m9y}GM0;)Ede$%WuBhMkIx|uv>OPIkT3xYqAO#J?TY zH!-Hg{24lB?lzRR$fV~f+bhr5T=~UB5^J#Zm8Yt={MKVJXr>81}xS?V1FamH0Zm9YAtr@+ch4l*Z*jn{r z^F?+{VZ%lvVrOnYO?OUwCCeilEfA~|g`h-OZciKK<^CnHJ}Rbr$<^)j2|n zk8II+90A=Kb)spNC>$qhOV-l2qu`u4XYAF9a+i#2??8x}pR}VHG)0=p6pVn?qVNn` zDF9q{%u5~n6hu<-h?+&xk#?{T5e@faGW2)z`K!0!rLAQ3OjKJ=`OvTa6DR!@I-#`m zbPOeKeVe&OPBI{KFMkOLg8Hx6H%poPswvzH8^gnYU^;qHMyEa2RcZdgxZ&7>hC#>` z7;bTw9m#!vNF7vyX_>}pMxaP8P^N%m7Tnv(5o44&pfExe(_Ji zmp}{721?d=#HCpMSV~m=!`v;nQ-Pj6P)XFA7j$<5{UkFC64~3xM_sSml=?Jc0fy`J z2QQb=y%$*PynE6vo>%3j1krF% zb+3RhK-&AWskz3LKe;d%lzjkk>~sttmD_G)RTq?k!Xkfool0Mp5skBz2#2?P&M2bu zJz2aOWb%*nWhP5oc{qmt6P{_7>g>5ELGl zhr^Xx4a-HOEdramJCYb~=;ync=qvBPXJ8@j5EV*3&eeoefsEOZD=PW$clR13SN2W- zw7j4GrVKpEqy#>cDF9WqEI#|I>|;~KlR6(;RUauB25U;i@$7Lf6}LnhsT~XpAD)Rz!KmUgD%^h%ZT)^VqVj6)9*_ z$%I?XQ9JS07r9%w3aQQE-lI-nRbflW!BPr^PK#H>U$-EYrm^bAvkR&`Pr+c6U?I4Q zL=Pe~J?5}6?&nXdPvxm{1z_}~wdd6|GfBWPNYw_C`-z1*RfA>B^>C`?Nmk-Y33&)o zMg$NCMUc!-98>~rX|U@MhjF>y9~WBnsdV$$zVSH0y*aw!g2l+rz>JUzdqw=>K{$xi ze;As9Q*t;tTf&Z&L->{j?NcR}Xl!p`c3cS%R@_Tm$a;|hvz`~^Ux>2Iy?Bd9RmNYL zMxN!9$e&8Dnc_Un@PE4?i}S6s>023(+l|wQoRVs}Q5v$G$^2E5MH+HUTWKr8s*ZLQ znjY;G`H6HK*JJw-i4k}lql@{pjuM-56Dfd7uSnERApv;PjX_l_;?mnff|=6|Jp1n_ zIKRhy2d3YTBlt(lTNd(E)ntWe&o};<`+*9?CHUoUP3`|@Ps~HGGzztNm0-N_`aw|n z{HThya~EY(@L5(n)(YemQ32y;8s!HEdUah8`52gu8!tSVnol2@|lZziO3!Z2;d5C_Y!9V zlM3DBJtIycbt9Igs5UFHMI;&7lQ{x(|M{zrO06pNd-EZ^E4}zhLkcuq8E8n^ERY@X zw*BStyC*#ypHC8quv&Tpo}l*zt7gO_!SXS88Hz7gW*Y>@T{YT#D$b4)4TQ^eCbNB? ztpK(gZ=eS=q5gQ3U>~z-A_HBjH|&G;K6M9p>I zNIBoLz6oJP5p6r_5kY`dCRnJc9w)Y9W#%O26_#O~t+v-iNmZg>JS+a58++CTl2P)OUxSnMc?n+P<4IT~fogGpYljS*a-0mU~My(&aJbhBv!M z@?mMt)3vTYJ^2E!g{mM=uBX>Mt=qv(pU4Hxgh%-|`YVT}&T zHmzWO=u^!iI2XtxW{fgbzLunYcHw@nMTultGVzI=0LUf%rA3~Mt6?A6>o2c`Qzwds zy!JzRE)?=eBYB64Bj(0glGqoUor6mD(l&M6`=NHuk3t{*ZLkdimJl4wqoYv4Yr(%8 z^e~(3*~|IPj1vIXpj}(1mhVU#uxv(IX(g(hL|5`Rk!^A&IGh zArpLuOnmu%yFI`p#~q*KyNm&4Hw3Oz(PsxXDhvDTx|}4|^x~*!pwRLfyui$!>pG($&D&oQl z1`65x`43Hnfb+WBCu&L0Yj@fKR4_80AYXF!&ds>G3u;3*54vGV0ETu5p+6?iLN(fs zxxSJ(m4www(bS^6q3IH6otv0wGHzd72iajb=B$~iYAiMXLl2TwN>1Jvz;o706y)XV z1#WMy7j$M;z0usR7BpcIH))0eVzXWpsTw*2#d|GvS=@G+5?U8r639RD-~j1$h#3)# z_MTR>6QN^c+Y*pwSA&>VKfUAXEkSltO39^MUURAmDxR(BWs6Wum|8&5pz&?dq2#^V zfV$tIGn5)Gtw5CdFB$2Q{+UpgmSmqwr6&tqw%sLR+K|QFd4d-jXx{sosd-dl;XeTd zPUz4ZM=fKL+!4N?2oC&33=7{SKom@{75fAynaLBvUmd13>*77&=`*0T%i6eHT^RVC zR78el;)t5|A7@lzuNU_NhNWK{B-Bg5b9d$or27WxM<{C2Gugp#ES_ldto8IU{klfy zu&R>f_H#6(-2= zOF0uDsqr-}Iw`i<(nZlB?={{7rjNU`C1SoUCC@TzkNg0__q}NUEmzS9#-TY7(XkCC z0rnO&8I4vmuT=ABmaYZzL?y{LZQdExH&~-nLkP^yPEi`1hPKOQ5FIWk=QFk(SZtG@ z)?M-W#5r`%xaXEzibO6*Z)aY+Ymxn1eaf;WKmzqaC0f-t*}~*$SG-4`7-9n|xiNkD z7I^P&2=jxQSBJHfZS?tHZ09i8A}#FC{{XOIbk!#;{7*LdWq!LLqEcpelze=F$(GiM zk6~f+|L=(%a3N4*K{0%e|H$$_P5X|m6QnJbZ5PhpT6>cm)n_U+eTE{*I_nq^n=2-Z z@;}7nPccqF7gtj*_o%j z_6BWdNTT957Rp0b?(y^rB1>~TFW%g(rmIfUMWm~z;Ldhv z_Nq0S1ghn!1PgwIJ`jqYBhOMp!xMhBVfS!LYfna4~rW7Kuv@~?mo3> zV_Qz;zp#^>cqG6A-85AEd$mF8soap?m@_2en5c@oluC&-$Orazo5{kLz6ZMklfoEh zx^`uZr~~KB?|D52(V({1&ROycVcy7HI*AX?BjRWK6~*YqZLLnGzjSwxa$J&?57LRw zgM|rZ2_Aaar}C4O+wP)DO)yNCASfFxD0jfx<3b2~EuK50a@pkn7=pwn3&wnrofL#P z2*;1i9!4*3Gz46!P)1?${psthX7<51wKZOYyt;_d6INtC$>GI1&dP`*F6ljWqnse) zw!2@*Jh04uNU_%g54p@Aln}=_DxCW5&Ln3eIBazz11%X?B9JV#}}L{s$+oDY{+!~6h?Ei#Fd52Vh@?h z0N$hJI}FMb(!SaC>5Sis2Zne=MATg4e6ro$ZIW1KN;mDe6@ZXQEsGPldLQ0-Wo(Fg z3j)KSnu~~4HX;8|j!Xt_v;+&Jj!++LhJ18M8djKMpcn=I z<*~a6Hr(usPX8b$Ko}tH%~gN!g^cr+>~oF7xWkLzpIBROwh|AR-Icxpjx!Dk8ol)x zS&?4lIu>PXr1*x})>vVj`RndDwPu9xcci@bVTZ~A#=D-vNi?r7uEXF#4?FKtH|AY^ zS8S?LDrjT@W)|rlsuldcmoQpI2TQd`CDA|S%v=+5fl4$VcZQ8g_s+Oc3mY`#)N*>y?AIJ+|cZ zVKVzf<%8H@NmNs~?!t_44N?=CU)IxmGxi8u`5bt%eVKy+EWHf|@o&yF>6{;H>W)t# zIhhVid~a08KXqOtqc&pcB4D9}AEafn+tEXK*cc3)?@TQ~R>gC4Ohj-9fkL1>`~8|; z@#JXVw%=PrVWmlzJ%V4<8@#D191-epS?j#SyJ@mtMQb)&(-{AdW zr+;XxHKcwbfF&$He$J7U+lyl zj*Rqz56}7AK)<1N&>x}YGbh~Mu1WIgXFE!Vb!uKNRk zK-l%MoyvC{{EnsnED?%I%VfnIc8yWawbAenbhT-P7whTFIdE};GxZ{npW;7U$;WF} zx>Sx29r^c)ZGfC8S1PFSuwgq?XV;W113*T`G}uSpwLT|PO-_6FtB5Ig7eL;>X3n>> zaZqtGYr3D98ak~cJVAn!t?1yy$bVanhO1xhnrF51Mma0`()qCpwS`vPmxx94%Fu~0 z$(SCJE@XILOjbD20}N;nc?|o6|6KTG2QF=^DyYXY zE66peyhe0S7-Ma!2j*R-11Kh_MjCuIfWEFhF&NVLQ9Q@}KM|5_iG!-3nQ+1LfZUuB&pfGJdZ1zkUsM#YG2^;Z!-R|%V?t822+|E(gh1FI~9^J(44 z5~N@`P_k5u>2~c+aeipiXYSOLwE%lamUD-jaPP@=mqE@zIv^Z{Z}&ivkNxV_QqwTf zjaQXDZ5gjUKg@U6vrFnLc#gRPy`@48k|YK|jFqg&{8s!-6F9hDE?0@qOzei>d*quY zHNDVJZ1%3Y3^mk#9da|M30_>yW9O z|L*V)lES8=*|@1}{sjrp2|-&dIM!@Nx-*&18{R)91{FiFs*jYL4= zL*q_uk}389qv(*m@k3)jTY*54G|BJ#W{=(@q=NWYpWEm3)e<@qx*faV8(C# zOOSdTvU4Z1U2N+~;NKi(?oh)i4^%|Xz^a?AYV4(}wpYBW8+;1G=zJDdEBjNW13I#J ze+5qGLE&uKkmQNOC1rVaej1}CSIG+o{U8#NXT=`Y3yVNJI&N{P>+9(EYt1omw&uR3 zY%-@q3<=E~g`Yi$IV|xLj~-U!drOdN3rSFWa}WgK3~6CfkN^)inw}{x2`2FHScfGK z-2DCXRidBLyy3tf`^not7-b}G-T5`Vn#HArTBO`KNy_YRIXw_5KYO_f+A>AIrkNR~ zUK7Ob@@rmNP^mhT;9EZi?|k#!`umuD>eDI4@35CF3wbK%B` zn%B_jup&gnzwweBkmO0(4&mXCAFBqqCMnx@RnvsRj&3zMoixg+@jEm!J+^SMrqMSj zz0;4hWoR*+hg1Zj?^wk4pOx-E+y@+X7XHnP7U^L&?cLI#Cx0VnPV^uvTJZNFL^3e5D}OZmLV~V()EXA zz)pt!cOsUNEjbZi?P|M1d8)P9nde8`lmG~up^G4lSo%tY@)Cs)SLf53dG!M3WUkAS zluJ?X=j-18n8M|l4=^wvHh4C^Vf7aln#-6H^Dp&~)M8bcJr$p)yA2R0*8L{KBii0kKr7c7OA>4Pa9 zh>evgpW=|?7?cbE7NL~DL zH}y@_73y|3>TrCsRejX9SZ)Xt0v4gYURB^ zA5%5ZDHdA@VfvaYEFrArdubK(YoIW}$73wqMFnrKt<8KwxQt!96>zMZH!jsa!eaDC zVfDnYB)mqLLQ2$6ZH3}G(sR7uyfO%k-OgdxLGqbaHI-nUG#UWc+e+?{A9Q_YJes+Z|FJezU%TmzI4exxm^88Te zEQ;GldrxfCMpHPRA7e4^#fH8qdZhy)+L6B@_#=Ck_p!rNvkiCB0DTYIdH&ctZ2XUw z$tBf5j9$ztWB<<`nLtJ;B@t(ge%WLm&G7W9wv0+{A=j7)C5-Txnu z0`C&yrp_Bq#~zfsEV(=+K(){XosWLhxu1ZpDw*P2ME~7zFl~B-`<}J#;)Ne!6Ev!m*?y_5G4d!lwnu7~dBGRu|cF(G_ zmgB0}z9zL~L{>P$yTQzJyhV&h`9Gd`iWpd;u;lBp?ca>oUM=i&8X^97z%`}CMA8wP z5O|h$nkl~fi+u6K`w{ytK~c74KdY32R14}ug7*xS{omNsVFS)ro^dW)+)Xfr@CT6U zqN`19j9v+;D4jpF%`;j9Feu{KT)BlaM|8Ov$kx1rSAYCC^~EXVIFQx)vPojej*m!Ah~w#MtCO%T=&-=D59QQG1trj*p3BxG%U-R>tff@Q7^`NK{s-bvh=M zj*_t2{304}gSO9n(>p)g6dh$`Myq2=K`7NA=rm`LQU73KCaoOSZg?iGgk@#3XX)!wV; zn^ANSM7PMeSknWk*$@s3u>eiCQral7u##g0$#n~uqC{tG`S+-D7^GElD@=Snlqi^sM z9Af-#yK4%@4!A&MOJZH~R;7C-BnL~VAT2&r!=Qgbog(8g`XTAm8&i~0#wn=@g43oa zU=@VDm)mP|pVsp+HiH(L(FTd*8`T3YOrvPn98nHCSXs-cGQs`*YtETtw9Wsj+N?ha zi=#9eyo+Ux2dVM+0jLt*Rk&*Tyk`}gHF7oJn1tYq=2?d2Qv=U@fFpg#>4v+a=$Ijm zatOTEtvp4%x8jZX!3(^n068G9)2pUOZrHs0?*fGqtQ?VPRF>>Q0#z-30pKZ;cApM~ zn3rXb2R~!)QTI$q)Q9_;K_&c44te4IJpW4raz-{k=(Z(>W828mZ>?-2pT=yti^gkO zYhs>&;nt)#+DoEVMH%@tgq^*8K1;KT)5PA zh*QtxC|oDtR4(0}8bvjWVFd=Yt&wRY%{F_@ON(0;a`RSU`|EF3e8hN?H6AS+qi`C8AA^?`&(yCXIT-Dnd<`46us;WEv9*7M_BTJep zUNT0&7GzM=7+eE(9ypP(7kKi%XuGpF`4&;XxW5%ci6+5@rDS}_q8Wt4T;g$K^fiOT zu-2ar4({kYy6{W-A&e|)T^m(Se9 z3fO_K*}#ByC_e+(ad+t3!(4sFZWyo~yvaL&yXaUB_HJ*?l@m>%L}D1$Vmzl)TM7{) zUyhNhej9Ykcu4J0KH%FL*EldnGCZlb1OkN3w7H;ZV5=b*Le{Y>Zu<3+Vb${vt>zua zDH;EWstQ-NhYn z(V>K$Z3JE#`S3s&d+cxS54 zBq6E%X$}84@626#<>Gust??a+$HIyIMuQ0=X`q95!7ti!U2!cP&$fjf z*KK>SocePLZ3@Pz^@}ntnbYlpj4XrD-GIYTzo4QJ)Pm95D5cprbe(;aIrYlvpt0zD zm>CZK<<{Mu1q&Gi-?*%w5&(lTI&f3{JH%*Wc4Hq=K;-}v8NIy4sP%hd%rAl3h5IRA zot8i7Sx0FK;Pi60CI@*^ZfimbvfDd{ynA66T+;1rYmWx=`?CHo&Rsbt}e)8D@`2|HFf)|t$H2*MFbjrruNlf zg41Phvd@tS`(kd^k$qgH4<7H$a@#Yy$LB|~bbR^=ynF#XPzv>s6_Y$ds%v3jPsPd) zpEk09(`=hjVaFp4r_-0lsbZM?)}3EbFEJ9bN=yXYElPv^pk4!Qf_uzjxaLWaI(0QSJ`)C<>(0h=MretG`P>pFER>|2|q>^aHY^ZD8dt(DL-XuQ_^(xlo^ z-K&`8ix!PB3WV7_q9r5X5PZ+C&u)I8D!`=}-@moy=VBxhKg^(uiY==tDrdZ1NZn}D zEN@v-mjiN*JONg@CSc})8VZ37YyuQON)(TU54Cn}I(59H)LdlfA>71x107Q8 zEhfcp903Imjw^ub8B7bioS_@+s_^TzWZNN~FEnuJPB|YGO2ixP3Zav#3;jMD)9$Bb zP8A(af_!f7=VqCK`XlZQlD7q@O6+9Rs*o)$Mno;udMDqN(M|NBwnn@0ab%5

    B5# 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 z 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


    |J(H>5v(Cw_rTzZ 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
  • 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�Gt< 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