diff --git a/frontend/index.html b/frontend/index.html
index 703a64c..7e5cf5e 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -717,6 +717,12 @@
+
+
@@ -725,10 +731,11 @@
-
-
🟦 Dossier
-
🟩 Fichier .md
-
⬜ Autre fichier
+
+
+
+
+ │
── Parent
┅┅ Wikilink
← Backlink
diff --git a/frontend/js/graph.js b/frontend/js/graph.js
index 6b8b956..18c4488 100644
--- a/frontend/js/graph.js
+++ b/frontend/js/graph.js
@@ -300,6 +300,7 @@ export const GraphViewManager = {
// Draw nodes
const searchLower = this._searchTerm.toLowerCase();
for (const node of this._nodes) {
+ if (!this._isNodeVisible(node)) continue;
const p = this._nodePositions[node.id];
if (!p) continue;
@@ -395,6 +396,48 @@ export const GraphViewManager = {
if (this._tooltipEl) this._tooltipEl.style.display = 'none';
},
+ // --- Advanced controls ---
+
+ _isNodeVisible(node) {
+ const showDir = document.getElementById('graph-filter-dir')?.checked ?? true;
+ const showMd = document.getElementById('graph-filter-md')?.checked ?? true;
+ const showOther = document.getElementById('graph-filter-other')?.checked ?? true;
+ if (node.type === 'directory') return showDir;
+ if (node.type === 'file' && (node.path || '').endsWith('.md')) return showMd;
+ if (node.type === 'file') return showOther;
+ return true;
+ },
+
+ applyTypeFilter() {
+ // Filters are applied during _draw() — nodes/edges not in visible set are skipped
+ },
+
+ exportPNG() {
+ const link = document.createElement('a');
+ link.download = `obsigate-graph-${this._vault}-${Date.now()}.png`;
+ link.href = this._canvas.toDataURL('image/png');
+ link.click();
+ },
+
+ toggleFullscreen() {
+ const container = this._canvas?.parentElement?.parentElement; // editor-container
+ if (!container) return;
+ if (document.fullscreenElement) {
+ document.exitFullscreen();
+ } else {
+ container.requestFullscreen();
+ }
+ // Re-init layout after fullscreen change
+ setTimeout(() => this._onResize(), 300);
+ },
+
+ focusNode(nodeId) {
+ const pos = this._nodePositions[nodeId];
+ if (!pos) return;
+ this._offsetX = this._width / 2 - pos.x * this._zoom;
+ this._offsetY = this._height / 2 - pos.y * this._zoom;
+ },
+
_onMouseDown(e) {
const rect = this._canvas.getBoundingClientRect();
const mx = e.clientX - rect.left;
@@ -520,6 +563,20 @@ export function initGraphView() {
});
}
+ // Export PNG
+ const exportBtn = document.getElementById('graph-export');
+ if (exportBtn) exportBtn.addEventListener('click', () => gm.exportPNG());
+
+ // Fullscreen
+ const fullscreenBtn = document.getElementById('graph-fullscreen');
+ if (fullscreenBtn) fullscreenBtn.addEventListener('click', () => gm.toggleFullscreen());
+
+ // Type filters
+ ['dir', 'md', 'other'].forEach(type => {
+ const cb = document.getElementById(`graph-filter-${type}`);
+ if (cb) cb.addEventListener('change', () => gm.applyTypeFilter());
+ });
+
if (canvas) {
canvas.addEventListener('mousedown', (e) => gm._onMouseDown(e));
canvas.addEventListener('mousemove', (e) => gm._onMouseMove(e));