feat(graph): Phase 3 — type filter, export PNG, fullscreen, focus node
- Type filter checkboxes (dossier, .md, autre) in legend - Export PNG button (canvas.toDataURL) - Fullscreen button (Fullscreen API) - Focus node function (center on specific node) - Filter applied during _draw() to skip hidden nodes
This commit is contained in:
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user