From 5905aa37b951869677395350d2dbc2d4ce607c50 Mon Sep 17 00:00:00 2001 From: Andras Schmelczer Date: Sat, 29 Nov 2025 14:24:53 +0000 Subject: [PATCH] Add copy to clipboard button --- .../src/views/logs/logs-view.scss | 18 ++++++++- .../src/views/logs/logs-view.ts | 39 ++++++++++++++++++- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/frontend/obsidian-plugin/src/views/logs/logs-view.scss b/frontend/obsidian-plugin/src/views/logs/logs-view.scss index 82ed1037..2bffe693 100644 --- a/frontend/obsidian-plugin/src/views/logs/logs-view.scss +++ b/frontend/obsidian-plugin/src/views/logs/logs-view.scss @@ -14,8 +14,22 @@ margin: 0; } - select { - cursor: pointer; + .logs-controls { + display: flex; + align-items: center; + gap: var(--size-4-2); + + button { + display: flex; + align-items: center; + gap: var(--size-2-1); + padding: var(--size-2-2) var(--size-4-2); + cursor: pointer; + } + + select { + cursor: pointer; + } } } diff --git a/frontend/obsidian-plugin/src/views/logs/logs-view.ts b/frontend/obsidian-plugin/src/views/logs/logs-view.ts index 19cf4701..68d597e4 100644 --- a/frontend/obsidian-plugin/src/views/logs/logs-view.ts +++ b/frontend/obsidian-plugin/src/views/logs/logs-view.ts @@ -1,7 +1,7 @@ import "./logs-view.scss"; import type { WorkspaceLeaf } from "obsidian"; -import { ItemView } from "obsidian"; +import { ItemView, Notice, setIcon } from "obsidian"; import type { LogLine } from "sync-client"; import { LogLevel, type SyncClient } from "sync-client"; @@ -78,7 +78,16 @@ export class LogsView extends ItemView { text: "VaultLink logs" }); - verbositySection.createEl("select", {}, (dropdown) => { + const controls = verbositySection.createDiv({ cls: "logs-controls" }); + + const copyButton = controls.createEl("button", { + text: "Copy logs", + cls: "clickable-icon" + }); + setIcon(copyButton, "clipboard-copy"); + copyButton.addEventListener("click", () => this.copyLogsToClipboard()); + + controls.createEl("select", {}, (dropdown) => { logLevels.forEach(({ label, value }) => dropdown.createEl("option", { text: label, value }) ); @@ -102,6 +111,32 @@ export class LogsView extends ItemView { this.updateView(); } + private copyLogsToClipboard(): void { + const logs = this.client.logger.getMessages(this.minLogLevel); + + if (logs.length === 0) { + new Notice("No logs to copy"); + return; + } + + const formattedLogs = logs + .map((logLine) => { + const timestamp = logLine.timestamp.toLocaleString(); + const level = logLine.level.toUpperCase(); + return `[${timestamp}] ${level}: ${logLine.message}`; + }) + .join("\n"); + + navigator.clipboard.writeText(formattedLogs) + .then(() => { + new Notice(`Copied ${logs.length} log entries to clipboard`); + }) + .catch((error: unknown) => { + this.client.logger.error(`Failed to copy logs to clipboard: ${error}`); + new Notice("Failed to copy logs to clipboard"); + }); + } + private updateView(): void { const container = this.logsContainer; if (container === undefined) {