feat: onglet Accueil, menus contextuels de navigation et racine vault #158
- clic sur le titre: la page d'accueil s'ouvre dans un onglet Accueil (icone Maison) epingle en tete de barre, reactivable d'un clic (onglet propre au panneau actif en split) - page de navigation: menus contextuels des repertoires et des fichiers identiques a ceux de la sidebar, clic sur la racine d'un vault qui ouvre la vue, icone dossier a la couleur de l'arbre de navigation - BUG-101: bloc « Keyboard shortcuts for tabs » duplique dans ui.js (un seul Ctrl+W fermait deux onglets) - BUG-102: le menu contextuel se refermait 10 ms apres son ouverture (scroll de reflow des icones lucide)
This commit is contained in:
+48
-30
@@ -1776,7 +1776,12 @@ export const ContextMenuManager = {
|
||||
if (e.key === 'Escape') this.hide();
|
||||
});
|
||||
|
||||
document.addEventListener('scroll', () => this.hide(), true);
|
||||
document.addEventListener('scroll', () => {
|
||||
// Un scroll déclenché juste après l'ouverture vient de la reflow des
|
||||
// icônes (lucide) : on ne referme pas le menu qui vient d'apparaître.
|
||||
if (performance.now() - (this._shownAt || 0) < 250) return;
|
||||
this.hide();
|
||||
}, true);
|
||||
},
|
||||
|
||||
show(x, y, vault, path, type, isReadonly) {
|
||||
@@ -1822,6 +1827,7 @@ export const ContextMenuManager = {
|
||||
}
|
||||
|
||||
this._menu.classList.add('active');
|
||||
this._shownAt = performance.now();
|
||||
|
||||
const rect = this._menu.getBoundingClientRect();
|
||||
const viewportWidth = window.innerWidth;
|
||||
@@ -2133,9 +2139,38 @@ export const TabManager = {
|
||||
this.activate(tabId);
|
||||
},
|
||||
|
||||
/** Onglet Accueil (#158) : la page d'accueil vit dans un onglet épinglé tout
|
||||
* à gauche de la barre. Recréé (et remonté en position 0) à chaque clic sur
|
||||
* le titre. */
|
||||
async openHome() {
|
||||
// En split, l'onglet appartient au panneau actif
|
||||
if (window.getActiveTabManager && window.PaneManager && window.PaneManager.isSplit()) {
|
||||
return window.getActiveTabManager().openHome(t("common.home"));
|
||||
}
|
||||
const tabId = "home";
|
||||
const idx = this._tabs.findIndex(t => t.id === tabId);
|
||||
if (idx > 0) {
|
||||
const [tab] = this._tabs.splice(idx, 1);
|
||||
this._tabs.unshift(tab); // toujours en tête de barre
|
||||
} else if (idx === -1) {
|
||||
const name = t("common.home");
|
||||
this._tabs.unshift({ id: tabId, vault: null, path: "", name, icon: "home", home: true });
|
||||
this._tabCache[tabId] = { home: true, vault: null, path: "", title: name, data: null, rawSource: null, sourceView: false, scrollTop: 0, icon: "home" };
|
||||
}
|
||||
this._renderTabs();
|
||||
this.activate(tabId);
|
||||
},
|
||||
|
||||
/** Drop the active-tab marker — the dashboard/home page is showing.
|
||||
* Keeps the tabs open; clicking one re-activates (and re-renders) it. */
|
||||
* Keeps the tabs open; clicking one re-activates (and re-renders) it.
|
||||
* L'onglet Accueil, lui, reste l'onglet actif quand la page d'accueil
|
||||
* s'affiche (il EST la page d'accueil). */
|
||||
deactivate() {
|
||||
const active = this._activeTabId && this._tabCache[this._activeTabId];
|
||||
if (active && active.home) {
|
||||
this._renderTabs();
|
||||
return;
|
||||
}
|
||||
this._activeTabId = null;
|
||||
this._renderTabs();
|
||||
},
|
||||
@@ -2160,6 +2195,17 @@ export const TabManager = {
|
||||
const cache = this._tabCache[tabId];
|
||||
if (!cache) return;
|
||||
|
||||
// Onglet Accueil (#158) — la page d'accueil vit dans l'onglet
|
||||
if (cache.home) {
|
||||
state.currentVault = null;
|
||||
state.currentPath = null;
|
||||
showWelcome(); // conserve l'onglet Accueil actif (deactivate())
|
||||
if (history.pushState) {
|
||||
history.pushState(null, "", "#");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Navigation tab — render the directory view instead of fetching a file
|
||||
if (cache.nav) {
|
||||
state.currentVault = cache.vault;
|
||||
@@ -2556,32 +2602,4 @@ export const TabManager = {
|
||||
|
||||
|
||||
|
||||
// ---- 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 ----
|
||||
|
||||
Reference in New Issue
Block a user