diff --git a/frontend/obsidian-plugin/src/vault-link-plugin.ts b/frontend/obsidian-plugin/src/vault-link-plugin.ts index 435cecd1..7e762a87 100644 --- a/frontend/obsidian-plugin/src/vault-link-plugin.ts +++ b/frontend/obsidian-plugin/src/vault-link-plugin.ts @@ -66,7 +66,7 @@ export default class VaultLinkPlugin extends Plugin { ); this.registerView( LogsView.TYPE, - (leaf) => new LogsView(this, this.client, leaf) + (leaf) => new LogsView(this.client, leaf) ); this.addRibbonIcon( diff --git a/frontend/obsidian-plugin/src/views/logs-view.ts b/frontend/obsidian-plugin/src/views/logs-view.ts index 9c852998..62a2bf22 100644 --- a/frontend/obsidian-plugin/src/views/logs-view.ts +++ b/frontend/obsidian-plugin/src/views/logs-view.ts @@ -1,14 +1,15 @@ import type { WorkspaceLeaf } from "obsidian"; import { ItemView } from "obsidian"; -import type VaultLinkPlugin from "../vault-link-plugin"; -import { LogLevel, type SyncClient } from "sync-client"; +import { LogLevel, LogLine, 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 logLineToElement: Map = new Map(); + public constructor( - private readonly plugin: VaultLinkPlugin, private readonly client: SyncClient, leaf: WorkspaceLeaf ) { @@ -36,76 +37,58 @@ export class LogsView extends ItemView { const container = this.containerEl.children[1]; container.addClass("logs-view"); + container.createEl("h4", { text: "VaultLink logs" }); + this.logsContainer = container.createDiv({ cls: "logs-container" }); } private updateView(): void { - const container = this.containerEl.children[1]; - - let logsContainer = container - .getElementsByClassName("logs-container") - .item(0); - const scrollPosition = logsContainer?.scrollTop; - - container.empty(); - - container.createEl("h4", { text: "VaultLink logs" }); - container.createEl( - "p", - { - text: "This view displays logs generated by VaultLink. You can set the log level in the " - }, - (p) => { - p.createEl( - "a", - { - text: "settings" - }, - (button) => { - button.addEventListener("click", () => { - this.plugin.openSettings(); - }); - } - ); - - p.createSpan({ text: "." }); - } - ); - - const logs = this.client.logger.getMessages(LogLevel.DEBUG); - - if (logs.length === 0) { - container.createEl("p", { text: "No logs available yet." }); + const container = this.logsContainer; + if (container === undefined) { return; } - logsContainer = container.createDiv( - { cls: "logs-container" }, - (element) => { - logs.forEach((message) => - element.createDiv( - { - cls: ["log-message", message.level] - }, - (messageContainer) => { - messageContainer.createEl("span", { - text: LogsView.formatTimestamp( - message.timestamp - ), - cls: "timestamp" - }); - messageContainer.createEl("span", { - text: message.message - }); - } - ) - ); - } - ); + const logs = this.client.logger.getMessages(LogLevel.DEBUG); - if (scrollPosition !== undefined) { - logsContainer.scrollTop = scrollPosition; - } else { - logsContainer.scrollTop = logsContainer.scrollHeight; + 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 = container.createDiv( + { + cls: ["log-message", message.level] + }, + (messageContainer) => { + messageContainer.createEl("span", { + text: LogsView.formatTimestamp(message.timestamp), + cls: "timestamp" + }); + messageContainer.createEl("span", { + text: message.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.createEl("p", { + text: "No logs available yet." + }); } } } diff --git a/frontend/sync-client/src/tracing/logger.ts b/frontend/sync-client/src/tracing/logger.ts index a2e7cf98..f817bc26 100644 --- a/frontend/sync-client/src/tracing/logger.ts +++ b/frontend/sync-client/src/tracing/logger.ts @@ -21,7 +21,7 @@ export class LogLine { } export class Logger { - private static readonly MAX_MESSAGES = 10000; + private static readonly MAX_MESSAGES = 2000; private readonly messages: LogLine[] = []; private readonly onMessageListeners: ((message: LogLine) => void)[] = [];