import type { WorkspaceLeaf } from "obsidian"; import { ItemView } from "obsidian"; import type { LogLine } from "sync-client"; import { LogLevel, type SyncClient } from "sync-client"; export class LogsView extends ItemView { public static readonly TYPE = "logs-view"; public static readonly ICON = "logs"; private logsContainer: HTMLElement | undefined; private readonly logLineToElement = new Map(); public constructor( private readonly client: SyncClient, leaf: WorkspaceLeaf ) { super(leaf); this.icon = LogsView.ICON; this.client.logger.addOnMessageListener(() => { this.updateView(); }); } private static createLogLineElement( container: HTMLElement, logLine: LogLine ): HTMLElement { return container.createDiv( { cls: ["log-message", logLine.level] }, (messageContainer) => { messageContainer.createEl("span", { text: LogsView.formatTimestamp(logLine.timestamp), cls: "timestamp" }); messageContainer.createEl("span", { text: logLine.message }); } ); } private static formatTimestamp(timestamp: Date): string { return timestamp.toTimeString().split(" ")[0]; } public getViewType(): string { return LogsView.TYPE; } public getDisplayText(): string { return "VaultLink logs"; } public async onOpen(): Promise { const container = this.containerEl.children[1]; container.addClass("logs-view"); container.createEl("h4", { text: "VaultLink logs" }); this.logsContainer = container.createDiv({ cls: "logs-container" }); this.updateView(); } private updateView(): void { const container = this.logsContainer; if (container === undefined) { return; } const logs = this.client.logger.getMessages(LogLevel.DEBUG); if (this.logLineToElement.size === 0 && logs.length > 0) { // Clear the "No logs available yet" message container.empty(); } logs.forEach((message) => { if (this.logLineToElement.has(message)) { return; } const element = LogsView.createLogLineElement(container, message); this.logLineToElement.set(message, element); }); const newLines = new Set(logs); for (const [logLine, element] of this.logLineToElement) { if (!newLines.has(logLine)) { element.remove(); this.logLineToElement.delete(logLine); } } if (logs.length === 0) { container.empty(); container.createEl("p", { text: "No logs available yet." }); } } }