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 <noreply@anthropic.com>
This commit is contained in:
svemagie
2026-03-04 22:54:35 +01:00
parent 5905c458fc
commit 6c851c921c
6 changed files with 42 additions and 25 deletions
+11
View File
@@ -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)"
]
}
}
+14 -9
View File
@@ -131,7 +131,7 @@ var ChatView = class extends import_obsidian.ItemView {
this.sendBtn = inputActions.createEl("button", { cls: "vc-send-btn" }); this.sendBtn = inputActions.createEl("button", { cls: "vc-send-btn" });
this.sendBtn.setText("Senden"); this.sendBtn.setText("Senden");
this.sendBtn.onclick = () => this.handleSend(); this.sendBtn.onclick = () => this.handleSend();
this.inputEl.addEventListener("keydown", (e) => { this.registerDomEvent(this.inputEl, "keydown", (e) => {
if (this.mentionDropdownEl.style.display !== "none") { if (this.mentionDropdownEl.style.display !== "none") {
if (e.key === "ArrowDown") { if (e.key === "ArrowDown") {
e.preventDefault(); 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(); this.renderThreadList();
} }
// ─── Thread Management ──────────────────────────────────────────────────── // ─── Thread Management ────────────────────────────────────────────────────
@@ -571,6 +571,14 @@ ${content}`;
this.statusEl.setText(text); this.statusEl.setText(text);
this.statusEl.style.display = text ? "block" : "none"; 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() { handleInputChange() {
var _a; var _a;
this.inputEl.style.height = "auto"; this.inputEl.style.height = "auto";
@@ -1199,8 +1207,7 @@ Wenn du Fragen beantwortest:
var MODELS = [ var MODELS = [
{ id: "claude-opus-4-5-20251101", name: "Claude Opus 4.5 (St\xE4rkst)" }, { 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-sonnet-4-5-20250929", name: "Claude Sonnet 4.5 (Empfohlen)" },
{ id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5 (Schnell)" }, { id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5 (Schnell)" }
{ id: "claude-opus-4-5-20251101", name: "Claude Opus 4.5" }
]; ];
var MemexChatSettingsTab = class extends import_obsidian3.PluginSettingTab { var MemexChatSettingsTab = class extends import_obsidian3.PluginSettingTab {
constructor(app, plugin) { 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]; const leaf = this.app.workspace.getLeavesOfType(VIEW_TYPE_MEMEX_CHAT)[0];
if (leaf) { if (leaf) {
const view = leaf.view; const view = leaf.view;
view.inputEl.value = `Erkl\xE4re und verkn\xFCpfe [[${file.basename}]] mit anderen Konzepten im Vault.`; view.setInputValue(`Erkl\xE4re und verkn\xFCpfe [[${file.basename}]] mit anderen Konzepten im Vault.`);
view.explicitContext = [file]; view.setExplicitContext([file]);
} }
}); });
} }
@@ -1554,9 +1561,7 @@ var MemexChatPlugin = class extends import_obsidian4.Plugin {
this.search.onProgress = void 0; this.search.onProgress = void 0;
if (view) { if (view) {
view.setStatus(`\u2713 ${this.app.vault.getMarkdownFiles().length} Notizen indiziert`); view.setStatus(`\u2713 ${this.app.vault.getMarkdownFiles().length} Notizen indiziert`);
setTimeout(() => { setTimeout(() => view.setStatus(""), 3e3);
view.setStatus("");
}, 3e3);
} }
} }
async saveSettings() { async saveSettings() {
-1
View File
@@ -5,6 +5,5 @@
"minAppVersion": "1.4.0", "minAppVersion": "1.4.0",
"description": "Chat with your Obsidian vault using Claude AI — semantic context retrieval, @ mentions, thread history.", "description": "Chat with your Obsidian vault using Claude AI — semantic context retrieval, @ mentions, thread history.",
"author": "Sven", "author": "Sven",
"authorUrl": "",
"isDesktopOnly": false "isDesktopOnly": false
} }
+14 -4
View File
@@ -172,8 +172,8 @@ export class ChatView extends ItemView {
this.sendBtn.setText("Senden"); this.sendBtn.setText("Senden");
this.sendBtn.onclick = () => this.handleSend(); this.sendBtn.onclick = () => this.handleSend();
// Key bindings // Key bindings — use registerDomEvent for automatic cleanup on view close
this.inputEl.addEventListener("keydown", (e) => { this.registerDomEvent(this.inputEl, "keydown", (e: KeyboardEvent) => {
if (this.mentionDropdownEl.style.display !== "none") { if (this.mentionDropdownEl.style.display !== "none") {
if (e.key === "ArrowDown") { if (e.key === "ArrowDown") {
e.preventDefault(); 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(); this.renderThreadList();
} }
@@ -668,11 +668,21 @@ export class ChatView extends ItemView {
this.messagesEl.scrollTop = this.messagesEl.scrollHeight; this.messagesEl.scrollTop = this.messagesEl.scrollHeight;
} }
private setStatus(text: string): void { setStatus(text: string): void {
this.statusEl.setText(text); this.statusEl.setText(text);
this.statusEl.style.display = text ? "block" : "none"; 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 { private handleInputChange(): void {
// Auto-resize textarea // Auto-resize textarea
this.inputEl.style.height = "auto"; this.inputEl.style.height = "auto";
-1
View File
@@ -62,7 +62,6 @@ export const MODELS = [
{ id: "claude-opus-4-5-20251101", name: "Claude Opus 4.5 (Stärkst)" }, { 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-sonnet-4-5-20250929", name: "Claude Sonnet 4.5 (Empfohlen)" },
{ id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5 (Schnell)" }, { 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 { export class MemexChatSettingsTab extends PluginSettingTab {
+3 -10
View File
@@ -68,10 +68,8 @@ export default class MemexChatPlugin extends Plugin {
const leaf = this.app.workspace.getLeavesOfType(VIEW_TYPE_MEMEX_CHAT)[0]; const leaf = this.app.workspace.getLeavesOfType(VIEW_TYPE_MEMEX_CHAT)[0];
if (leaf) { if (leaf) {
const view = leaf.view as ChatView; const view = leaf.view as ChatView;
// @ts-ignore view.setInputValue(`Erkläre und verknüpfe [[${file.basename}]] mit anderen Konzepten im Vault.`);
view.inputEl.value = `Erkläre und verknüpfe [[${file.basename}]] mit anderen Konzepten im Vault.`; view.setExplicitContext([file]);
// @ts-ignore
view.explicitContext = [file];
} }
}); });
} }
@@ -116,7 +114,6 @@ export default class MemexChatPlugin extends Plugin {
this.search.priorityProperties = this.settings.contextProperties; this.search.priorityProperties = this.settings.contextProperties;
this.search.onProgress = (done, total) => { this.search.onProgress = (done, total) => {
if (view && done % 200 === 0) { if (view && done % 200 === 0) {
// @ts-ignore
view.setStatus(`Indiziere… ${done}/${total}`); view.setStatus(`Indiziere… ${done}/${total}`);
} }
}; };
@@ -124,12 +121,8 @@ export default class MemexChatPlugin extends Plugin {
await this.search.buildIndex(); await this.search.buildIndex();
this.search.onProgress = undefined; this.search.onProgress = undefined;
if (view) { if (view) {
// @ts-ignore
view.setStatus(`${this.app.vault.getMarkdownFiles().length} Notizen indiziert`); view.setStatus(`${this.app.vault.getMarkdownFiles().length} Notizen indiziert`);
setTimeout(() => { setTimeout(() => view.setStatus(""), 3000);
// @ts-ignore
view.setStatus("");
}, 3000);
} }
} }