From 6c851c921cb4359be3c66b144ed1ec8f79634ffd Mon Sep 17 00:00:00 2001 From: svemagie <869694+svemagie@users.noreply.github.com> Date: Wed, 4 Mar 2026 22:54:35 +0100 Subject: [PATCH] Fix plugin API compliance (audit) - Replace manual addEventListener with registerDomEvent on input listeners for automatic cleanup when the view closes - Expose setStatus(), setInputValue(), setExplicitContext() as public methods on ChatView; remove all @ts-ignore casts in main.ts - Remove duplicate claude-opus-4-5 entry from MODELS array - Remove empty authorUrl field from manifest.json Co-Authored-By: Claude Sonnet 4.6 --- .claude/settings.local.json | 11 +++++++++++ main.js | 23 ++++++++++++++--------- manifest.json | 1 - src/ChatView.ts | 18 ++++++++++++++---- src/SettingsTab.ts | 1 - src/main.ts | 13 +++---------- 6 files changed, 42 insertions(+), 25 deletions(-) create mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..357d29b --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,11 @@ +{ + "permissions": { + "allow": [ + "Bash(gh repo create memex-chat --public --source=. --remote=origin --push)", + "Bash(/opt/homebrew/bin/gh repo create memex-chat --public --source=. --remote=origin --push)", + "Bash(npm run build)", + "Bash(npm install)", + "WebFetch(domain:docs.obsidian.md)" + ] + } +} diff --git a/main.js b/main.js index 10f22b8..935f523 100644 --- a/main.js +++ b/main.js @@ -131,7 +131,7 @@ var ChatView = class extends import_obsidian.ItemView { this.sendBtn = inputActions.createEl("button", { cls: "vc-send-btn" }); this.sendBtn.setText("Senden"); this.sendBtn.onclick = () => this.handleSend(); - this.inputEl.addEventListener("keydown", (e) => { + this.registerDomEvent(this.inputEl, "keydown", (e) => { if (this.mentionDropdownEl.style.display !== "none") { if (e.key === "ArrowDown") { e.preventDefault(); @@ -164,7 +164,7 @@ var ChatView = class extends import_obsidian.ItemView { } } }); - this.inputEl.addEventListener("input", () => this.handleInputChange()); + this.registerDomEvent(this.inputEl, "input", () => this.handleInputChange()); this.renderThreadList(); } // ─── Thread Management ──────────────────────────────────────────────────── @@ -571,6 +571,14 @@ ${content}`; this.statusEl.setText(text); this.statusEl.style.display = text ? "block" : "none"; } + /** Pre-fill the input textarea (used from plugin commands) */ + setInputValue(value) { + this.inputEl.value = value; + } + /** Add files as explicit context (used from plugin commands) */ + setExplicitContext(files) { + this.explicitContext = files; + } handleInputChange() { var _a; this.inputEl.style.height = "auto"; @@ -1199,8 +1207,7 @@ Wenn du Fragen beantwortest: var MODELS = [ { id: "claude-opus-4-5-20251101", name: "Claude Opus 4.5 (St\xE4rkst)" }, { id: "claude-sonnet-4-5-20250929", name: "Claude Sonnet 4.5 (Empfohlen)" }, - { id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5 (Schnell)" }, - { id: "claude-opus-4-5-20251101", name: "Claude Opus 4.5" } + { id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5 (Schnell)" } ]; var MemexChatSettingsTab = class extends import_obsidian3.PluginSettingTab { constructor(app, plugin) { @@ -1509,8 +1516,8 @@ var MemexChatPlugin = class extends import_obsidian4.Plugin { const leaf = this.app.workspace.getLeavesOfType(VIEW_TYPE_MEMEX_CHAT)[0]; if (leaf) { const view = leaf.view; - view.inputEl.value = `Erkl\xE4re und verkn\xFCpfe [[${file.basename}]] mit anderen Konzepten im Vault.`; - view.explicitContext = [file]; + view.setInputValue(`Erkl\xE4re und verkn\xFCpfe [[${file.basename}]] mit anderen Konzepten im Vault.`); + view.setExplicitContext([file]); } }); } @@ -1554,9 +1561,7 @@ var MemexChatPlugin = class extends import_obsidian4.Plugin { this.search.onProgress = void 0; if (view) { view.setStatus(`\u2713 ${this.app.vault.getMarkdownFiles().length} Notizen indiziert`); - setTimeout(() => { - view.setStatus(""); - }, 3e3); + setTimeout(() => view.setStatus(""), 3e3); } } async saveSettings() { diff --git a/manifest.json b/manifest.json index 06e443f..28b8aa0 100644 --- a/manifest.json +++ b/manifest.json @@ -5,6 +5,5 @@ "minAppVersion": "1.4.0", "description": "Chat with your Obsidian vault using Claude AI — semantic context retrieval, @ mentions, thread history.", "author": "Sven", - "authorUrl": "", "isDesktopOnly": false } diff --git a/src/ChatView.ts b/src/ChatView.ts index ba58147..d105be3 100644 --- a/src/ChatView.ts +++ b/src/ChatView.ts @@ -172,8 +172,8 @@ export class ChatView extends ItemView { this.sendBtn.setText("Senden"); this.sendBtn.onclick = () => this.handleSend(); - // Key bindings - this.inputEl.addEventListener("keydown", (e) => { + // Key bindings — use registerDomEvent for automatic cleanup on view close + this.registerDomEvent(this.inputEl, "keydown", (e: KeyboardEvent) => { if (this.mentionDropdownEl.style.display !== "none") { if (e.key === "ArrowDown") { e.preventDefault(); @@ -207,7 +207,7 @@ export class ChatView extends ItemView { } }); - this.inputEl.addEventListener("input", () => this.handleInputChange()); + this.registerDomEvent(this.inputEl, "input", () => this.handleInputChange()); this.renderThreadList(); } @@ -668,11 +668,21 @@ export class ChatView extends ItemView { this.messagesEl.scrollTop = this.messagesEl.scrollHeight; } - private setStatus(text: string): void { + setStatus(text: string): void { this.statusEl.setText(text); this.statusEl.style.display = text ? "block" : "none"; } + /** Pre-fill the input textarea (used from plugin commands) */ + setInputValue(value: string): void { + this.inputEl.value = value; + } + + /** Add files as explicit context (used from plugin commands) */ + setExplicitContext(files: TFile[]): void { + this.explicitContext = files; + } + private handleInputChange(): void { // Auto-resize textarea this.inputEl.style.height = "auto"; diff --git a/src/SettingsTab.ts b/src/SettingsTab.ts index 8548b7b..9abb369 100644 --- a/src/SettingsTab.ts +++ b/src/SettingsTab.ts @@ -62,7 +62,6 @@ export const MODELS = [ { id: "claude-opus-4-5-20251101", name: "Claude Opus 4.5 (Stärkst)" }, { id: "claude-sonnet-4-5-20250929", name: "Claude Sonnet 4.5 (Empfohlen)" }, { id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5 (Schnell)" }, - { id: "claude-opus-4-5-20251101", name: "Claude Opus 4.5" }, ]; export class MemexChatSettingsTab extends PluginSettingTab { diff --git a/src/main.ts b/src/main.ts index a9c8a26..9de98ae 100644 --- a/src/main.ts +++ b/src/main.ts @@ -68,10 +68,8 @@ export default class MemexChatPlugin extends Plugin { const leaf = this.app.workspace.getLeavesOfType(VIEW_TYPE_MEMEX_CHAT)[0]; if (leaf) { const view = leaf.view as ChatView; - // @ts-ignore - view.inputEl.value = `Erkläre und verknüpfe [[${file.basename}]] mit anderen Konzepten im Vault.`; - // @ts-ignore - view.explicitContext = [file]; + view.setInputValue(`Erkläre und verknüpfe [[${file.basename}]] mit anderen Konzepten im Vault.`); + view.setExplicitContext([file]); } }); } @@ -116,7 +114,6 @@ export default class MemexChatPlugin extends Plugin { this.search.priorityProperties = this.settings.contextProperties; this.search.onProgress = (done, total) => { if (view && done % 200 === 0) { - // @ts-ignore view.setStatus(`Indiziere… ${done}/${total}`); } }; @@ -124,12 +121,8 @@ export default class MemexChatPlugin extends Plugin { await this.search.buildIndex(); this.search.onProgress = undefined; if (view) { - // @ts-ignore view.setStatus(`✓ ${this.app.vault.getMarkdownFiles().length} Notizen indiziert`); - setTimeout(() => { - // @ts-ignore - view.setStatus(""); - }, 3000); + setTimeout(() => view.setStatus(""), 3000); } }