diff --git a/frontend/app/tab/tabbar.tsx b/frontend/app/tab/tabbar.tsx index 62e9052e31..476027b6af 100644 --- a/frontend/app/tab/tabbar.tsx +++ b/frontend/app/tab/tabbar.tsx @@ -75,6 +75,30 @@ const WaveAIButton = memo(({ divRef }: { divRef?: React.RefObject }) => { + const widgetsSidebarVisible = useAtomValue(WorkspaceLayoutModel.getInstance().widgetsSidebarVisibleAtom); + + const onClick = () => { + const current = WorkspaceLayoutModel.getInstance().getWidgetsSidebarVisible(); + WorkspaceLayoutModel.getInstance().setWidgetsSidebarVisible(!current); + }; + + return ( + + + + ); +}); +WidgetsSidebarButton.displayName = "WidgetsSidebarButton"; + function strArrayIsEqual(a: string[], b: string[]) { // null check if (a == null && b == null) { @@ -123,6 +147,7 @@ const TabBar = memo(({ workspace, noTabs }: TabBarProps) => { const rightContainerRef = useRef(null); const workspaceSwitcherRef = useRef(null); const waveAIButtonRef = useRef(null); + const widgetsSidebarButtonRef = createRef(); const appMenuButtonRef = useRef(null); const tabWidthRef = useRef(TabDefaultWidth); const scrollableRef = useRef(false); @@ -665,6 +690,7 @@ const TabBar = memo(({ workspace, noTabs }: TabBarProps) => {
+
{ ); }); -export { TabBar, WaveAIButton }; +export { TabBar, WaveAIButton, WidgetsSidebarButton }; diff --git a/frontend/app/workspace/workspace-layout-model.ts b/frontend/app/workspace/workspace-layout-model.ts index 1c86bb8a39..b15cd212b4 100644 --- a/frontend/app/workspace/workspace-layout-model.ts +++ b/frontend/app/workspace/workspace-layout-model.ts @@ -56,6 +56,7 @@ class WorkspaceLayoutModel { private focusTimeoutRef: NodeJS.Timeout | null = null; private debouncedPersistAIWidth: () => void; private debouncedPersistVTabWidth: () => void; + widgetsSidebarVisibleAtom: jotai.Atom; private constructor() { this.aiPanelRef = null; @@ -71,6 +72,7 @@ class WorkspaceLayoutModel { this.vtabWidth = VTabBar_DefaultWidth; this.vtabVisible = false; this.panelVisibleAtom = jotai.atom(false); + this.widgetsSidebarVisibleAtom = jotai.atom((get) => get(this.getWidgetsSidebarVisibleAtom()) ?? true); this.initializeFromMeta(); this.handleWindowResize = this.handleWindowResize.bind(this); @@ -135,6 +137,10 @@ class WorkspaceLayoutModel { return getOrefMetaKeyAtom(WOS.makeORef("workspace", this.getWorkspaceId()), "layout:vtabbarwidth"); } + private getWidgetsSidebarVisibleAtom(): jotai.Atom { + return getOrefMetaKeyAtom(WOS.makeORef("workspace", this.getWorkspaceId()), "layout:widgetsvisible"); + } + private initializeFromMeta(): void { try { const savedVisible = globalStore.get(this.getPanelOpenAtom()); @@ -352,6 +358,18 @@ class WorkspaceLayoutModel { return this.getResolvedAIWidth(window.innerWidth); } + getWidgetsSidebarVisible(): boolean { + return globalStore.get(this.widgetsSidebarVisibleAtom); + } + + setWidgetsSidebarVisible(visible: boolean): void { + if (globalStore.get(this.widgetsSidebarVisibleAtom) === visible) return; + RpcApi.SetMetaCommand(TabRpcClient, { + oref: WOS.makeORef("workspace", this.getWorkspaceId()), + meta: { "layout:widgetsvisible": visible }, + }); + } + // ---- Initial percentage helpers (used by workspace.tsx for defaultSize) ---- getLeftGroupInitialPercentage(windowWidth: number, showLeftTabBar: boolean): number { diff --git a/frontend/app/workspace/workspace.tsx b/frontend/app/workspace/workspace.tsx index 3e29bfa9f1..08278a4eed 100644 --- a/frontend/app/workspace/workspace.tsx +++ b/frontend/app/workspace/workspace.tsx @@ -46,6 +46,7 @@ const WorkspaceElem = memo(() => { const tabBarPosition = useAtomValue(getSettingsKeyAtom("app:tabbar")) ?? "top"; const showLeftTabBar = tabBarPosition === "left"; const aiPanelVisible = useAtomValue(workspaceLayoutModel.panelVisibleAtom); + const widgetsSidebarVisible = useAtomValue(workspaceLayoutModel.widgetsSidebarVisibleAtom); const windowWidth = window.innerWidth; const leftGroupInitialPct = workspaceLayoutModel.getLeftGroupInitialPercentage(windowWidth, showLeftTabBar); const innerVTabInitialPct = workspaceLayoutModel.getInnerVTabInitialPercentage(windowWidth, showLeftTabBar); @@ -158,7 +159,7 @@ const WorkspaceElem = memo(() => { ) : (
- + {widgetsSidebarVisible && }
)} diff --git a/frontend/types/gotypes.d.ts b/frontend/types/gotypes.d.ts index 0e56b7d345..53f8812841 100644 --- a/frontend/types/gotypes.d.ts +++ b/frontend/types/gotypes.d.ts @@ -1159,6 +1159,7 @@ declare global { "bg:bordercolor"?: string; "bg:activebordercolor"?: string; "layout:vtabbarwidth"?: number; + "layout:widgetsvisible"?: boolean; "waveai:panelopen"?: boolean; "waveai:panelwidth"?: number; "waveai:model"?: string; diff --git a/pkg/waveobj/metaconsts.go b/pkg/waveobj/metaconsts.go index f41435954c..0ce08099d8 100644 --- a/pkg/waveobj/metaconsts.go +++ b/pkg/waveobj/metaconsts.go @@ -100,6 +100,7 @@ const ( MetaKey_BgActiveBorderColor = "bg:activebordercolor" MetaKey_LayoutVTabBarWidth = "layout:vtabbarwidth" + MetaKey_LayoutWidgetsVisible = "layout:widgetsvisible" MetaKey_WaveAiPanelOpen = "waveai:panelopen" MetaKey_WaveAiPanelWidth = "waveai:panelwidth" diff --git a/pkg/waveobj/wtypemeta.go b/pkg/waveobj/wtypemeta.go index 4a36fdd46f..2280b55d2d 100644 --- a/pkg/waveobj/wtypemeta.go +++ b/pkg/waveobj/wtypemeta.go @@ -102,7 +102,8 @@ type MetaTSType struct { BgActiveBorderColor string `json:"bg:activebordercolor,omitempty"` // frame:activebordercolor // for workspace - LayoutVTabBarWidth int `json:"layout:vtabbarwidth,omitempty"` + LayoutVTabBarWidth int `json:"layout:vtabbarwidth,omitempty"` + LayoutWidgetsVisible *bool `json:"layout:widgetsvisible,omitempty"` // for tabs+waveai WaveAiPanelOpen bool `json:"waveai:panelopen,omitempty"`