diff --git a/src/extension/src/command-executor.ts b/src/extension/src/command-executor.ts index 1a3ffdc2..9ea7507a 100644 --- a/src/extension/src/command-executor.ts +++ b/src/extension/src/command-executor.ts @@ -1,4 +1,5 @@ import * as vscode from "vscode"; +import { MESSAGES } from "../../shared/constants"; import { TerminalExecutor, QuickPickCreator } from "./adapters"; import { findMatchingShortcut } from "./keyboard-layout-converter"; import { ButtonConfig } from "./types"; @@ -85,11 +86,7 @@ export const createQuickPickWithShortcuts = ( const duplicates = validateShortcuts(config.items); if (duplicates.length > 0) { - vscode.window.showErrorMessage( - `Duplicate shortcuts detected: ${duplicates.join( - ", " - )}. Please ensure each shortcut is unique.` - ); + vscode.window.showErrorMessage(MESSAGES.ERROR.duplicateShortcuts(duplicates)); return; } @@ -183,8 +180,8 @@ const showGroupQuickPick = ( createQuickPickWithShortcuts( { items: items, - placeholder: "Select a command to execute", - title: `${button.name} Commands`, + placeholder: MESSAGES.INFO.selectCommand, + title: MESSAGES.INFO.groupCommands(button.name), }, terminalExecutor, quickPickCreator diff --git a/src/extension/src/config-constants.ts b/src/extension/src/config-constants.ts index c4f4a5cc..e8024074 100644 --- a/src/extension/src/config-constants.ts +++ b/src/extension/src/config-constants.ts @@ -1,17 +1,9 @@ import * as vscode from "vscode"; +import { CONFIG, CONFIGURATION_TARGET } from "../../shared/constants"; -export const CONFIG_SECTION = "quickCommandButtons"; - -export const CONFIG_KEYS = { - BUTTONS: "buttons", - CONFIGURATION_TARGET: "configurationTarget", - REFRESH_BUTTON: "refreshButton", -} as const; - -export const CONFIGURATION_TARGETS = { - GLOBAL: "global", - WORKSPACE: "workspace", -} as const; +export const CONFIG_SECTION = CONFIG.SECTION; +export const CONFIG_KEYS = CONFIG.KEYS; +export const CONFIGURATION_TARGETS = CONFIGURATION_TARGET; export const VS_CODE_CONFIGURATION_TARGETS = { [CONFIGURATION_TARGETS.GLOBAL]: vscode.ConfigurationTarget.Global, @@ -19,5 +11,5 @@ export const VS_CODE_CONFIGURATION_TARGETS = { } as const; export type ConfigurationTargetType = - (typeof CONFIGURATION_TARGETS)[keyof typeof CONFIGURATION_TARGETS]; -export type ConfigKeyType = (typeof CONFIG_KEYS)[keyof typeof CONFIG_KEYS]; + (typeof CONFIGURATION_TARGET)[keyof typeof CONFIGURATION_TARGET]; +export type ConfigKeyType = (typeof CONFIG.KEYS)[keyof typeof CONFIG.KEYS]; diff --git a/src/extension/src/show-all-commands.ts b/src/extension/src/show-all-commands.ts index 3734614d..eee0ac21 100644 --- a/src/extension/src/show-all-commands.ts +++ b/src/extension/src/show-all-commands.ts @@ -1,4 +1,5 @@ import * as vscode from "vscode"; +import { MESSAGES } from "../../shared/constants"; import { ConfigReader, QuickPickCreator, TerminalExecutor } from "./adapters"; import { createQuickPickWithShortcuts, QuickPickItem } from "./command-executor"; import { ButtonConfig } from "./types"; @@ -6,7 +7,9 @@ import { ButtonConfig } from "./types"; export const createQuickPickItemsFromButtons = (buttons: ButtonConfig[]): QuickPickItem[] => { return buttons.map((button) => ({ command: button, - description: button.group ? `${button.group.length} commands` : button.command || "", + description: button.group + ? MESSAGES.INFO.commandsCount(button.group.length) + : button.command || "", label: button.shortcut ? `${button.name} (${button.shortcut})` : button.name, })); }; @@ -20,7 +23,7 @@ export const createShowAllCommandsCommand = ( const buttons = configReader.getButtons(); if (buttons.length === 0) { - vscode.window.showInformationMessage("No commands found"); + vscode.window.showInformationMessage(MESSAGES.ERROR.noCommands); return; } @@ -29,8 +32,8 @@ export const createShowAllCommandsCommand = ( createQuickPickWithShortcuts( { items: items, - placeholder: "Select a command/group to execute (or type shortcut key)", - title: "Quick Commands", + placeholder: MESSAGES.INFO.selectCommandOrGroup, + title: MESSAGES.INFO.quickCommands, }, terminalExecutor, quickPickCreator diff --git a/src/shared/constants.ts b/src/shared/constants.ts new file mode 100644 index 00000000..88db34e5 --- /dev/null +++ b/src/shared/constants.ts @@ -0,0 +1,38 @@ +export const CONFIG = { + SECTION: "quickCommandButtons", + KEYS: { + BUTTONS: "buttons", + CONFIGURATION_TARGET: "configurationTarget", + REFRESH_BUTTON: "refreshButton", + }, +} as const; + +export const CONFIGURATION_TARGET = { + GLOBAL: "global", + WORKSPACE: "workspace", +} as const; + +export const MESSAGE_TYPE = { + GET_CONFIG: "getConfig", + SET_CONFIG: "setConfig", + SET_CONFIGURATION_TARGET: "setConfigurationTarget", + CONFIG_DATA: "configData", + CONFIGURATION_TARGET_CHANGED: "configurationTargetChanged", +} as const; + +export const MESSAGES = { + ERROR: { + contextRequired: (hookName: string) => + `${hookName} must be used within a VscodeCommandProvider`, + duplicateShortcuts: (shortcuts: string[]) => + `Duplicate shortcuts detected: ${shortcuts.join(", ")}. Please ensure each shortcut is unique.`, + noCommands: "No commands found", + }, + INFO: { + selectCommand: "Select a command to execute", + selectCommandOrGroup: "Select a command/group to execute (or type shortcut key)", + quickCommands: "Quick Commands", + groupCommands: (buttonName: string) => `${buttonName} Commands`, + commandsCount: (count: number) => `${count} commands`, + }, +} as const; diff --git a/src/web-view/src/components/header.tsx b/src/web-view/src/components/header.tsx index 60aa7186..d8852e46 100644 --- a/src/web-view/src/components/header.tsx +++ b/src/web-view/src/components/header.tsx @@ -1,5 +1,6 @@ import { Button } from "~/core"; +import { CONFIGURATION_TARGET } from "../../../shared/constants"; import { useCommandForm } from "../context/command-form-context.tsx"; import { useVscodeCommand } from "../context/vscode-command-context.tsx"; import { useDarkMode } from "../hooks/use-dark-mode.tsx"; @@ -10,7 +11,10 @@ export const Header = () => { const { isDark, toggleTheme } = useDarkMode(); const toggleConfigurationTarget = () => { - const newTarget = configurationTarget === "workspace" ? "global" : "workspace"; + const newTarget = + configurationTarget === CONFIGURATION_TARGET.WORKSPACE + ? CONFIGURATION_TARGET.GLOBAL + : CONFIGURATION_TARGET.WORKSPACE; setConfigurationTarget(newTarget); }; @@ -36,12 +40,12 @@ export const Header = () => {
Configuration Scope - {configurationTarget === "workspace" + {configurationTarget === CONFIGURATION_TARGET.WORKSPACE ? "📁 Workspace: Project-specific commands shared with team" : "🌐 Global: Personal commands across all projects"}
- {configurationTarget === "workspace" + {configurationTarget === CONFIGURATION_TARGET.WORKSPACE ? "Saved to .vscode/settings.json • Best for team collaboration" : "Saved to user settings • Best for personal workflow"}
@@ -50,13 +54,13 @@ export const Header = () => { className="border-border hover:bg-accent" onClick={toggleConfigurationTarget} title={ - configurationTarget === "workspace" + configurationTarget === CONFIGURATION_TARGET.WORKSPACE ? "Switch to Global settings (personal commands)" : "Switch to Workspace settings (team commands)" } variant="outline" > - {configurationTarget === "workspace" ? "📁 Workspace" : "🌐 Global"} + {configurationTarget === CONFIGURATION_TARGET.WORKSPACE ? "📁 Workspace" : "🌐 Global"}
diff --git a/src/web-view/src/context/vscode-command-context.tsx b/src/web-view/src/context/vscode-command-context.tsx index ee69708f..a6af854a 100644 --- a/src/web-view/src/context/vscode-command-context.tsx +++ b/src/web-view/src/context/vscode-command-context.tsx @@ -1,5 +1,6 @@ import { createContext, useContext, useEffect, useState, type ReactNode } from "react"; +import { MESSAGE_TYPE, MESSAGES, CONFIGURATION_TARGET } from "../../../shared/constants"; import { vscodeApi, isDevelopment } from "../core/vscode-api.tsx"; import { mockCommands } from "../mock/mock-data.tsx"; import { type ButtonConfig } from "../types"; @@ -20,7 +21,7 @@ const VscodeCommandContext = createContext export const useVscodeCommand = () => { const context = useContext(VscodeCommandContext); if (context === undefined) { - throw new Error("useVscodeCommand must be used within a VscodeCommandProvider"); + throw new Error(MESSAGES.ERROR.contextRequired("useVscodeCommand")); } return context; }; @@ -31,7 +32,9 @@ type VscodeCommandProviderProps = { export const VscodeCommandProvider = ({ children }: VscodeCommandProviderProps) => { const [commands, setCommands] = useState([]); - const [configurationTarget, setConfigurationTargetState] = useState("workspace"); + const [configurationTarget, setConfigurationTargetState] = useState( + CONFIGURATION_TARGET.WORKSPACE + ); useEffect(() => { if (isDevelopment) { @@ -40,18 +43,18 @@ export const VscodeCommandProvider = ({ children }: VscodeCommandProviderProps) } const requestConfig = () => { - vscodeApi.postMessage({ type: "getConfig" }); + vscodeApi.postMessage({ type: MESSAGE_TYPE.GET_CONFIG }); }; const handleMessage = (event: MessageEvent) => { const message = event.data; - if (message?.type === "configData") { + if (message?.type === MESSAGE_TYPE.CONFIG_DATA) { if (message.data && typeof message.data === "object" && message.data.buttons) { - // New format with configurationTarget setCommands(message.data.buttons || []); - setConfigurationTargetState(message.data.configurationTarget || "workspace"); + setConfigurationTargetState( + message.data.configurationTarget || CONFIGURATION_TARGET.WORKSPACE + ); } else { - // Old format (backward compatibility) setCommands(message.data || []); } } @@ -68,7 +71,7 @@ export const VscodeCommandProvider = ({ children }: VscodeCommandProviderProps) vscodeApi.setCurrentData(commands); return; } - vscodeApi.postMessage({ data: commands, type: "setConfig" }); + vscodeApi.postMessage({ data: commands, type: MESSAGE_TYPE.SET_CONFIG }); }; const addCommand = (command: ButtonConfig) => { @@ -94,7 +97,7 @@ export const VscodeCommandProvider = ({ children }: VscodeCommandProviderProps) const setConfigurationTarget = (target: string) => { setConfigurationTargetState(target); if (!isDevelopment) { - vscodeApi.postMessage({ target, type: "setConfigurationTarget" }); + vscodeApi.postMessage({ target, type: MESSAGE_TYPE.SET_CONFIGURATION_TARGET }); } };