Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion frontend/app/tab/tabbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,30 @@ const WaveAIButton = memo(({ divRef }: { divRef?: React.RefObject<HTMLDivElement
});
WaveAIButton.displayName = "WaveAIButton";

const WidgetsSidebarButton = memo(({ divRef }: { divRef?: React.RefObject<HTMLDivElement> }) => {
const widgetsSidebarVisible = useAtomValue(WorkspaceLayoutModel.getInstance().widgetsSidebarVisibleAtom);

const onClick = () => {
const current = WorkspaceLayoutModel.getInstance().getWidgetsSidebarVisible();
WorkspaceLayoutModel.getInstance().setWidgetsSidebarVisible(!current);
};

return (
<Tooltip
content="Toggle Widgets Sidebar"
placement="bottom"
hideOnClick
divClassName={`flex h-[22px] px-3.5 justify-end mb-1 items-center rounded-md mr-1 box-border cursor-pointer bg-hover hover:bg-hoverbg transition-colors text-[12px] ${widgetsSidebarVisible ? "text-accent" : "text-secondary"}`}
divStyle={{ WebkitAppRegion: "no-drag" } as React.CSSProperties}
divOnClick={onClick}
divRef={divRef}
>
<i className="fa fa-bars" />
</Tooltip>
);
});
WidgetsSidebarButton.displayName = "WidgetsSidebarButton";

function strArrayIsEqual(a: string[], b: string[]) {
// null check
if (a == null && b == null) {
Expand Down Expand Up @@ -123,6 +147,7 @@ const TabBar = memo(({ workspace, noTabs }: TabBarProps) => {
const rightContainerRef = useRef<HTMLDivElement>(null);
const workspaceSwitcherRef = useRef<HTMLDivElement>(null);
const waveAIButtonRef = useRef<HTMLDivElement>(null);
const widgetsSidebarButtonRef = createRef<HTMLDivElement>();
const appMenuButtonRef = useRef<HTMLDivElement>(null);
const tabWidthRef = useRef<number>(TabDefaultWidth);
const scrollableRef = useRef<boolean>(false);
Expand Down Expand Up @@ -665,6 +690,7 @@ const TabBar = memo(({ workspace, noTabs }: TabBarProps) => {
</button>
<div className="flex-1" />
<div ref={rightContainerRef} className="flex flex-row gap-1 items-end">
<WidgetsSidebarButton divRef={widgetsSidebarButtonRef} />
<UpdateStatusBanner />
<div
className="h-full shrink-0 z-window-drag"
Expand All @@ -675,4 +701,4 @@ const TabBar = memo(({ workspace, noTabs }: TabBarProps) => {
);
});

export { TabBar, WaveAIButton };
export { TabBar, WaveAIButton, WidgetsSidebarButton };
18 changes: 18 additions & 0 deletions frontend/app/workspace/workspace-layout-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class WorkspaceLayoutModel {
private focusTimeoutRef: NodeJS.Timeout | null = null;
private debouncedPersistAIWidth: () => void;
private debouncedPersistVTabWidth: () => void;
widgetsSidebarVisibleAtom: jotai.Atom<boolean>;

private constructor() {
this.aiPanelRef = null;
Expand All @@ -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);
Expand Down Expand Up @@ -135,6 +137,10 @@ class WorkspaceLayoutModel {
return getOrefMetaKeyAtom(WOS.makeORef("workspace", this.getWorkspaceId()), "layout:vtabbarwidth");
}

private getWidgetsSidebarVisibleAtom(): jotai.Atom<boolean | undefined> {
return getOrefMetaKeyAtom(WOS.makeORef("workspace", this.getWorkspaceId()), "layout:widgetsvisible");
}

private initializeFromMeta(): void {
try {
const savedVisible = globalStore.get(this.getPanelOpenAtom());
Expand Down Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion frontend/app/workspace/workspace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -158,7 +159,7 @@ const WorkspaceElem = memo(() => {
) : (
<div className="flex flex-row h-full">
<TabContent key={tabId} tabId={tabId} noTopPadding={showLeftTabBar && isMacOS()} />
<Widgets />
{widgetsSidebarVisible && <Widgets />}
</div>
)}
</Panel>
Expand Down
1 change: 1 addition & 0 deletions frontend/types/gotypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions pkg/waveobj/metaconsts.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
3 changes: 2 additions & 1 deletion pkg/waveobj/wtypemeta.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down