mirror of
https://github.com/dotwee/obsidian-raindropio-plugin.git
synced 2026-07-22 06:50:29 +00:00
feat(settings): support settings search with legacy fallback
Implement the declarative setting definitions API so plugin settings show up in the settings search on newer Obsidian versions. Add a self-contained control value reader/writer and an imperative fallback renderer so the tab keeps working on app versions that predate the declarative API. Lower the minimum app version to match the documented compatibility floor already declared in the version map. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
ad2baee012
commit
6779b5f539
2 changed files with 103 additions and 6 deletions
|
|
@ -2,7 +2,7 @@
|
|||
"id": "raindrop-io",
|
||||
"name": "Raindrop.io",
|
||||
"version": "1.0.4",
|
||||
"minAppVersion": "1.13.0",
|
||||
"minAppVersion": "1.7.2",
|
||||
"description": "Browse Raindrop.io links in notes with note-aware and configurable search filters.",
|
||||
"author": "Lukas '@dotWee' Wolfsteiner",
|
||||
"authorUrl": "https://lukas.wolfsteiner.media",
|
||||
|
|
|
|||
107
src/settings.ts
107
src/settings.ts
|
|
@ -1,5 +1,5 @@
|
|||
import { App, PluginSettingTab } from "obsidian";
|
||||
import type { SettingDefinitionItem } from "obsidian";
|
||||
import { App, PluginSettingTab, Setting } from "obsidian";
|
||||
import type { SettingControl, SettingDefinition, SettingDefinitionItem, SettingGroup } from "obsidian";
|
||||
import { DEFAULT_DISPLAY_FIELDS, type RaindropDisplayFields } from "./renderer";
|
||||
import type RaindropViewPlugin from "./main";
|
||||
|
||||
|
|
@ -151,9 +151,106 @@ export class RaindropSettingTab extends PluginSettingTab {
|
|||
];
|
||||
}
|
||||
|
||||
setControlValue(key: string, value: unknown): void | Promise<void> {
|
||||
if (key === "tagClickBehavior" && !isRaindropTagClickBehavior(value)) return;
|
||||
return super.setControlValue(key, typeof value === "string" ? value.trim() : value);
|
||||
// Implemented without super calls so the tab also works on Obsidian
|
||||
// versions before 1.13.0, where the SettingTab base class does not
|
||||
// provide getControlValue/setControlValue.
|
||||
getControlValue(key: string): unknown {
|
||||
return (this.plugin.settings as unknown as Record<string, unknown>)[key];
|
||||
}
|
||||
|
||||
async setControlValue(key: string, value: unknown): Promise<void> {
|
||||
if (key === "tagClickBehavior" && !isRaindropTagClickBehavior(value)) return;
|
||||
const normalized = typeof value === "string" ? value.trim() : value;
|
||||
(this.plugin.settings as unknown as Record<string, unknown>)[key] = normalized;
|
||||
await this.plugin.saveSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fallback for Obsidian versions before 1.13.0, which do not call
|
||||
* getSettingDefinitions(). Renders the same definitions imperatively.
|
||||
* On 1.13.0+ this method is never called because getSettingDefinitions()
|
||||
* returns a non-empty array.
|
||||
*/
|
||||
display(): void {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
this.renderDefinitionItems(this.getSettingDefinitions(), containerEl);
|
||||
}
|
||||
|
||||
private renderDefinitionItems(items: SettingDefinitionItem[], containerEl: HTMLElement): void {
|
||||
for (const item of items) {
|
||||
if ("type" in item && (item.type === "group" || item.type === "list")) {
|
||||
if (item.heading) {
|
||||
new Setting(containerEl).setName(item.heading).setHeading();
|
||||
}
|
||||
this.renderDefinitionItems(item.items ?? [], containerEl);
|
||||
continue;
|
||||
}
|
||||
if ("type" in item && item.type === "page") continue;
|
||||
this.renderDefinition(item as SettingDefinition, containerEl);
|
||||
}
|
||||
}
|
||||
|
||||
private renderDefinition(def: SettingDefinition, containerEl: HTMLElement): void {
|
||||
const setting = new Setting(containerEl).setName(def.name);
|
||||
if (def.desc) setting.setDesc(def.desc);
|
||||
if (def.render) {
|
||||
// Our render callbacks only use the Setting instance; SettingGroup
|
||||
// does not exist at runtime before 1.13.0.
|
||||
def.render(setting, undefined as unknown as SettingGroup);
|
||||
return;
|
||||
}
|
||||
if (def.control) this.renderControl(setting, def.control);
|
||||
}
|
||||
|
||||
private renderControl(setting: Setting, control: SettingControl): void {
|
||||
const rawValue = this.getControlValue(control.key) ?? control.defaultValue;
|
||||
const currentValue =
|
||||
typeof rawValue === "string" || typeof rawValue === "number" || typeof rawValue === "boolean"
|
||||
? rawValue
|
||||
: undefined;
|
||||
switch (control.type) {
|
||||
case "text":
|
||||
setting.addText((text) => {
|
||||
if (control.placeholder) text.setPlaceholder(control.placeholder);
|
||||
text.setValue(currentValue === undefined ? "" : String(currentValue)).onChange(async (value) => {
|
||||
if (control.validate && (await control.validate(value))) return;
|
||||
await this.setControlValue(control.key, value);
|
||||
});
|
||||
});
|
||||
break;
|
||||
case "number":
|
||||
setting.addText((text) => {
|
||||
text.inputEl.type = "number";
|
||||
if (control.min !== undefined) text.inputEl.min = String(control.min);
|
||||
if (control.max !== undefined) text.inputEl.max = String(control.max);
|
||||
if (control.step !== undefined) text.inputEl.step = String(control.step);
|
||||
if (control.placeholder) text.setPlaceholder(control.placeholder);
|
||||
text.setValue(currentValue === undefined ? "" : String(currentValue)).onChange(async (value) => {
|
||||
const parsed = Number(value);
|
||||
if (!Number.isFinite(parsed)) return;
|
||||
if (control.validate && (await control.validate(parsed))) return;
|
||||
await this.setControlValue(control.key, parsed);
|
||||
});
|
||||
});
|
||||
break;
|
||||
case "dropdown":
|
||||
setting.addDropdown((dropdown) => {
|
||||
dropdown.addOptions(control.options);
|
||||
dropdown.setValue(currentValue === undefined ? "" : String(currentValue)).onChange(async (value) => {
|
||||
await this.setControlValue(control.key, value);
|
||||
});
|
||||
});
|
||||
break;
|
||||
case "toggle":
|
||||
setting.addToggle((toggle) => {
|
||||
toggle.setValue(Boolean(currentValue)).onChange(async (value) => {
|
||||
await this.setControlValue(control.key, value);
|
||||
});
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue