mirror of
https://github.com/etaiso/obsidian-tag-fuzzy-find.git
synced 2026-07-22 06:53:02 +00:00
refactor: split settings UI into settingsTab.ts to keep settings.ts Node-pure
This commit is contained in:
parent
808dd4259b
commit
dea5fd83e3
5 changed files with 68 additions and 126 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import { Plugin } from "obsidian";
|
||||
import { DEFAULT_SETTINGS, PersistedData, PluginSettings } from "./types";
|
||||
import { normalizeSettings, TagFinderSettingTab } from "./settings";
|
||||
import { normalizeSettings } from "./settings";
|
||||
import { TagFinderSettingTab } from "./settingsTab";
|
||||
import { RecentTags, RecentTagsStore } from "./recentTags";
|
||||
import { TagSuggestModal } from "./tagSuggestModal";
|
||||
import { NoteSuggestModal } from "./noteSuggestModal";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import { App, PluginSettingTab, Setting, Notice } from "obsidian";
|
||||
import { DEFAULT_SETTINGS, EmptyStateMode, PluginSettings } from "./types";
|
||||
import type TagFinderPlugin from "./main";
|
||||
|
||||
const VALID_MODES: EmptyStateMode[] = ["recent-then-usage", "usage", "alphabetical", "blank"];
|
||||
|
||||
|
|
@ -26,69 +24,3 @@ export function normalizeSettings(raw: unknown): PluginSettings {
|
|||
|
||||
return { emptyStateMode, enableQuickSwitcherHook, recentLimit };
|
||||
}
|
||||
|
||||
// --- Settings tab UI (uses Obsidian runtime — not unit-tested) ---
|
||||
|
||||
export class TagFinderSettingTab extends PluginSettingTab {
|
||||
constructor(app: App, private plugin: TagFinderPlugin) {
|
||||
super(app, plugin);
|
||||
}
|
||||
|
||||
display(): void {
|
||||
const { containerEl, plugin } = this;
|
||||
containerEl.empty();
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Initial sort")
|
||||
.setDesc("Order of tags before you start typing.")
|
||||
.addDropdown(dd =>
|
||||
dd
|
||||
.addOptions({
|
||||
"recent-then-usage": "Recent, then most-used",
|
||||
"usage": "Most-used",
|
||||
"alphabetical": "Alphabetical",
|
||||
"blank": "Empty until typing",
|
||||
})
|
||||
.setValue(plugin.settings.emptyStateMode)
|
||||
.onChange(async value => {
|
||||
plugin.settings.emptyStateMode = value as typeof plugin.settings.emptyStateMode;
|
||||
await plugin.savePluginData();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Integrate with Quick Switcher")
|
||||
.setDesc("Open Tag Finder when the Quick Switcher input starts with '#'.")
|
||||
.addToggle(t =>
|
||||
t.setValue(plugin.settings.enableQuickSwitcherHook).onChange(async value => {
|
||||
plugin.settings.enableQuickSwitcherHook = value;
|
||||
await plugin.savePluginData();
|
||||
plugin.refreshQuickSwitcherHook();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Recent tags to remember")
|
||||
.setDesc("0 disables recent entirely.")
|
||||
.addSlider(s =>
|
||||
s
|
||||
.setLimits(0, 30, 1)
|
||||
.setValue(plugin.settings.recentLimit)
|
||||
.setDynamicTooltip()
|
||||
.onChange(async value => {
|
||||
plugin.settings.recentLimit = value;
|
||||
plugin.recent.setLimit(value);
|
||||
await plugin.savePluginData();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Recent tags")
|
||||
.addButton(b =>
|
||||
b.setButtonText("Clear recent tags").onClick(async () => {
|
||||
await plugin.recent.clear();
|
||||
new Notice("Recent tags cleared.");
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
66
src/settingsTab.ts
Normal file
66
src/settingsTab.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import { App, PluginSettingTab, Setting, Notice } from "obsidian";
|
||||
import type TagFinderPlugin from "./main";
|
||||
|
||||
export class TagFinderSettingTab extends PluginSettingTab {
|
||||
constructor(app: App, private plugin: TagFinderPlugin) {
|
||||
super(app, plugin);
|
||||
}
|
||||
|
||||
display(): void {
|
||||
const { containerEl, plugin } = this;
|
||||
containerEl.empty();
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Initial sort")
|
||||
.setDesc("Order of tags before you start typing.")
|
||||
.addDropdown(dd =>
|
||||
dd
|
||||
.addOptions({
|
||||
"recent-then-usage": "Recent, then most-used",
|
||||
"usage": "Most-used",
|
||||
"alphabetical": "Alphabetical",
|
||||
"blank": "Empty until typing",
|
||||
})
|
||||
.setValue(plugin.settings.emptyStateMode)
|
||||
.onChange(async value => {
|
||||
plugin.settings.emptyStateMode = value as typeof plugin.settings.emptyStateMode;
|
||||
await plugin.savePluginData();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Integrate with Quick Switcher")
|
||||
.setDesc("Open Tag Finder when the Quick Switcher input starts with '#'.")
|
||||
.addToggle(t =>
|
||||
t.setValue(plugin.settings.enableQuickSwitcherHook).onChange(async value => {
|
||||
plugin.settings.enableQuickSwitcherHook = value;
|
||||
await plugin.savePluginData();
|
||||
plugin.refreshQuickSwitcherHook();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Recent tags to remember")
|
||||
.setDesc("0 disables recent entirely.")
|
||||
.addSlider(s =>
|
||||
s
|
||||
.setLimits(0, 30, 1)
|
||||
.setValue(plugin.settings.recentLimit)
|
||||
.setDynamicTooltip()
|
||||
.onChange(async value => {
|
||||
plugin.settings.recentLimit = value;
|
||||
plugin.recent.setLimit(value);
|
||||
await plugin.savePluginData();
|
||||
}),
|
||||
);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Recent tags")
|
||||
.addButton(b =>
|
||||
b.setButtonText("Clear recent tags").onClick(async () => {
|
||||
await plugin.recent.clear();
|
||||
new Notice("Recent tags cleared.");
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
// Minimal runtime stub for the `obsidian` package in tests.
|
||||
// The real package ships only type declarations, so any code path that
|
||||
// imports runtime values from "obsidian" needs an alias during tests.
|
||||
export class PluginSettingTab {
|
||||
app: unknown;
|
||||
plugin: unknown;
|
||||
containerEl: { empty(): void };
|
||||
constructor(app: unknown, plugin: unknown) {
|
||||
this.app = app;
|
||||
this.plugin = plugin;
|
||||
this.containerEl = { empty: () => {} };
|
||||
}
|
||||
display(): void {}
|
||||
hide(): void {}
|
||||
}
|
||||
|
||||
export class Setting {
|
||||
constructor(_containerEl: unknown) {}
|
||||
setName(_v: string) { return this; }
|
||||
setDesc(_v: string) { return this; }
|
||||
addDropdown(_cb: (d: unknown) => unknown) { return this; }
|
||||
addToggle(_cb: (t: unknown) => unknown) { return this; }
|
||||
addSlider(_cb: (s: unknown) => unknown) { return this; }
|
||||
addButton(_cb: (b: unknown) => unknown) { return this; }
|
||||
}
|
||||
|
||||
export class Notice {
|
||||
constructor(_message: string) {}
|
||||
}
|
||||
|
||||
export class Plugin {
|
||||
app: unknown;
|
||||
constructor() { this.app = {}; }
|
||||
async loadData() { return null; }
|
||||
async saveData(_data: unknown) {}
|
||||
addCommand(_cmd: unknown) {}
|
||||
addSettingTab(_tab: unknown) {}
|
||||
async onload() {}
|
||||
async onunload() {}
|
||||
}
|
||||
|
||||
export class SuggestModal<T> {
|
||||
app: unknown;
|
||||
constructor(app: unknown) { this.app = app; }
|
||||
setPlaceholder(_v: string) {}
|
||||
open() {}
|
||||
close() {}
|
||||
}
|
||||
|
||||
export class App {}
|
||||
export class TFile {}
|
||||
|
|
@ -1,14 +1,8 @@
|
|||
import { defineConfig } from "vitest/config";
|
||||
import { resolve } from "node:path";
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
include: ["tests/**/*.test.ts"],
|
||||
environment: "node",
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
obsidian: resolve(__dirname, "tests/__mocks__/obsidian.ts"),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue