From a2dcc97f3e7da7006989c9042f23416dbfbad4ff Mon Sep 17 00:00:00 2001 From: John Morabito Date: Sat, 13 Jun 2026 19:31:17 -0400 Subject: [PATCH] feat: add Text Toolbar plugin integration Commander now detects the standalone Text Toolbar plugin at load time and: - Pushes saved commands into the toolbar via its public API (setCommands) - Shows a "Text Toolbar" tab in Commander settings when the plugin is installed, using the existing CommandViewer UI for add/remove/reorder The tab is hidden when the Text Toolbar plugin is not installed. Co-Authored-By: Claude Sonnet 4.6 --- src/constants.ts | 1 + src/main.ts | 6 +++ src/manager/commands/index.ts | 2 + .../commands/textToolbarIntegrationManager.ts | 44 +++++++++++++++++++ src/types.ts | 1 + src/ui/components/settingTabComponent.tsx | 14 ++++++ 6 files changed, 68 insertions(+) create mode 100644 src/manager/commands/textToolbarIntegrationManager.ts diff --git a/src/constants.ts b/src/constants.ts index a16ba8b..8e15742 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -14,6 +14,7 @@ export const DEFAULT_SETTINGS: CommanderSettings = { pageHeader: [], macros: [], explorer: [], + textToolbarCommands: [], hide: { statusbar: [], leftRibbon: [], diff --git a/src/main.ts b/src/main.ts index a9fa57a..1485472 100644 --- a/src/main.ts +++ b/src/main.ts @@ -14,6 +14,7 @@ import { FileMenuCommandManager, PageHeaderManager, StatusBarManager, + TextToolbarIntegrationManager, } from "./manager/commands"; import { Action, CommanderSettings } from "./types"; import CommanderSettingTab from "./ui/settingTab"; @@ -36,6 +37,7 @@ export default class CommanderPlugin extends Plugin { statusBar: StatusBarManager; pageHeader: PageHeaderManager; explorerManager: ExplorerManager; + textToolbarIntegration: TextToolbarIntegrationManager; }; public async executeStartupMacros(): Promise { @@ -95,6 +97,7 @@ export default class CommanderPlugin extends Plugin { statusBar: new StatusBarManager(this, this.settings.statusBar), pageHeader: new PageHeaderManager(this, this.settings.pageHeader), explorerManager: new ExplorerManager(this, this.settings.explorer), + textToolbarIntegration: new TextToolbarIntegrationManager(this, this.settings.textToolbarCommands), }; this.addSettingTab(new CommanderSettingTab(this)); @@ -127,6 +130,9 @@ export default class CommanderPlugin extends Plugin { injectIcons(this.settings.advancedToolbar, this); this.executeStartupMacros(); + + // Push saved commands into the Text Toolbar plugin if it is installed + this.manager.textToolbarIntegration.reorder(); }); } diff --git a/src/manager/commands/index.ts b/src/manager/commands/index.ts index 97577da..356298f 100644 --- a/src/manager/commands/index.ts +++ b/src/manager/commands/index.ts @@ -1,4 +1,5 @@ import ExplorerManager from "./explorerManager"; +import TextToolbarIntegrationManager from "./textToolbarIntegrationManager"; import { EditorMenuCommandManager, FileMenuCommandManager, @@ -12,6 +13,7 @@ export { FileMenuCommandManager, PageHeaderManager, StatusBarManager, + TextToolbarIntegrationManager, TitleBarManager, ExplorerManager, }; diff --git a/src/manager/commands/textToolbarIntegrationManager.ts b/src/manager/commands/textToolbarIntegrationManager.ts new file mode 100644 index 0000000..bde3c0e --- /dev/null +++ b/src/manager/commands/textToolbarIntegrationManager.ts @@ -0,0 +1,44 @@ +import CommanderPlugin from "src/main"; +import { CommandIconPair } from "src/types"; +import CommandManagerBase from "./commandManager"; + +interface TextToolbarAPI { + setCommands(cmds: { id: string; icon: string; name: string }[]): void; +} + +function getTextToolbarAPI(plugin: CommanderPlugin): TextToolbarAPI | undefined { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return (plugin.app as any).plugins?.plugins?.["text-toolbar"]?.api; +} + +export default class TextToolbarIntegrationManager extends CommandManagerBase { + public constructor(plugin: CommanderPlugin, pairs: CommandIconPair[]) { + super(plugin, pairs); + } + + private sync(): void { + const api = getTextToolbarAPI(this.plugin); + if (!api) return; + api.setCommands(this.pairs.map(p => ({ id: p.id, icon: p.icon, name: p.name }))); + } + + public static isAvailable(plugin: CommanderPlugin): boolean { + return getTextToolbarAPI(plugin) !== undefined; + } + + public async addCommand(pair: CommandIconPair): Promise { + this.pairs.push(pair); + await this.plugin.saveSettings(); + this.sync(); + } + + public async removeCommand(pair: CommandIconPair): Promise { + this.pairs.remove(pair); + await this.plugin.saveSettings(); + this.sync(); + } + + public reorder(): void { + this.sync(); + } +} diff --git a/src/types.ts b/src/types.ts index 3b83f1e..4d4f084 100644 --- a/src/types.ts +++ b/src/types.ts @@ -33,6 +33,7 @@ export interface CommanderSettings { pageHeader: CommandIconPair[]; explorer: CommandIconPair[]; macros: Macro[]; + textToolbarCommands: CommandIconPair[]; hide: { statusbar: string[]; leftRibbon: string[]; diff --git a/src/ui/components/settingTabComponent.tsx b/src/ui/components/settingTabComponent.tsx index 04c7c14..cc958a8 100644 --- a/src/ui/components/settingTabComponent.tsx +++ b/src/ui/components/settingTabComponent.tsx @@ -11,6 +11,7 @@ import CommandViewer from "./commandViewerComponent"; import { LeftRibbonHider, StatusbarHider } from "./hidingViewer"; import MacroViewer from "./MacroViewer"; import { SliderComponent, ToggleComponent } from "./settingComponent"; +import TextToolbarIntegrationManager from "src/manager/commands/textToolbarIntegrationManager"; export default function settingTabComponent({ plugin, @@ -256,6 +257,19 @@ export default function settingTabComponent({ ), }, + ...(TextToolbarIntegrationManager.isAvailable(plugin) + ? [ + { + name: "Text Toolbar", + tab: ( + + ), + }, + ] + : []), { name: Platform.isMobile ? "Mobile Toolbar" : "Toolbar", tab: ,