Skip to content

Commit da0de63

Browse files
committed
get icon/icon color implemented in appmeta and show in wave UI
1 parent a3dce97 commit da0de63

File tree

8 files changed

+56
-17
lines changed

8 files changed

+56
-17
lines changed

frontend/app/block/blockframe.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,19 @@ function handleHeaderContextMenu(
8585
ContextMenuModel.showContextMenu(menu, e);
8686
}
8787

88-
function getViewIconElem(viewIconUnion: string | IconButtonDecl, blockData: Block): React.ReactElement {
88+
function getViewIconElem(
89+
viewIconUnion: string | IconButtonDecl,
90+
blockData: Block,
91+
iconColor?: string
92+
): React.ReactElement {
8993
if (viewIconUnion == null || typeof viewIconUnion === "string") {
9094
const viewIcon = viewIconUnion as string;
91-
return <div className="block-frame-view-icon">{getBlockHeaderIcon(viewIcon, blockData)}</div>;
95+
const style: React.CSSProperties = iconColor ? { color: iconColor, opacity: 1.0 } : {};
96+
return (
97+
<div className="block-frame-view-icon" style={style}>
98+
{getBlockHeaderIcon(viewIcon, blockData)}
99+
</div>
100+
);
92101
} else {
93102
return <IconButton decl={viewIconUnion} className="block-frame-view-icon" />;
94103
}
@@ -172,6 +181,7 @@ const BlockFrame_Header = ({
172181
let viewName = util.useAtomValueSafe(viewModel?.viewName) ?? blockViewToName(blockData?.meta?.view);
173182
const showBlockIds = jotai.useAtomValue(getSettingsKeyAtom("blockheader:showblockids"));
174183
let viewIconUnion = util.useAtomValueSafe(viewModel?.viewIcon) ?? blockViewToIcon(blockData?.meta?.view);
184+
const viewIconColor = util.useAtomValueSafe(viewModel?.viewIconColor);
175185
const preIconButton = util.useAtomValueSafe(viewModel?.preIconButton);
176186
let headerTextUnion = util.useAtomValueSafe(viewModel?.viewText);
177187
const magnified = jotai.useAtomValue(nodeModel.isMagnified);
@@ -208,7 +218,7 @@ const BlockFrame_Header = ({
208218
);
209219

210220
const endIconsElem = computeEndIcons(viewModel, nodeModel, onContextMenu);
211-
const viewIconElem = getViewIconElem(viewIconUnion, blockData);
221+
const viewIconElem = getViewIconElem(viewIconUnion, blockData, viewIconColor);
212222
let preIconButtonElem: React.ReactElement = null;
213223
if (preIconButton) {
214224
preIconButtonElem = <IconButton decl={preIconButton} className="block-frame-preicon-button" />;

frontend/app/view/tsunami/tsunami.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ class TsunamiViewModel extends WebViewModel {
1818
appMetaUnsubFn: () => void;
1919
isRestarting: jotai.PrimitiveAtom<boolean>;
2020
viewName: jotai.Atom<string>;
21+
viewIconColor: jotai.Atom<string>;
2122

2223
constructor(blockId: string, nodeModel: BlockNodeModel) {
2324
super(blockId, nodeModel);
2425
this.viewType = "tsunami";
25-
this.viewIcon = jotai.atom("cube");
2626
this.isRestarting = jotai.atom(false);
2727

2828
// Hide navigation bar (URL bar, back/forward/home buttons)
@@ -46,6 +46,14 @@ class TsunamiViewModel extends WebViewModel {
4646
});
4747

4848
this.appMeta = jotai.atom(null) as jotai.PrimitiveAtom<AppMeta>;
49+
this.viewIcon = jotai.atom((get) => {
50+
const meta = get(this.appMeta);
51+
return meta?.icon || "cube";
52+
});
53+
this.viewIconColor = jotai.atom((get) => {
54+
const meta = get(this.appMeta);
55+
return meta?.iconcolor;
56+
});
4957
this.viewName = jotai.atom((get) => {
5058
const meta = get(this.appMeta);
5159
return meta?.title || "WaveApp";
@@ -58,6 +66,8 @@ class TsunamiViewModel extends WebViewModel {
5866
const meta: AppMeta = {
5967
title: rtInfo["tsunami:title"],
6068
shortdesc: rtInfo["tsunami:shortdesc"],
69+
icon: rtInfo["tsunami:icon"],
70+
iconcolor: rtInfo["tsunami:iconcolor"],
6171
};
6272
globalStore.set(this.appMeta, meta);
6373
}
@@ -151,15 +161,15 @@ class TsunamiViewModel extends WebViewModel {
151161
async remixInBuilder() {
152162
const blockData = globalStore.get(this.blockAtom);
153163
const appId = blockData?.meta?.["tsunami:appid"];
154-
164+
155165
if (!appId || !appId.startsWith("local/")) {
156166
return;
157167
}
158-
168+
159169
try {
160170
const result = await RpcApi.MakeDraftFromLocalCommand(TabRpcClient, { localappid: appId });
161171
const draftAppId = result.draftappid;
162-
172+
163173
getApi().openBuilder(draftAppId);
164174
} catch (err) {
165175
console.error("Failed to create draft from local app:", err);
@@ -192,7 +202,7 @@ class TsunamiViewModel extends WebViewModel {
192202
const blockData = globalStore.get(this.blockAtom);
193203
const appId = blockData?.meta?.["tsunami:appid"];
194204
const showRemixOption = appId && appId.startsWith("local/");
195-
205+
196206
// Add tsunami-specific menu items at the beginning
197207
const tsunamiItems: ContextMenuItem[] = [
198208
{
@@ -211,7 +221,7 @@ class TsunamiViewModel extends WebViewModel {
211221
type: "separator",
212222
},
213223
];
214-
224+
215225
if (showRemixOption) {
216226
tsunamiItems.push(
217227
{

frontend/types/custom.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ declare global {
294294
// Icon representing the view, can be a string or an IconButton declaration.
295295
viewIcon?: jotai.Atom<string | IconButtonDecl>;
296296

297+
// Optional color for the view icon.
298+
viewIconColor?: jotai.Atom<string>;
299+
297300
// Display name for the view, used in UI headers.
298301
viewName?: jotai.Atom<string>;
299302

frontend/types/gotypes.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ declare global {
7474
type AppMeta = {
7575
title: string;
7676
shortdesc: string;
77+
icon: string;
78+
iconcolor: string;
7779
};
7880

7981
// waveobj.Block
@@ -913,6 +915,8 @@ declare global {
913915
type ObjRTInfo = {
914916
"tsunami:title"?: string;
915917
"tsunami:shortdesc"?: string;
918+
"tsunami:icon"?: string;
919+
"tsunami:iconcolor"?: string;
916920
"tsunami:schemas"?: any;
917921
"shell:hascurcwd"?: boolean;
918922
"shell:state"?: string;

pkg/blockcontroller/tsunamicontroller.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ func (c *TsunamiController) Start(ctx context.Context, blockMeta waveobj.MetaMap
168168
if manifest.AppMeta.ShortDesc != "" {
169169
rtInfo["tsunami:shortdesc"] = manifest.AppMeta.ShortDesc
170170
}
171+
if manifest.AppMeta.Icon != "" {
172+
rtInfo["tsunami:icon"] = manifest.AppMeta.Icon
173+
}
174+
if manifest.AppMeta.IconColor != "" {
175+
rtInfo["tsunami:iconcolor"] = manifest.AppMeta.IconColor
176+
}
171177
if len(rtInfo) > 0 {
172178
wstore.SetRTInfo(blockRef, rtInfo)
173179
wps.Broker.Publish(wps.WaveEvent{

pkg/waveobj/objrtinfo.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package waveobj
66
type ObjRTInfo struct {
77
TsunamiTitle string `json:"tsunami:title,omitempty"`
88
TsunamiShortDesc string `json:"tsunami:shortdesc,omitempty"`
9+
TsunamiIcon string `json:"tsunami:icon,omitempty"`
10+
TsunamiIconColor string `json:"tsunami:iconcolor,omitempty"`
911
TsunamiSchemas any `json:"tsunami:schemas,omitempty"`
1012

1113
ShellHasCurCwd bool `json:"shell:hascurcwd,omitempty"`
@@ -22,7 +24,7 @@ type ObjRTInfo struct {
2224
BuilderAppId string `json:"builder:appid,omitempty"`
2325
BuilderEnv map[string]string `json:"builder:env,omitempty"`
2426

25-
WaveAIChatId string `json:"waveai:chatid,omitempty"`
26-
WaveAIThinkingMode string `json:"waveai:thinkingmode,omitempty"`
27-
WaveAIMaxOutputTokens int `json:"waveai:maxoutputtokens,omitempty"`
27+
WaveAIChatId string `json:"waveai:chatid,omitempty"`
28+
WaveAIThinkingMode string `json:"waveai:thinkingmode,omitempty"`
29+
WaveAIMaxOutputTokens int `json:"waveai:maxoutputtokens,omitempty"`
2830
}

pkg/wshrpc/wshrpctypes.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,8 @@ type RestartBuilderAndWaitResult struct {
10541054
type AppMeta struct {
10551055
Title string `json:"title"`
10561056
ShortDesc string `json:"shortdesc"`
1057+
Icon string `json:"icon"`
1058+
IconColor string `json:"iconcolor"`
10571059
}
10581060

10591061
type SecretMeta struct {

tsunami/engine/clientimpl.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ var defaultClient = makeClient()
4343
type AppMeta struct {
4444
Title string `json:"title"`
4545
ShortDesc string `json:"shortdesc"`
46+
Icon string `json:"icon"` // for waveapps, the icon to use (fontawesome names)
47+
IconColor string `json:"iconcolor"` // for waveapps, the icon color to use (HTML color -- name, hex, rgb)
4648
}
4749

4850
type SecretMeta struct {
@@ -51,10 +53,10 @@ type SecretMeta struct {
5153
}
5254

5355
type AppManifest struct {
54-
AppMeta AppMeta `json:"appmeta"`
55-
ConfigSchema map[string]any `json:"configschema"`
56-
DataSchema map[string]any `json:"dataschema"`
57-
Secrets map[string]SecretMeta `json:"secrets"`
56+
AppMeta AppMeta `json:"appmeta"`
57+
ConfigSchema map[string]any `json:"configschema"`
58+
DataSchema map[string]any `json:"dataschema"`
59+
Secrets map[string]SecretMeta `json:"secrets"`
5860
}
5961

6062
type ClientImpl struct {
@@ -497,7 +499,7 @@ func (c *ClientImpl) GetAppManifest() AppManifest {
497499
configSchema := GenerateConfigSchema(c.Root)
498500
dataSchema := GenerateDataSchema(c.Root)
499501
secrets := c.GetSecrets()
500-
502+
501503
return AppManifest{
502504
AppMeta: appMeta,
503505
ConfigSchema: configSchema,

0 commit comments

Comments
 (0)