import { Component, EventEmitter, Input, Output, ViewChild, inject, OnChanges, SimpleChanges } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; import { FileExplorerComponent } from '../../../components/file-explorer/file-explorer.component'; import { QuickLinksComponent } from '../quick-links/quick-links.component'; import { ScrollableOverlayDirective } from '../../shared/overlay-scrollbar/scrollable-overlay.directive'; import type { VaultNode, TagInfo } from '../../../types'; import { environment } from '../../../environments/environment'; import { VaultService } from '../../../services/vault.service'; import { UrlStateService } from '../../services/url-state.service'; import { SidebarStateService } from '../../services/sidebar-state.service'; import { FilterService } from '../../services/filter.service'; @Component({ selector: 'app-nimbus-sidebar', standalone: true, imports: [CommonModule, RouterModule, FileExplorerComponent, QuickLinksComponent, ScrollableOverlayDirective], host: { class: 'block h-full' }, template: `
ObsiViewer {{ vaultName }} - ObsiViewer
  • {{ t.count }}
La corbeille est vide
ObsiViewer
` }) export class NimbusSidebarComponent implements OnChanges { @Input() vaultName = ''; @Input() effectiveFileTree: VaultNode[] = []; @Input() selectedNoteId: string | null = null; @Input() tags: TagInfo[] = []; @Input() quickLinkFilter: 'favoris' | 'publish' | 'draft' | 'template' | 'task' | 'private' | 'archive' | null = null; @Input() forceOpenSection: 'folders' | 'tags' | 'quick' | null = null; @Output() toggleSidebarRequest = new EventEmitter(); @Output() folderSelected = new EventEmitter(); @Output() fileSelected = new EventEmitter(); @Output() tagSelected = new EventEmitter(); @Output() quickLinkSelected = new EventEmitter(); @Output() markdownPlaygroundSelected = new EventEmitter(); @Output() testsPanelSelected = new EventEmitter(); @Output() testsExcalidrawSelected = new EventEmitter(); @Output() helpPageSelected = new EventEmitter(); @Output() aboutSelected = new EventEmitter(); env = environment; open = { quick: true, folders: false, tags: false, trash: false, tests: false }; private vault = inject(VaultService); urlState = inject(UrlStateService); private sidebar = inject(SidebarStateService); filters = inject(FilterService); @ViewChild('foldersExplorer') private foldersExplorer?: FileExplorerComponent; ngOnChanges(changes: SimpleChanges): void { if (changes['forceOpenSection']) { const which = this.forceOpenSection; if (which === 'folders') { this.open = { quick: false, folders: true, tags: false, trash: false, tests: false }; } else if (which === 'tags') { this.open = { quick: false, folders: false, tags: true, trash: false, tests: false }; } else if (which === 'quick') { this.open = { quick: true, folders: false, tags: false, trash: false, tests: false }; } } } onQuickLink(id: string) { this.quickLinkSelected.emit(id); } onHomeClick(event: MouseEvent): void { event.preventDefault(); this.open = { quick: true, folders: false, tags: false, trash: false, tests: false }; this.sidebar.open('quick'); void this.urlState.setQuickWithMarkdown('all'); } onQuickLinksHeaderClick(event: MouseEvent): void { event.preventDefault(); this.open = { quick: true, folders: false, tags: false, trash: false, tests: false }; this.sidebar.open('quick'); void this.urlState.setQuickWithMarkdown('all'); } onMarkdownPlaygroundClick(): void { this.markdownPlaygroundSelected.emit(); } onApiTestsPanelClick(): void { this.testsPanelSelected.emit(); } trashNotes = () => this.vault.trashNotes(); trashCount = () => this.vault.counts().trash; trashHasContent = () => (this.vault.trashTree() || []).length > 0; trackNoteId = (_: number, n: { id: string }) => n.id; toggleSection(which: 'quick' | 'folders' | 'tags'): void { // Open requested section, close others, and reset filters/search via SidebarStateService this.open = { quick: false, folders: false, tags: false, trash: false, tests: false }; (this.open as any)[which] = true; this.sidebar.open(which); } onCreateFolderAtRoot(): void { // If not yet rendered, open the section first, then defer action if (!this.open.folders) { this.open.folders = true; setTimeout(() => this.foldersExplorer?.openCreateAtRoot(), 0); } else { this.foldersExplorer?.openCreateAtRoot(); } } toggleTrashSection(): void { const next = !this.open.trash; this.open.trash = next; if (next) { this.folderSelected.emit('.trash'); } } setKind(kind: 'image'|'video'|'pdf'|'markdown'|'excalidraw'|'code'|'all') { this.filters.toggleKind(kind === 'all' ? 'all' : kind as any); } chipClass(active: boolean): string { return active ? 'bg-primary/15 text-primary ring-1 ring-primary/40' : 'bg-surface1/50 text-muted hover:bg-surface1 dark:hover:bg-card'; } }