Refactor file opening to use TabManager and add dashboard tab system

This commit is contained in:
Bruno Charest 2026-05-26 12:14:47 -04:00
parent b38f3f16e4
commit 872a3e56dd
2 changed files with 80 additions and 90 deletions

View File

@ -542,7 +542,7 @@
li.appendChild(metaEl); li.appendChild(metaEl);
li.addEventListener("click", () => { li.addEventListener("click", () => {
this.hide(); this.hide();
openFile(item.vault, item.path); TabManager.openPreview(item.vault, item.path);
}); });
this._titlesList.appendChild(li); this._titlesList.appendChild(li);
}); });
@ -2642,10 +2642,15 @@
attachTreeItemLongPress(fileItem, () => ({ vault: vaultName, path: item.path, type: "file", isReadonly: false })); attachTreeItemLongPress(fileItem, () => ({ vault: vaultName, path: item.path, type: "file", isReadonly: false }));
fileItem.addEventListener("click", () => { fileItem.addEventListener("click", () => {
scrollTreeItemIntoView(fileItem, false); scrollTreeItemIntoView(fileItem, false);
openFile(vaultName, item.path); TabManager.openPreview(vaultName, item.path);
closeMobileSidebar(); closeMobileSidebar();
}); });
fileItem.addEventListener("dblclick", (e) => {
e.preventDefault();
TabManager.openPersistent(vaultName, item.path);
});
fileItem.addEventListener("contextmenu", (e) => { fileItem.addEventListener("contextmenu", (e) => {
e.preventDefault(); e.preventDefault();
const isReadonly = false; const isReadonly = false;
@ -2797,7 +2802,7 @@
if (entry.type === "directory") { if (entry.type === "directory") {
await focusPathInSidebar(entry.vault, entry.path, { alignToTop: true, expandTarget: true }); await focusPathInSidebar(entry.vault, entry.path, { alignToTop: true, expandTarget: true });
} else { } else {
await openFile(entry.vault, entry.path); await TabManager.openPreview(entry.vault, entry.path);
await focusPathInSidebar(entry.vault, getParentDirectoryPath(entry.path), { alignToTop: true, expandTarget: true }); await focusPathInSidebar(entry.vault, getParentDirectoryPath(entry.path), { alignToTop: true, expandTarget: true });
syncActiveFileTreeItem(entry.vault, entry.path); syncActiveFileTreeItem(entry.vault, entry.path);
} }
@ -5657,26 +5662,16 @@
</div> </div>
</div>`; </div>`;
// Wire dashboard tab switching // Re-initialize widgets and dashboard tabs
document.querySelectorAll(".dashboard-tab").forEach(tab => {
tab.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");
});
});
// Re-initialize widgets
if (typeof DashboardRecentWidget !== "undefined") { if (typeof DashboardRecentWidget !== "undefined") {
DashboardRecentWidget.init(); DashboardRecentWidget.init();
} }
initDashboardTabs();
safeCreateIcons(); safeCreateIcons();
} else if (home) { } else if (home) {
// Dashboard already exists, just show it // Dashboard already exists, show it with default tab
home.style.display = ""; home.style.display = "";
// Activate default tab // Reset tabs to default
document.querySelectorAll(".dashboard-tab").forEach(t => t.classList.remove("active")); document.querySelectorAll(".dashboard-tab").forEach(t => t.classList.remove("active"));
document.querySelectorAll(".dashboard-panel").forEach(p => p.classList.remove("active")); document.querySelectorAll(".dashboard-panel").forEach(p => p.classList.remove("active"));
const defaultTab = document.querySelector('.dashboard-tab[data-tab="stats"]'); const defaultTab = document.querySelector('.dashboard-tab[data-tab="stats"]');
@ -7506,8 +7501,25 @@
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
init(); init();
registerServiceWorker(); 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 // Tab Manager — Multi-file tab support
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ObsiGate</title> <title>ObsiGate</title>
<!-- PWA Meta Tags --> <!-- PWA Meta Tags -->
<meta name="description" content="Porte d'entrée web pour vos vaults Obsidian - Accédez, naviguez et recherchez dans toutes vos notes"> <meta name="description" content="Porte d'entrée web pour vos vaults Obsidian - Accédez, naviguez et recherchez dans toutes vos notes">
<meta name="theme-color" content="#2563eb"> <meta name="theme-color" content="#2563eb">
@ -12,18 +12,18 @@
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="ObsiGate"> <meta name="apple-mobile-web-app-title" content="ObsiGate">
<!-- PWA Manifest --> <!-- PWA Manifest -->
<link rel="manifest" href="/static/manifest.json"> <link rel="manifest" href="/static/manifest.json">
<!-- Apple Touch Icons --> <!-- Apple Touch Icons -->
<link rel="apple-touch-icon" sizes="152x152" href="/static/icons/icon-152x152.svg"> <link rel="apple-touch-icon" sizes="152x152" href="/static/icons/icon-152x152.svg">
<link rel="apple-touch-icon" sizes="192x192" href="/static/icons/icon-192x192.svg"> <link rel="apple-touch-icon" sizes="192x192" href="/static/icons/icon-192x192.svg">
<!-- Favicon --> <!-- Favicon -->
<link rel="icon" type="image/svg+xml" href="/static/icons/icon-72x72.svg"> <link rel="icon" type="image/svg+xml" href="/static/icons/icon-72x72.svg">
<link rel="icon" type="image/png" sizes="192x192" href="/static/icons/icon-192x192.svg"> <link rel="icon" type="image/png" sizes="192x192" href="/static/icons/icon-192x192.svg">
<link rel="stylesheet" href="/static/style.css"> <link rel="stylesheet" href="/static/style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css" id="hljs-theme-dark"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css" id="hljs-theme-dark">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css" id="hljs-theme-light" disabled> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css" id="hljs-theme-light" disabled>
@ -36,7 +36,7 @@
} }
} }
</script> </script>
<!-- CodeMirror 6 --> <!-- CodeMirror 6 -->
<script type="module"> <script type="module">
import { EditorView, keymap, lineNumbers, highlightActiveLineGutter, highlightSpecialChars, drawSelection, dropCursor, rectangularSelection, crosshairCursor, highlightActiveLine } from "https://esm.sh/@codemirror/view@6.9.0?external=@codemirror/state"; import { EditorView, keymap, lineNumbers, highlightActiveLineGutter, highlightSpecialChars, drawSelection, dropCursor, rectangularSelection, crosshairCursor, highlightActiveLine } from "https://esm.sh/@codemirror/view@6.9.0?external=@codemirror/state";
@ -58,7 +58,7 @@
import { java } from "https://esm.sh/@codemirror/lang-java@6.0.1?external=@codemirror/state"; import { java } from "https://esm.sh/@codemirror/lang-java@6.0.1?external=@codemirror/state";
import { rust } from "https://esm.sh/@codemirror/lang-rust@6.0.1?external=@codemirror/state"; import { rust } from "https://esm.sh/@codemirror/lang-rust@6.0.1?external=@codemirror/state";
import { oneDark } from "https://esm.sh/@codemirror/theme-one-dark@6.1.0?external=@codemirror/state"; import { oneDark } from "https://esm.sh/@codemirror/theme-one-dark@6.1.0?external=@codemirror/state";
const basicSetup = [ const basicSetup = [
lineNumbers(), lineNumbers(),
highlightActiveLineGutter(), highlightActiveLineGutter(),
@ -86,7 +86,7 @@
...completionKeymap, ...completionKeymap,
]) ])
]; ];
window.CodeMirror = { EditorView, EditorState, basicSetup, markdown, python, javascript, html, css, json, xml, sql, php, cpp, java, rust, oneDark, keymap }; window.CodeMirror = { EditorView, EditorState, basicSetup, markdown, python, javascript, html, css, json, xml, sql, php, cpp, java, rust, oneDark, keymap };
</script> </script>
</head> </head>
@ -358,27 +358,29 @@
<!-- Content --> <!-- Content -->
<main class="content-area" id="content-area" aria-label="Contenu principal"> <main class="content-area" id="content-area" aria-label="Contenu principal">
<div id="dashboard-home" class="dashboard-home" role="region" aria-label="Tableau de bord"> <div id="dashboard-home" class="dashboard-home" role="region" aria-label="Tableau de bord">
<!-- Stats Section --> <!-- Dashboard Tabs -->
<div id="dashboard-stats-section" class="dashboard-section"> <div class="dashboard-tabs">
<div class="dashboard-header"> <button class="dashboard-tab active" data-tab="stats">
<div class="dashboard-title-row"> <i data-lucide="bar-chart-3" style="width:14px;height:14px"></i> Statistiques
<i data-lucide="bar-chart-3" class="dashboard-icon" style="color:var(--accent)"></i> </button>
<h2>Statistiques</h2> <button class="dashboard-tab" data-tab="bookmarks">
</div> <i data-lucide="bookmark" style="width:14px;height:14px"></i> Bookmarks
</div> </button>
<button class="dashboard-tab" data-tab="recent">
<i data-lucide="clock" style="width:14px;height:14px"></i> Récents
</button>
</div>
<!-- Stats Panel -->
<div id="dashboard-panel-stats" class="dashboard-panel active">
<div id="dashboard-stats-grid" class="dashboard-stats-grid"> <div id="dashboard-stats-grid" class="dashboard-stats-grid">
<div class="dashboard-stats-loading">Chargement...</div> <div class="dashboard-stats-loading">Chargement...</div>
</div> </div>
<div id="dashboard-conflicts-container" style="margin-top:16px"></div>
</div> </div>
<!-- Bookmarks Section --> <!-- Bookmarks Panel -->
<div id="dashboard-bookmarks-section" class="dashboard-section"> <div id="dashboard-panel-bookmarks" class="dashboard-panel">
<div class="dashboard-header">
<div class="dashboard-title-row">
<i data-lucide="bookmark" class="dashboard-icon" style="color:var(--accent-green)"></i>
<h2>Bookmarks</h2>
</div>
</div>
<div id="dashboard-bookmarks-grid" class="dashboard-recent-grid"></div> <div id="dashboard-bookmarks-grid" class="dashboard-recent-grid"></div>
<div id="dashboard-bookmarks-empty" class="dashboard-recent-empty"> <div id="dashboard-bookmarks-empty" class="dashboard-recent-empty">
<i data-lucide="pin"></i> <i data-lucide="pin"></i>
@ -387,47 +389,23 @@
</div> </div>
</div> </div>
</div> <!-- Recent Panel -->
</div> <div id="dashboard-panel-recent" class="dashboard-panel">
<!-- Sync Conflicts Section -->
<div id="dashboard-conflicts-section" class="dashboard-section" style="display:none">
<div class="dashboard-header"> <div class="dashboard-header">
<div class="dashboard-title-row"> <div class="dashboard-title-row">
<i data-lucide="alert-triangle" class="dashboard-icon" style="color:var(--accent-orange)"></i>
<h2>Conflits de synchronisation</h2>
<span id="dashboard-conflicts-count" class="dashboard-badge" style="background:var(--accent-orange)"></span>
</div>
</div>
<div id="dashboard-conflicts-grid" class="dashboard-conflicts-grid"></div>
</div>
<!-- Recently Opened Section -->
<div id="dashboard-recent-section" class="dashboard-section">
<div class="dashboard-header">
<div class="dashboard-title-row">
<i data-lucide="clock" class="dashboard-icon"></i>
<h2>Derniers fichiers ouverts</h2>
<span id="dashboard-count" class="dashboard-badge"></span> <span id="dashboard-count" class="dashboard-badge"></span>
</div> </div>
<!-- <div class="dashboard-actions hidden"> <div class="dashboard-actions">
<select id="dashboard-vault-filter" class="dashboard-filter" aria-label="Filtrer par vault"> <select id="dashboard-vault-filter" class="dashboard-filter" aria-label="Filtrer par vault">
<option value="all">Tous les vaults</option> <option value="all">Tous les vaults</option>
</select> </select>
</div> --> </div>
</div> </div>
<div id="dashboard-recent-grid" class="dashboard-recent-grid"></div> <div id="dashboard-recent-grid" class="dashboard-recent-grid"></div>
<div id="dashboard-loading" class="dashboard-loading"> <div id="dashboard-loading" class="dashboard-loading">
<div class="skeleton-card"></div> <div class="skeleton-card"></div><div class="skeleton-card"></div><div class="skeleton-card"></div>
<div class="skeleton-card"></div> <div class="skeleton-card"></div><div class="skeleton-card"></div><div class="skeleton-card"></div>
<div class="skeleton-card"></div>
<div class="skeleton-card"></div>
<div class="skeleton-card"></div>
<div class="skeleton-card"></div>
</div> </div>
<div id="dashboard-recent-empty" class="dashboard-recent-empty hidden"> <div id="dashboard-recent-empty" class="dashboard-recent-empty hidden">
<i data-lucide="inbox"></i> <i data-lucide="inbox"></i>
<span>Aucun fichier récent</span> <span>Aucun fichier récent</span>
@ -504,7 +482,7 @@
<div class="editor-body" id="config-body"> <div class="editor-body" id="config-body">
<div class="config-content"> <div class="config-content">
<!-- Performance Settings Frontend --> <!-- Performance Settings - Frontend -->
<section class="config-section"> <section class="config-section">
<h2>Paramètres de recherche</h2> <h2>Paramètres de recherche</h2>
<p class="config-description">Ces paramètres s'appliquent immédiatement côté client.</p> <p class="config-description">Ces paramètres s'appliquent immédiatement côté client.</p>
@ -512,22 +490,22 @@
<div class="config-row"> <div class="config-row">
<label class="config-label" for="cfg-debounce">Délai debounce (ms)</label> <label class="config-label" for="cfg-debounce">Délai debounce (ms)</label>
<input type="number" id="cfg-debounce" class="config-input config-input--num" min="100" max="2000" step="50" value="300"> <input type="number" id="cfg-debounce" class="config-input config-input--num" min="100" max="2000" step="50" value="300">
<span class="config-hint">Délai avant exécution de la recherche (1002000)</span> <span class="config-hint">Délai avant exécution de la recherche (100-2000)</span>
</div> </div>
<div class="config-row"> <div class="config-row">
<label class="config-label" for="cfg-results-per-page">Résultats par page</label> <label class="config-label" for="cfg-results-per-page">Résultats par page</label>
<input type="number" id="cfg-results-per-page" class="config-input config-input--num" min="10" max="200" step="10" value="50"> <input type="number" id="cfg-results-per-page" class="config-input config-input--num" min="10" max="200" step="10" value="50">
<span class="config-hint">Nombre de résultats affichés par page (10200)</span> <span class="config-hint">Nombre de résultats affichés par page (10-200)</span>
</div> </div>
<div class="config-row"> <div class="config-row">
<label class="config-label" for="cfg-min-query">Longueur min. requête</label> <label class="config-label" for="cfg-min-query">Longueur min. requête</label>
<input type="number" id="cfg-min-query" class="config-input config-input--num" min="1" max="5" step="1" value="2"> <input type="number" id="cfg-min-query" class="config-input config-input--num" min="1" max="5" step="1" value="2">
<span class="config-hint">Nombre minimum de caractères avant recherche (15)</span> <span class="config-hint">Nombre minimum de caractères avant recherche (1-5)</span>
</div> </div>
<div class="config-row"> <div class="config-row">
<label class="config-label" for="cfg-timeout">Timeout recherche (ms)</label> <label class="config-label" for="cfg-timeout">Timeout recherche (ms)</label>
<input type="number" id="cfg-timeout" class="config-input config-input--num" min="5000" max="120000" step="5000" value="30000"> <input type="number" id="cfg-timeout" class="config-input config-input--num" min="5000" max="120000" step="5000" value="30000">
<span class="config-hint">Annuler la recherche après ce délai (5000120000)</span> <span class="config-hint">Annuler la recherche après ce délai (5000-120000)</span>
</div> </div>
</section> </section>
@ -541,7 +519,7 @@
</div> </div>
</section> </section>
<!-- Performance Settings Backend --> <!-- Performance Settings - Backend -->
<section class="config-section"> <section class="config-section">
<h2>Paramètres backend <span class="config-badge-restart">Redémarrage requis</span></h2> <h2>Paramètres backend <span class="config-badge-restart">Redémarrage requis</span></h2>
<p class="config-description">Ces paramètres sont sauvegardés sur le serveur. Certains nécessitent un redémarrage ou une réindexation.</p> <p class="config-description">Ces paramètres sont sauvegardés sur le serveur. Certains nécessitent un redémarrage ou une réindexation.</p>
@ -549,12 +527,12 @@
<div class="config-row"> <div class="config-row">
<label class="config-label" for="cfg-workers">Workers de recherche</label> <label class="config-label" for="cfg-workers">Workers de recherche</label>
<input type="number" id="cfg-workers" class="config-input config-input--num" min="1" max="8" step="1" value="2"> <input type="number" id="cfg-workers" class="config-input config-input--num" min="1" max="8" step="1" value="2">
<span class="config-hint">Threads dédiés à la recherche (18)</span> <span class="config-hint">Threads dédiés à la recherche (1-8)</span>
</div> </div>
<div class="config-row"> <div class="config-row">
<label class="config-label" for="cfg-max-content">Taille max contenu (octets)</label> <label class="config-label" for="cfg-max-content">Taille max contenu (octets)</label>
<input type="number" id="cfg-max-content" class="config-input config-input--num" min="10000" max="1000000" step="10000" value="100000"> <input type="number" id="cfg-max-content" class="config-input config-input--num" min="10000" max="1000000" step="10000" value="100000">
<span class="config-hint">Contenu indexé par fichier (10K1M). Réindexation requise.</span> <span class="config-hint">Contenu indexé par fichier (10K-1M). Réindexation requise.</span>
</div> </div>
<div class="config-row"> <div class="config-row">
<label class="config-label" for="cfg-title-boost">Boost titre</label> <label class="config-label" for="cfg-title-boost">Boost titre</label>
@ -569,7 +547,7 @@
<div class="config-row"> <div class="config-row">
<label class="config-label" for="cfg-prefix-exp">Expansions préfixe max</label> <label class="config-label" for="cfg-prefix-exp">Expansions préfixe max</label>
<input type="number" id="cfg-prefix-exp" class="config-input config-input--num" min="10" max="200" step="10" value="50"> <input type="number" id="cfg-prefix-exp" class="config-input config-input--num" min="10" max="200" step="10" value="50">
<span class="config-hint">Nombre max de tokens élargis par préfixe (10200)</span> <span class="config-hint">Nombre max de tokens élargis par préfixe (10-200)</span>
</div> </div>
<div class="config-actions-row"> <div class="config-actions-row">
@ -583,14 +561,14 @@
<section class="config-section"> <section class="config-section">
<h2>Filtrage de tags</h2> <h2>Filtrage de tags</h2>
<p class="config-description">Définissez les patterns de tags à masquer dans la sidebar. Vous pouvez utiliser des wildcards pour cibler les tags de template.</p> <p class="config-description">Définissez les patterns de tags à masquer dans la sidebar. Vous pouvez utiliser des wildcards pour cibler les tags de template.</p>
<div class="config-filters-list" id="config-filters-list"></div> <div class="config-filters-list" id="config-filters-list"></div>
<div class="config-add-pattern"> <div class="config-add-pattern">
<input type="text" id="config-pattern-input" placeholder="Ex: #&lt;% ... %&gt; ou #{{ ... }}" class="config-input"> <input type="text" id="config-pattern-input" placeholder="Ex: #&lt;% ... %&gt; ou #{{ ... }}" class="config-input">
<button id="config-add-btn" class="config-btn-add">Ajouter</button> <button id="config-add-btn" class="config-btn-add">Ajouter</button>
</div> </div>
<div class="config-regex-preview" id="config-regex-preview" style="display:none;"> <div class="config-regex-preview" id="config-regex-preview" style="display:none;">
<small>Regex : <code id="config-regex-code"></code></small> <small>Regex : <code id="config-regex-code"></code></small>
</div> </div>
@ -620,12 +598,12 @@
<div class="config-row"> <div class="config-row">
<label class="config-label" for="cfg-watcher-interval">Intervalle polling (s)</label> <label class="config-label" for="cfg-watcher-interval">Intervalle polling (s)</label>
<input type="number" id="cfg-watcher-interval" class="config-input config-input--num" min="1" max="30" step="1" value="5"> <input type="number" id="cfg-watcher-interval" class="config-input config-input--num" min="1" max="30" step="1" value="5">
<span class="config-hint">Intervalle de scrutation en mode polling (130 secondes)</span> <span class="config-hint">Intervalle de scrutation en mode polling (1-30 secondes)</span>
</div> </div>
<div class="config-row"> <div class="config-row">
<label class="config-label" for="cfg-watcher-debounce">Debounce (s)</label> <label class="config-label" for="cfg-watcher-debounce">Debounce (s)</label>
<input type="number" id="cfg-watcher-debounce" class="config-input config-input--num" min="0.5" max="10" step="0.5" value="2"> <input type="number" id="cfg-watcher-debounce" class="config-input config-input--num" min="0.5" max="10" step="0.5" value="2">
<span class="config-hint">Délai avant traitement des changements groupés (0.510 secondes)</span> <span class="config-hint">Délai avant traitement des changements groupés (0.5-10 secondes)</span>
</div> </div>
</section> </section>
@ -634,13 +612,13 @@
<h2>🗂️ Fichiers cachés</h2> <h2>🗂️ Fichiers cachés</h2>
<p class="config-description">Contrôlez l'affichage des fichiers/dossiers cachés (commençant par <code>.</code>) par vault.</p> <p class="config-description">Contrôlez l'affichage des fichiers/dossiers cachés (commençant par <code>.</code>) par vault.</p>
<p class="config-hint" style="margin-bottom: 12px; padding: 8px; background: var(--background-secondary); border-radius: 4px;"> <p class="config-hint" style="margin-bottom: 12px; padding: 8px; background: var(--background-secondary); border-radius: 4px;">
<strong>Note :</strong> Tous les fichiers sont toujours indexés et cherchables. Ce paramètre contrôle uniquement leur visibilité dans l'interface. i <strong>Note :</strong> Tous les fichiers sont toujours indexés et cherchables. Ce paramètre contrôle uniquement leur visibilité dans l'interface.
</p> </p>
<div id="hidden-files-vault-list"> <div id="hidden-files-vault-list">
<!-- Vault-specific settings will be injected here --> <!-- Vault-specific settings will be injected here -->
</div> </div>
<div class="config-actions-row" style="margin-top: 16px;"> <div class="config-actions-row" style="margin-top: 16px;">
<button class="config-btn-save" id="cfg-save-hidden-files">💾 Sauvegarder</button> <button class="config-btn-save" id="cfg-save-hidden-files">💾 Sauvegarder</button>
</div> </div>
@ -780,7 +758,7 @@
<section class="help-section" id="help-interface"> <section class="help-section" id="help-interface">
<h2>🧭 Interface utilisateur</h2> <h2>🧭 Interface utilisateur</h2>
<h3>En-tête</h3> <h3>En-tête</h3>
<p>La barre supérieure contient les éléments essentiels :</p> <p>La barre supérieure contient les éléments essentiels :</p>
<ul> <ul>
@ -1084,7 +1062,7 @@
</section> </section>
<div class="help-footer"> <div class="help-footer">
<p><strong>ObsiGate v1.2.0</strong> Porte d'entrée web pour vos vaults Obsidian</p> <p><strong>ObsiGate v1.2.0</strong> - Porte d'entrée web pour vos vaults Obsidian</p>
<p>Pour plus d'informations, consultez le <a href="https://git.dracodev.net/Projets/ObsiGate" target="_blank">dépôt du projet</a>.</p> <p>Pour plus d'informations, consultez le <a href="https://git.dracodev.net/Projets/ObsiGate" target="_blank">dépôt du projet</a>.</p>
</div> </div>
</div> </div>