diff --git a/src/main.ts b/src/main.ts index 15cb9e2..ceb0da5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,28 +1,122 @@ -import { Plugin, FileSystemAdapter, TFile } from 'obsidian'; +import { Plugin, FileSystemAdapter, TFile, MarkdownView, Notice } from 'obsidian'; import { LogfireSettings, DEFAULT_SETTINGS, deepMerge } from './types'; import { DatabaseManager } from './core/database'; +import { EventBus } from './core/event-bus'; +import { SessionManager } from './core/session-manager'; +import { ContentAnalyzer } from './core/content-analyzer'; +import { FileCollector } from './collectors/file-collector'; +import { ContentCollector } from './collectors/content-collector'; +import { NavCollector } from './collectors/nav-collector'; +import { EditorCollector } from './collectors/editor-collector'; +import { SystemCollector } from './collectors/system-collector'; import { LogfireSettingTab } from './ui/settings-tab'; +import { InitialScanModal } from './ui/initial-scan-modal'; export default class LogfirePlugin extends Plugin { settings!: LogfireSettings; db!: DatabaseManager; + eventBus!: EventBus; + sessionManager!: SessionManager; + contentAnalyzer!: ContentAnalyzer; + + private fileCollector!: FileCollector; + private contentCollector!: ContentCollector; + private navCollector!: NavCollector; + private editorCollector!: EditorCollector; + private systemCollector!: SystemCollector; + + private paused = false; async onload(): Promise { console.log('[Logfire] Lade Plugin...'); await this.loadSettings(); + // Core infrastructure const dbPath = this.getDatabasePath(); this.db = new DatabaseManager(dbPath, this.settings); + this.eventBus = new EventBus( + this.db, + this.settings.advanced.flushIntervalMs, + this.settings.advanced.flushThreshold, + ); + + const vaultName = this.app.vault.getName(); + this.sessionManager = new SessionManager(this.eventBus, this.db, vaultName); + + // Content analyzer + this.contentAnalyzer = new ContentAnalyzer(); + if (this.db.hasBaseline()) { + this.contentAnalyzer.loadBaseline(this.db.loadBaseline()); + } + + // Collectors + const shouldTrack = (path: string) => this.shouldTrack(path); + + this.fileCollector = new FileCollector( + this.app, this.eventBus, this.sessionManager, this.settings, shouldTrack, + ); + this.contentCollector = new ContentCollector( + this.app, this.eventBus, this.sessionManager, this.settings, this.contentAnalyzer, shouldTrack, + ); + this.navCollector = new NavCollector( + this.app, this.eventBus, this.sessionManager, this.settings, shouldTrack, + ); + this.editorCollector = new EditorCollector( + this.eventBus, this.sessionManager, this.settings, shouldTrack, + () => this.getActiveFilePath(), + ); + this.systemCollector = new SystemCollector( + this.app, this.eventBus, this.sessionManager, this.settings, + ); + + // Register CM6 editor extension + this.registerEditorExtension(this.editorCollector.createExtension()); + + // UI: Settings tab this.addSettingTab(new LogfireSettingTab(this.app, this)); - console.log('[Logfire] Plugin geladen.'); + // Commands + this.registerCommands(); + + // Start tracking + if (!this.settings.general.pauseOnStartup) { + this.startTracking(); + } else { + this.paused = true; + } + + // Initial scan + maintenance on startup (after layout ready) + this.app.workspace.onLayoutReady(() => { + if (!this.db.hasBaseline()) { + this.runInitialScan(); + } + if (this.settings.advanced.retention.maintenanceOnStartup) { + try { + this.db.runMaintenance(this.settings.advanced.retention); + } catch (err) { + console.error('[Logfire] Wartung beim Start fehlgeschlagen:', err); + } + } + }); + + console.log('[Logfire] Plugin geladen. Session:', this.sessionManager.currentSessionId); } async onunload(): Promise { console.log('[Logfire] Entlade Plugin...'); + this.stopTracking(); + + if (this.sessionManager) { + this.sessionManager.endSession(); + } + + if (this.eventBus) { + this.eventBus.destroy(); + } + if (this.db) { this.db.close(); } @@ -31,10 +125,65 @@ export default class LogfirePlugin extends Plugin { } // --------------------------------------------------------------------------- - // Track filtering (used by collectors in later features) + // Tracking lifecycle + // --------------------------------------------------------------------------- + + private startTracking(): void { + this.sessionManager.startSession(); + this.fileCollector.register(); + this.contentCollector.register(); + this.navCollector.register(); + this.systemCollector.register(); + } + + private stopTracking(): void { + this.fileCollector?.unregister(); + this.contentCollector?.unregister(); + this.navCollector?.unregister(); + this.systemCollector?.unregister(); + } + + isPaused(): boolean { + return this.paused; + } + + pause(): void { + if (!this.paused) { + this.paused = true; + this.stopTracking(); + } + } + + resume(): void { + if (this.paused) { + this.paused = false; + this.startTracking(); + } + } + + // --------------------------------------------------------------------------- + // Initial scan + // --------------------------------------------------------------------------- + + private async runInitialScan(): Promise { + const modal = new InitialScanModal( + this.app, + this.settings, + this.contentAnalyzer, + this.db, + this.eventBus, + this.sessionManager, + (path) => this.shouldTrack(path), + ); + await modal.open(); + } + + // --------------------------------------------------------------------------- + // Track filtering // --------------------------------------------------------------------------- shouldTrack(path: string): boolean { + if (this.paused) return false; if (!this.settings.general.enabled) return false; const logFolder = this.settings.general.logFolder; @@ -58,6 +207,62 @@ export default class LogfirePlugin extends Plugin { return true; } + private getActiveFilePath(): string | null { + const view = this.app.workspace.getActiveViewOfType(MarkdownView); + return view?.file?.path ?? null; + } + + // --------------------------------------------------------------------------- + // Commands + // --------------------------------------------------------------------------- + + private registerCommands(): void { + this.addCommand({ + id: 'toggle-tracking', + name: 'Tracking pausieren/fortsetzen', + callback: () => { + if (this.paused) { + this.resume(); + new Notice('Logfire: Tracking fortgesetzt.'); + } else { + this.pause(); + new Notice('Logfire: Tracking pausiert.'); + } + }, + }); + + this.addCommand({ + id: 'rescan-vault', + name: 'Vault erneut scannen', + callback: () => this.runInitialScan(), + }); + + this.addCommand({ + id: 'run-maintenance', + name: 'Wartung ausführen', + callback: () => { + this.db.runMaintenance(this.settings.advanced.retention); + new Notice('Logfire: Wartung abgeschlossen.'); + }, + }); + + this.addCommand({ + id: 'debug-info', + name: 'Debug-Info', + callback: () => { + console.log('[Logfire] Debug-Info:', { + paused: this.paused, + sessionId: this.sessionManager.currentSessionId, + sessionDuration: this.sessionManager.sessionDurationMs, + bufferSize: this.eventBus.getBufferSize(), + eventCount: this.db.getEventCount(), + hasBaseline: this.db.hasBaseline(), + dbSize: this.db.getDatabaseSizeBytes(), + }); + }, + }); + } + // --------------------------------------------------------------------------- // Settings // ---------------------------------------------------------------------------