Attention ! Cette action est irréversible.
@@ -532,7 +892,7 @@ export function initTagResize() {
this._closeModal(overlay);
await refreshSidebarTreePreservingState();
- if (state.currentVault === vault && state.currentPath === path) {
+ if (currentVault === vault && currentPath === path) {
showWelcome();
}
} catch (err) {
@@ -566,7 +926,7 @@ export function initTagResize() {
// ---------------------------------------------------------------------------
// Find in Page Manager
// ---------------------------------------------------------------------------
-export const FindInPageManager = {
+const FindInPageManager = {
isOpen: false,
searchTerm: "",
matches: [],
@@ -985,313 +1345,112 @@ export const FindInPageManager = {
};
// ---------------------------------------------------------------------------
-// Tab Manager
+// Init
// ---------------------------------------------------------------------------
-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(),
+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();
- init() {
- this._tabBar = document.getElementById("tab-bar");
- this._tabList = document.getElementById("tab-list");
- },
+ // Check auth status first
+ const authOk = await AuthManager.initAuth();
- /** 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 (authOk) {
+ // Start SSE sync AFTER auth is established (cookie available)
+ initSyncStatus();
- // 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;
- }
+ try {
+ await Promise.all([loadVaultSettings(), loadVaults(), loadTags()]);
- // 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;
+ // Initialize dashboard widgets now that vaults are loaded
+ if (typeof DashboardRecentWidget !== "undefined") {
+ DashboardRecentWidget.init();
}
- 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();
+ // Check for popup mode query parameter
+ const urlParams = new URLSearchParams(window.location.search);
+ if (urlParams.get("popup") === "true") {
+ document.body.classList.add("popup-mode");
}
- 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);
+ // 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);
}
- if (cache.scrollTop) {
- area.scrollTop = cache.scrollTop;
- }
- } catch (err) {
- area.innerHTML = `
Erreur: ${escapeHtml(err.message)}
`;
+ } 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();
+}
+
+// ---- 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);
}
}
-
- // 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(state.selectedContextVault);
- if (typeof DashboardBookmarkWidget !== "undefined") DashboardBookmarkWidget.load(state.selectedContextVault);
- if (history.pushState) {
- history.pushState(null, "", "#");
- }
- },
-
- /** Render the tab bar */
+// ---- Modify init to include TabManager ----
+const _origInit2 = init;
+init = function() {
+ _origInit2();
+ TabManager.init();
+};
\ No newline at end of file
diff --git a/frontend/js/viewer.js b/frontend/js/viewer.js
index d0016cc..b300ad5 100644
--- a/frontend/js/viewer.js
+++ b/frontend/js/viewer.js
@@ -1,9 +1,5 @@
-/* ObsiGate — Viewer module: Outline, ScrollSpy, ReadingProgress, file viewer, frontmatter card, editor init */
+/* ObsiGate — Auto-extracted module */
import { state } from './state.js';
-import { escapeHtml, safeCreateIcons, safeHighlight, getFileIcon } from "./utils.js";
-
-// initEditor is defined in utils.js — re-exported below.
-
// ---------------------------------------------------------------------------
// Outline/TOC Manager
// ---------------------------------------------------------------------------
@@ -118,7 +114,7 @@ const OutlineManager = {
outlineList.appendChild(item);
});
- state.headingsCache = headings;
+ headingsCache = headings;
},
/**
@@ -148,9 +144,9 @@ const OutlineManager = {
* Set active heading in outline
*/
setActiveHeading(headingId) {
- if (state.activeHeadingId === headingId) return;
+ if (activeHeadingId === headingId) return;
- state.activeHeadingId = headingId;
+ activeHeadingId = headingId;
const items = document.querySelectorAll(".outline-item");
items.forEach((item) => {
@@ -182,12 +178,11 @@ const OutlineManager = {
destroy() {
ScrollSpyManager.destroy();
ReadingProgressManager.destroy();
- state.headingsCache = [];
- state.activeHeadingId = null;
+ headingsCache = [];
+ activeHeadingId = null;
},
};
-
// ---------------------------------------------------------------------------
// Scroll Spy Manager
// ---------------------------------------------------------------------------
@@ -245,7 +240,6 @@ const ScrollSpyManager = {
},
};
-
// ---------------------------------------------------------------------------
// Reading Progress Manager
// ---------------------------------------------------------------------------
@@ -311,15 +305,14 @@ const ReadingProgressManager = {
},
};
-
// ---------------------------------------------------------------------------
// File viewer
// ---------------------------------------------------------------------------
async function openFile(vaultName, filePath) {
- state.currentVault = vaultName;
- state.currentPath = filePath;
- state.showingSource = false;
- state.cachedRawSource = null;
+ currentVault = vaultName;
+ currentPath = filePath;
+ showingSource = false;
+ cachedRawSource = null;
// Highlight active
syncActiveFileTreeItem(vaultName, filePath);
@@ -442,12 +435,12 @@ function renderFile(data) {
copyBtn.addEventListener("click", async () => {
try {
// Fetch raw content if not already cached
- if (!state.cachedRawSource) {
+ if (!cachedRawSource) {
const rawUrl = `/api/file/${encodeURIComponent(data.vault)}/raw?path=${encodeURIComponent(data.path)}`;
const rawData = await api(rawUrl);
- state.cachedRawSource = rawData.raw;
+ cachedRawSource = rawData.raw;
}
- await navigator.clipboard.writeText(state.cachedRawSource);
+ await navigator.clipboard.writeText(cachedRawSource);
copyBtn.lastChild.textContent = "Copié !";
setTimeout(() => (copyBtn.lastChild.textContent = "Copier"), 1500);
} catch (err) {
@@ -505,10 +498,194 @@ function renderFile(data) {
}
} catch (e) { /* ignore */ }
})();
- shareBtn.addEventListener("click",
+ shareBtn.addEventListener("click", () => openShareDialog(data.vault, data.path));
-... [OUTPUT TRUNCATED - 13907 chars omitted out of 63907 total] ...
+ // 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, 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();
+}
+
+// ---------------------------------------------------------------------------
+// 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(() => {
@@ -548,7 +725,7 @@ function renderFile(data) {
}
function getVaultIcon(vaultName, size = 16) {
- const v = state.allVaults.find((val) => val.name === vaultName);
+ const v = allVaults.find((val) => val.name === vaultName);
const type = v ? v.type : "VAULT";
if (type === "DIR") {
@@ -771,10 +948,10 @@ function showWelcome() {
DashboardConflictsWidget.load();
}
if (typeof DashboardRecentWidget !== "undefined") {
- DashboardRecentWidget.load(state.selectedContextVault);
+ DashboardRecentWidget.load(selectedContextVault);
}
if (typeof DashboardBookmarkWidget !== "undefined") {
- DashboardBookmarkWidget.load(state.selectedContextVault);
+ DashboardBookmarkWidget.load(selectedContextVault);
}
if (typeof DashboardSharedWidget !== "undefined") {
DashboardSharedWidget.load();
@@ -825,9 +1002,9 @@ async function loadSavedSearches() {
// 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;
+ 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");
@@ -842,8 +1019,8 @@ async function loadSavedSearches() {
AutocompleteDropdown._suppressNext = true;
const vault = s.vault || "all";
if (input) { input.dispatchEvent(new Event("input")); }
- clearTimeout(state.searchTimeout);
- state.advancedSearchOffset = 0;
+ clearTimeout(searchTimeout);
+ advancedSearchOffset = 0;
performAdvancedSearch(s.query, vault, null);
});
});
@@ -882,58 +1059,15 @@ function goHome() {
document.querySelectorAll(".tree-item.active").forEach((el) => el.classList.remove("active"));
- state.currentVault = null;
- state.currentPath = null;
- state.showingSource = false;
- state.cachedRawSource = null;
+ currentVault = null;
+ currentPath = null;
+ showingSource = false;
+ cachedRawSource = null;
closeMobileSidebar();
showWelcome();
}
-
-// initEditor wires up the editor modal — editor functions (openEditor, closeEditor, saveFile, deleteFile) are in utils.js
-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
// ---------------------------------------------------------------------------
@@ -1082,15 +1216,15 @@ const IndexUpdateManager = (() => {
// 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);
+ 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 && state.currentPath) {
- const changed = (data.changes || []).some((c) => c.vault === currentVault && c.path === state.currentPath);
+ if (currentVault && currentPath) {
+ const changed = (data.changes || []).some((c) => c.vault === currentVault && c.path === currentPath);
if (changed) {
- openFile(state.currentVault, state.currentPath);
+ openFile(currentVault, currentPath);
}
}
} catch (err) {
@@ -1099,7 +1233,7 @@ const IndexUpdateManager = (() => {
}
// Refresh recent tab if it is active
- if (state.activeSidebarTab === "recent") {
+ if (activeSidebarTab === "recent") {
const vaultFilter = document.getElementById("recent-vault-filter");
loadRecentFiles(vaultFilter ? vaultFilter.value || null : null);
}
@@ -1249,7 +1383,4 @@ function _renderSyncPanel(panel) {
}
panel.innerHTML = html;
-}
-
-export { OutlineManager, ScrollSpyManager, ReadingProgressManager, openFile, buildFrontmatterCard, initEditor };
-
+}
\ No newline at end of file