diff --git a/apps/desktop/src/App.vue b/apps/desktop/src/App.vue index 64afd838d2..2f05b1d8aa 100644 --- a/apps/desktop/src/App.vue +++ b/apps/desktop/src/App.vue @@ -8,6 +8,7 @@ import { TooltipProvider } from "@/components/ui/tooltip"; import AppToolbar from "@/components/layout/AppToolbar.vue"; import AppTabBar from "@/components/layout/AppTabBar.vue"; import { createGroupTabBarPortal, GROUP_TAB_BAR_PORTAL } from "@/components/layout/groupTabBarPortal"; +import PluginShortcutBar from "@/components/plugins/PluginShortcutBar.vue"; import AppSidebar from "@/components/layout/AppSidebar.vue"; import SqlEditorWorkspace from "@/components/layout/SqlEditorWorkspace.vue"; import { EDITOR_TOOLBAR_ACTIONS } from "@/components/layout/editorToolbarActions"; @@ -4154,6 +4155,7 @@ onUnmounted(() => { />
+ {
+ ({ store: null as any, @@ -175,6 +176,7 @@ async function mountSidebar() { setup: () => () => h(AppSidebar, { sidebarWidth: 260 }), }), ); + app.use(createPinia()); app.mount(host); mountedApps.push({ unmount: () => app.unmount(), host }); await nextTick(); diff --git a/apps/desktop/src/components/layout/AppSidebar.vue b/apps/desktop/src/components/layout/AppSidebar.vue index b21b4660cb..d5fb359cf1 100644 --- a/apps/desktop/src/components/layout/AppSidebar.vue +++ b/apps/desktop/src/components/layout/AppSidebar.vue @@ -8,6 +8,8 @@ import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from " import { Input } from "@/components/ui/input"; import LightDropdown from "@/components/ui/LightDropdown.vue"; import LightTooltip from "@/components/ui/LightTooltip.vue"; +import PluginShortcutBar from "@/components/plugins/PluginShortcutBar.vue"; +import { useSettingsStore } from "@/stores/settingsStore"; import ConnectionTree from "@/components/sidebar/ConnectionTree.vue"; import { applyConnectionMultiSelection, emptyConnectionMultiSelection, isExitConnectionMultiSelectionShortcut } from "@/lib/sidebar/sidebarConnectionMultiSelect"; import { connectionGroupDestinationRows } from "@/lib/sidebar/sidebarLayout"; @@ -33,6 +35,7 @@ type ImportSource = "dbx" | "navicat" | "dbeaver" | "datagrip"; const { t } = useI18n(); const connectionStore = useConnectionStore(); +const settingsStore = useSettingsStore(); const { toast } = useToast(); const connectionTreeRef = ref>(); const showDeleteSelectedConfirm = ref(false); @@ -296,6 +299,7 @@ defineExpose({ focusSearch, locateTabInSidebar });
+
diff --git a/apps/desktop/src/components/layout/AppToolbar.vue b/apps/desktop/src/components/layout/AppToolbar.vue index 3d64586437..4ae0833e4c 100644 --- a/apps/desktop/src/components/layout/AppToolbar.vue +++ b/apps/desktop/src/components/layout/AppToolbar.vue @@ -9,11 +9,9 @@ import LightDropdown from "@/components/ui/LightDropdown.vue"; import WindowControls from "@/components/layout/WindowControls.vue"; import ExportProgressPopover from "@/components/export/ExportProgressPopover.vue"; import ToolbarUpdateIcon from "@/components/layout/ToolbarUpdateIcon.vue"; +import PluginShortcutToolbar from "@/components/plugins/PluginShortcutToolbar.vue"; import { MAC_TRAFFIC_LIGHT_X, macTrafficLightInsetPaddingForScale, shouldReserveMacTrafficLightInset, useWindowControls } from "@/composables/useWindowControls"; import { useToast } from "@/composables/useToast"; -import PluginIcon from "@/components/plugins/PluginIcon.vue"; -import { setDockVisible, usePluginBottomDock } from "@/lib/plugins/pluginBottomDock"; -import { usePluginToolbarCommands, type PluginToolbarCommandEntry } from "@/lib/plugins/pluginCommandRegistry"; import { useSettingsStore } from "@/stores/settingsStore"; import { isSystemAppThemeMode, type AppThemeMode } from "@/lib/app/appTheme"; @@ -80,27 +78,6 @@ const emit = defineEmits<{ const { t } = useI18n(); const { toast } = useToast(); -// PR-A4 appToolbar surface (HOST_PLUGIN_UI_SPEC §5.1): plugin commands render as icons -// surface (next to Settings/AI); clicking runs the command (presentation: panel -> the global bottom dock), -// clicking again collapses an open dock command. -const { entries: pluginCommandEntries, open: openPluginCommand } = usePluginToolbarCommands(); -const { entries: pluginDockEntries, visible: dockVisible } = usePluginBottomDock(); -// The toolbar icon toggles panel visibility (panel hide keeps the webviews -// mounted, so sessions and height survive); with a hidden-but-populated dock -// the first click just restores it, and only an empty dock runs the command -// (otherwise "getting the panel back" would keep spawning new terminals). -function togglePluginCommand(entry: PluginToolbarCommandEntry) { - if (dockVisible.value) { - setDockVisible(false); - return; - } - if (pluginDockEntries.value.length) { - setDockVisible(true); - return; - } - const result = openPluginCommand(entry); - if (result.error) toast(result.error, 5000); -} const settingsStore = useSettingsStore(); const toolbarItems = computed(() => settingsStore.editorSettings.toolbarItems); const showToolbarUpdateEntry = computed(() => toolbarItems.value.checkUpdates || props.hasUpdateAvailable); @@ -186,6 +163,8 @@ function onToolbarDblClick(e: MouseEvent) { const toolbarEl = ref(); const newConnectionLabelEl = ref(); const toolbarCollapsed = ref(false); +const pluginCenterGroup = ref(null); +const showPluginCenterShortcuts = computed(() => settingsStore.editorSettings.pluginShortcuts.enabled && settingsStore.editorSettings.pluginShortcuts.position === "plugin-center"); const shouldReserveTrafficLightInset = computed(() => shouldReserveMacTrafficLightInset(isMac, isFullscreen.value, isDesktop)); function checkToolbarWidth() { @@ -611,10 +590,13 @@ const toolbarStyle = computed(() => { - +
+ + +
{