feat: navigation graphe — ← → historique + ↑ Parent
This commit is contained in:
parent
5783811448
commit
14192f67d7
@ -703,6 +703,9 @@
|
||||
<!-- Header: 3 zones — titre | recherche | contrôles -->
|
||||
<div class="editor-header" style="display:flex;align-items:center;gap:12px;padding:8px 12px;border-bottom:1px solid var(--border-color)">
|
||||
<div class="editor-title" id="graph-title" style="font-weight:600;font-size:0.9rem;white-space:nowrap;flex-shrink:0;min-width:0;overflow:hidden;text-overflow:ellipsis">Vue Graphique</div>
|
||||
<button class="editor-btn" id="graph-nav-back" title="Retour" style="font-size:0.75rem;padding:2px 4px;opacity:0.5;flex-shrink:0" disabled>←</button>
|
||||
<button class="editor-btn" id="graph-nav-fwd" title="Avancer" style="font-size:0.75rem;padding:2px 4px;opacity:0.5;flex-shrink:0" disabled>→</button>
|
||||
<button class="editor-btn" id="graph-nav-up" title="Dossier parent" style="font-size:0.7rem;padding:2px 6px;flex-shrink:0;display:none">↑ Parent</button>
|
||||
<div style="flex:1;display:flex;justify-content:center">
|
||||
<div style="position:relative;width:100%;max-width:400px">
|
||||
<i data-lucide="search" style="position:absolute;left:10px;top:50%;transform:translateY(-50%);width:14px;height:14px;color:var(--text-muted);pointer-events:none"></i>
|
||||
|
||||
@ -59,8 +59,16 @@ export const GraphViewManager = {
|
||||
_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;
|
||||
|
||||
@ -88,6 +96,7 @@ export const GraphViewManager = {
|
||||
this._resetView();
|
||||
|
||||
await this._fetchAndRender();
|
||||
this._updateNavButtons();
|
||||
safeCreateIcons();
|
||||
},
|
||||
|
||||
@ -196,6 +205,8 @@ export const GraphViewManager = {
|
||||
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;
|
||||
@ -210,6 +221,68 @@ export const GraphViewManager = {
|
||||
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;
|
||||
@ -810,6 +883,15 @@ export function initGraphView() {
|
||||
|
||||
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; });
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user