Skip to content

Commit 9d4acb7

Browse files
Copilotsawka
andauthored
Add builder-launch strip to AppsFloatingWindow (#2979)
AppsFloatingWindow currently lists local apps but does not provide an in-context way to open the app builder picker. This change adds a bottom ghost-style action strip (`+ Build/Edit Apps`) that launches the builder via Electron preload with `openBuilder(null)`. - **What changed** - Added a new bottom strip action inside `AppsFloatingWindow`: - Label: `+ Build/Edit Apps` - Visual style: ghost-like footer strip with top border, hover state, full-width click target - Wired the strip to call the preload API and close the floating window: - `getApi().openBuilder(null)` (`null` app id opens the app picker) - Kept the change scoped to `frontend/app/workspace/widgets.tsx` with no behavior changes to app-grid item launching. - **Implementation detail** - Imported `getApi` from `@/store/global` - Added a memoized handler for builder launch: ```tsx const handleOpenBuilder = useCallback(() => { getApi().openBuilder(null); onClose(); }, [onClose]); ``` - **UI preview** - <screenshot>https://github.com/user-attachments/assets/1448588f-ff1d-41b5-af72-2849135ca1f3</screenshot> <!-- START COPILOT CODING AGENT TIPS --> --- ✨ Let Copilot coding agent [set things up for you](https://github.com/wavetermdev/waveterm/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: sawka <2722291+sawka@users.noreply.github.com> Co-authored-by: sawka <mike@commandline.dev>
1 parent 73f7715 commit 9d4acb7

1 file changed

Lines changed: 62 additions & 48 deletions

File tree

frontend/app/workspace/widgets.tsx

Lines changed: 62 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ContextMenuModel } from "@/app/store/contextmenu";
66
import { RpcApi } from "@/app/store/wshclientapi";
77
import { TabRpcClient } from "@/app/store/wshrpcutil";
88
import { shouldIncludeWidgetForWorkspace } from "@/app/workspace/widgetfilter";
9-
import { atoms, createBlock, isDev } from "@/store/global";
9+
import { atoms, createBlock, getApi, isDev } from "@/store/global";
1010
import { fireAndForget, isBlank, makeIconClass } from "@/util/util";
1111
import {
1212
FloatingPortal,
@@ -111,6 +111,10 @@ const AppsFloatingWindow = memo(
111111

112112
const dismiss = useDismiss(context);
113113
const { getFloatingProps } = useInteractions([dismiss]);
114+
const handleOpenBuilder = useCallback(() => {
115+
getApi().openBuilder(null);
116+
onClose();
117+
}, [onClose]);
114118

115119
useEffect(() => {
116120
if (!isOpen) return;
@@ -148,55 +152,65 @@ const AppsFloatingWindow = memo(
148152
ref={refs.setFloating}
149153
style={floatingStyles}
150154
{...getFloatingProps()}
151-
className="bg-modalbg border border-border rounded-lg shadow-xl p-4 z-50"
155+
className="bg-modalbg border border-border rounded-lg shadow-xl z-50 overflow-hidden"
152156
>
153-
{loading ? (
154-
<div className="flex items-center justify-center p-8">
155-
<i className="fa fa-solid fa-spinner fa-spin text-2xl text-muted"></i>
156-
</div>
157-
) : apps.length === 0 ? (
158-
<div className="text-muted text-sm p-4 text-center">No local apps found</div>
159-
) : (
160-
<div
161-
className="grid gap-3"
162-
style={{
163-
gridTemplateColumns: `repeat(${gridSize}, minmax(0, 1fr))`,
164-
maxWidth: `${gridSize * 80}px`,
165-
}}
166-
>
167-
{apps.map((app) => {
168-
const appMeta = app.manifest?.appmeta;
169-
const displayName = app.appid.replace(/^local\//, "");
170-
const icon = appMeta?.icon || "cube";
171-
const iconColor = appMeta?.iconcolor || "white";
172-
173-
return (
174-
<div
175-
key={app.appid}
176-
className="flex flex-col items-center justify-center p-2 rounded hover:bg-hoverbg cursor-pointer transition-colors"
177-
onClick={() => {
178-
const blockDef: BlockDef = {
179-
meta: {
180-
view: "tsunami",
181-
controller: "tsunami",
182-
"tsunami:appid": app.appid,
183-
},
184-
};
185-
createBlock(blockDef);
186-
onClose();
187-
}}
188-
>
189-
<div style={{ color: iconColor }} className="text-3xl mb-1">
190-
<i className={makeIconClass(icon, false)}></i>
191-
</div>
192-
<div className="text-xxs text-center text-secondary break-words w-full px-1">
193-
{displayName}
157+
<div className="p-4">
158+
{loading ? (
159+
<div className="flex items-center justify-center p-8">
160+
<i className="fa fa-solid fa-spinner fa-spin text-2xl text-muted"></i>
161+
</div>
162+
) : apps.length === 0 ? (
163+
<div className="text-muted text-sm p-4 text-center">No local apps found</div>
164+
) : (
165+
<div
166+
className="grid gap-3"
167+
style={{
168+
gridTemplateColumns: `repeat(${gridSize}, minmax(0, 1fr))`,
169+
maxWidth: `${gridSize * 80}px`,
170+
}}
171+
>
172+
{apps.map((app) => {
173+
const appMeta = app.manifest?.appmeta;
174+
const displayName = app.appid.replace(/^local\//, "");
175+
const icon = appMeta?.icon || "cube";
176+
const iconColor = appMeta?.iconcolor || "white";
177+
178+
return (
179+
<div
180+
key={app.appid}
181+
className="flex flex-col items-center justify-center p-2 rounded hover:bg-hoverbg cursor-pointer transition-colors"
182+
onClick={() => {
183+
const blockDef: BlockDef = {
184+
meta: {
185+
view: "tsunami",
186+
controller: "tsunami",
187+
"tsunami:appid": app.appid,
188+
},
189+
};
190+
createBlock(blockDef);
191+
onClose();
192+
}}
193+
>
194+
<div style={{ color: iconColor }} className="text-3xl mb-1">
195+
<i className={makeIconClass(icon, false)}></i>
196+
</div>
197+
<div className="text-xxs text-center text-secondary break-words w-full px-1">
198+
{displayName}
199+
</div>
194200
</div>
195-
</div>
196-
);
197-
})}
198-
</div>
199-
)}
201+
);
202+
})}
203+
</div>
204+
)}
205+
</div>
206+
<button
207+
type="button"
208+
className="w-full px-4 py-2 border-t border-border text-xs text-secondary text-center hover:bg-hoverbg hover:text-white transition-colors cursor-pointer flex items-center justify-center gap-2"
209+
onClick={handleOpenBuilder}
210+
>
211+
<i className="fa fa-solid fa-hammer"></i>
212+
Build/Edit Apps
213+
</button>
200214
</div>
201215
</FloatingPortal>
202216
);

0 commit comments

Comments
 (0)