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 -->
|
<!-- 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-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>
|
<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="flex:1;display:flex;justify-content:center">
|
||||||
<div style="position:relative;width:100%;max-width:400px">
|
<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>
|
<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: {},
|
_previewCache: {},
|
||||||
_previewPending: null,
|
_previewPending: null,
|
||||||
_ctrlHoverNode: null,
|
_ctrlHoverNode: null,
|
||||||
|
_navHistory: [],
|
||||||
|
_navIndex: -1,
|
||||||
|
|
||||||
async open(vault, path, type) {
|
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._vault = vault;
|
||||||
this._path = path;
|
this._path = path;
|
||||||
|
|
||||||
@ -88,6 +96,7 @@ export const GraphViewManager = {
|
|||||||
this._resetView();
|
this._resetView();
|
||||||
|
|
||||||
await this._fetchAndRender();
|
await this._fetchAndRender();
|
||||||
|
this._updateNavButtons();
|
||||||
safeCreateIcons();
|
safeCreateIcons();
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -196,6 +205,8 @@ export const GraphViewManager = {
|
|||||||
close() {
|
close() {
|
||||||
const modal = document.getElementById('graph-modal');
|
const modal = document.getElementById('graph-modal');
|
||||||
if (modal) modal.classList.remove('active');
|
if (modal) modal.classList.remove('active');
|
||||||
|
this._navHistory = [];
|
||||||
|
this._navIndex = -1;
|
||||||
if (this._animFrame) {
|
if (this._animFrame) {
|
||||||
cancelAnimationFrame(this._animFrame);
|
cancelAnimationFrame(this._animFrame);
|
||||||
this._animFrame = null;
|
this._animFrame = null;
|
||||||
@ -210,6 +221,68 @@ export const GraphViewManager = {
|
|||||||
this._nodePositions = {};
|
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() {
|
_initLayout() {
|
||||||
const w = this._canvas.parentElement.clientWidth;
|
const w = this._canvas.parentElement.clientWidth;
|
||||||
const h = this._canvas.parentElement.clientHeight;
|
const h = this._canvas.parentElement.clientHeight;
|
||||||
@ -810,6 +883,15 @@ export function initGraphView() {
|
|||||||
|
|
||||||
if (closeBtn) closeBtn.addEventListener('click', () => gm.close());
|
if (closeBtn) closeBtn.addEventListener('click', () => gm.close());
|
||||||
if (modal) modal.addEventListener('click', (e) => { if (e.target === modal) 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 (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 (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 (reset) reset.addEventListener('click', () => { gm._offsetX = 0; gm._offsetY = 0; gm._zoom = 1; });
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user