diff --git a/src/logger.ts b/src/logger.ts index a483177..36077e1 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -40,6 +40,14 @@ export default class Logger { ); } + async read(): Promise { + return await this.vault.adapter.read(this.logFile); + } + + async clean(): Promise { + return await this.vault.adapter.write(this.logFile, ""); + } + enable(): void { this.enabled = true; } diff --git a/src/settings/tab.ts b/src/settings/tab.ts index 5cad28b..8921460 100644 --- a/src/settings/tab.ts +++ b/src/settings/tab.ts @@ -1,5 +1,13 @@ -import { PluginSettingTab, App, Setting, TextComponent, Modal } from "obsidian"; +import { + PluginSettingTab, + App, + Setting, + TextComponent, + Modal, + Notice, +} from "obsidian"; import GitHubSyncPlugin from "src/main"; +import { copyToClipboard } from "src/utils"; export default class GitHubSyncSettingsTab extends PluginSettingTab { plugin: GitHubSyncPlugin; @@ -268,6 +276,30 @@ export default class GitHubSyncSettingsTab extends PluginSettingTab { }); }); + new Setting(containerEl) + .setName("Copy logs") + .setDesc("Copy the log file content, this is useful to report bugs.") + .addButton((button) => { + button.setButtonText("Copy").onClick(async () => { + const logs: string = await this.plugin.logger.read(); + try { + await copyToClipboard(logs); + new Notice("Logs copied", 5000); + } catch (err) { + new Notice(`Failed copying logs: ${err}`, 10000); + } + }); + }); + + new Setting(containerEl) + .setName("Clean logs") + .setDesc("Delete all existing logs.") + .addButton((button) => { + button.setButtonText("Clean").onClick(async () => { + await this.plugin.logger.clean(); + }); + }); + new Setting(containerEl) .setName("Reset") .setDesc("Reset the plugin settings and metadata") diff --git a/src/utils.ts b/src/utils.ts index 8f4ceb0..5fd531f 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -12,3 +12,28 @@ export function decodeBase64String(s: string): string { const decoder = new TextDecoder(); return decoder.decode(buffer); } + +/** + * Copies the provided text to the system clipboard. + * Uses the modern Clipboard API with a fallback to older APIs. + * + * @param text The string to be copied to clipboard + * @returns A promise that resolves when the text has been copied + */ +export async function copyToClipboard(text: string) { + try { + await navigator.clipboard.writeText(text); + } catch (err) { + // Fallback for devices like iOS that don't support Clipboard API + const textarea = document.createElement("textarea"); + textarea.value = text; + textarea.setAttribute("readonly", ""); + textarea.style.position = "absolute"; + textarea.style.left = "-9999px"; + document.body.appendChild(textarea); + + textarea.select(); + document.execCommand("copy"); + document.body.removeChild(textarea); + } +}