22// SPDX-License-Identifier: Apache-2.0
33
44import WorkspaceSVG from "@/app/asset/workspace.svg" ;
5- import { Tooltip } from "@/app/element/tooltip" ;
65import { IconButton } from "@/app/element/iconbutton" ;
6+ import { Tooltip } from "@/app/element/tooltip" ;
7+ import { loadBadges , LoadBadgesEnv } from "@/app/store/badge" ;
78import { getAtoms } from "@/app/store/global-atoms" ;
8- import { TabV } from "@/app/tab/tab" ;
9+ import { Tab } from "@/app/tab/tab" ;
910import { ConfigErrorIcon , WaveAIButton } from "@/app/tab/tabbar" ;
1011import { TabBarEnv } from "@/app/tab/tabbarenv" ;
1112import { UpdateStatusBanner } from "@/app/tab/updatebanner" ;
12- import { useWaveEnv } from "@/app/waveenv/waveenv" ;
13+ import { useWaveEnv , WaveEnvContext } from "@/app/waveenv/waveenv" ;
14+ import { applyMockEnvOverrides } from "@/preview/mock/mockwaveenv" ;
1315import { useAtom } from "jotai" ;
1416import { CSSProperties , useEffect , useMemo , useRef , useState } from "react" ;
1517
@@ -20,26 +22,61 @@ type PreviewTabEntry = {
2022 flagColor ?: string | null ;
2123} ;
2224
25+ function badgeBlockId ( tabId : string , badgeId : string ) : string {
26+ return `${ tabId } -badge-${ badgeId } ` ;
27+ }
28+
29+ function makeTabWaveObj ( tab : PreviewTabEntry ) : Tab {
30+ const blockids = ( tab . badges ?? [ ] ) . map ( ( b ) => badgeBlockId ( tab . tabId , b . badgeid ) ) ;
31+ return {
32+ otype : "tab" ,
33+ oid : tab . tabId ,
34+ version : 1 ,
35+ name : tab . tabName ,
36+ blockids,
37+ meta : tab . flagColor ? { "tab:flagcolor" : tab . flagColor } : { } ,
38+ } as Tab ;
39+ }
40+
41+ function makeMockBadgeEvents ( ) : BadgeEvent [ ] {
42+ const events : BadgeEvent [ ] = [ ] ;
43+ for ( const tab of InitialTabs ) {
44+ for ( const badge of tab . badges ?? [ ] ) {
45+ events . push ( { oref : `block:${ badgeBlockId ( tab . tabId , badge . badgeid ) } ` , badge } ) ;
46+ }
47+ }
48+ return events ;
49+ }
50+
2351const TabDefaultWidth = 130 ;
2452const TabMinWidth = 100 ;
2553const TabHeight = 26 ;
2654const MockWorkspaceSwitcherWidth = 42 ;
2755const MockAddTabButtonWidth = 44 ;
2856const MockConfigErrors : ConfigError [ ] = [
29- { file : "~/.waveterm/config.json" , err : " unknown preset \ "bg@aurora\"" } ,
57+ { file : "~/.waveterm/config.json" , err : ' unknown preset "bg@aurora"' } ,
3058 { file : "~/.waveterm/settings.json" , err : "invalid color for tab theme" } ,
3159] ;
3260const InitialTabs : PreviewTabEntry [ ] = [
3361 { tabId : "preview-tab-1" , tabName : "Terminal" } ,
3462 {
3563 tabId : "preview-tab-2" ,
3664 tabName : "Build Logs" ,
37- badges : [ { badgeid : "01958000-0000-7000-0000-000000000001" , icon : "triangle-exclamation" , color : "#f59e0b" , priority : 2 } ] ,
65+ badges : [
66+ {
67+ badgeid : "01958000-0000-7000-0000-000000000001" ,
68+ icon : "triangle-exclamation" ,
69+ color : "#f59e0b" ,
70+ priority : 2 ,
71+ } ,
72+ ] ,
3873 } ,
3974 {
4075 tabId : "preview-tab-3" ,
4176 tabName : "Deploy" ,
42- badges : [ { badgeid : "01958000-0000-7000-0000-000000000002" , icon : "circle-check" , color : "#4ade80" , priority : 3 } ] ,
77+ badges : [
78+ { badgeid : "01958000-0000-7000-0000-000000000002" , icon : "circle-check" , color : "#4ade80" , priority : 3 } ,
79+ ] ,
4380 flagColor : "#429dff" ,
4481 } ,
4582 {
@@ -74,7 +111,13 @@ function getWindowDragWidths(platform: NodeJS.Platform, isFullScreen: boolean, z
74111
75112function MockWorkspaceSwitcher ( { divRef } : { divRef : React . RefObject < HTMLDivElement > } ) {
76113 return (
77- < Tooltip content = "Workspace Switcher" placement = "bottom" hideOnClick divRef = { divRef } divClassName = "flex items-center" >
114+ < Tooltip
115+ content = "Workspace Switcher"
116+ placement = "bottom"
117+ hideOnClick
118+ divRef = { divRef }
119+ divClassName = "flex items-center"
120+ >
78121 < div
79122 className = "mb-1 mr-1 flex h-[22px] w-[28px] items-center justify-center rounded-md bg-hover text-secondary"
80123 style = { { WebkitAppRegion : "no-drag" } as CSSProperties }
@@ -91,14 +134,12 @@ function MockTabStrip({
91134 availableWidth,
92135 onSelectTab,
93136 onCloseTab,
94- onRenameTab,
95137} : {
96138 tabs : PreviewTabEntry [ ] ;
97139 activeTabId : string ;
98140 availableWidth : number ;
99141 onSelectTab : ( tabId : string ) => void ;
100142 onCloseTab : ( tabId : string ) => void ;
101- onRenameTab : ( tabId : string , newName : string ) => void ;
102143} ) {
103144 const tabRefs = useRef < Record < string , HTMLDivElement | null > > ( { } ) ;
104145 const tabWidth = useMemo ( ( ) => {
@@ -128,25 +169,21 @@ function MockTabStrip({
128169 const isActive = tab . tabId === activeTabId ;
129170 const showDivider = index !== 0 && ! isActive && index !== activeIndex + 1 ;
130171 return (
131- < TabV
172+ < Tab
132173 key = { tab . tabId }
133174 ref = { ( el ) => {
134175 tabRefs . current [ tab . tabId ] = el ;
135176 } }
136- tabId = { tab . tabId }
137- tabName = { tab . tabName }
177+ id = { tab . tabId }
138178 active = { isActive }
139179 showDivider = { showDivider }
140180 isDragging = { false }
141181 tabWidth = { tabWidth }
142182 isNew = { false }
143- badges = { tab . badges ?? null }
144- flagColor = { tab . flagColor ?? null }
145- onClick = { ( ) => onSelectTab ( tab . tabId ) }
183+ onSelect = { ( ) => onSelectTab ( tab . tabId ) }
146184 onClose = { ( ) => onCloseTab ( tab . tabId ) }
147185 onDragStart = { ( ) => { } }
148- onContextMenu = { ( ) => { } }
149- onRename = { ( newName ) => onRenameTab ( tab . tabId , newName ) }
186+ onLoaded = { ( ) => { } }
150187 />
151188 ) ;
152189 } ) }
@@ -156,7 +193,26 @@ function MockTabStrip({
156193}
157194
158195export function TabBarPreview ( ) {
196+ const baseEnv = useWaveEnv ( ) ;
197+ const tabEnv = useMemo ( ( ) => {
198+ const mockWaveObjs = Object . fromEntries ( InitialTabs . map ( ( tab ) => [ `tab:${ tab . tabId } ` , makeTabWaveObj ( tab ) ] ) ) ;
199+ return applyMockEnvOverrides ( baseEnv , {
200+ mockWaveObjs,
201+ rpc : {
202+ GetAllBadgesCommand : ( ) => Promise . resolve ( makeMockBadgeEvents ( ) ) ,
203+ } ,
204+ } ) ;
205+ } , [ ] ) ;
206+ return (
207+ < WaveEnvContext . Provider value = { tabEnv } >
208+ < TabBarPreviewInner />
209+ </ WaveEnvContext . Provider >
210+ ) ;
211+ }
212+
213+ function TabBarPreviewInner ( ) {
159214 const env = useWaveEnv < TabBarEnv > ( ) ;
215+ const loadBadgesEnv = useWaveEnv < LoadBadgesEnv > ( ) ;
160216 const [ tabs , setTabs ] = useState < PreviewTabEntry [ ] > ( InitialTabs ) ;
161217 const [ activeTabId , setActiveTabId ] = useState < string > ( InitialTabs [ 1 ] . tabId ) ;
162218 const [ frameWidth , setFrameWidth ] = useState ( 1180 ) ;
@@ -173,6 +229,10 @@ export function TabBarPreview() {
173229 const updateStatusBannerRef = useRef < HTMLButtonElement > ( null ) ;
174230 const configErrorButtonRef = useRef < HTMLElement > ( null ) ;
175231
232+ useEffect ( ( ) => {
233+ loadBadges ( loadBadgesEnv ) ;
234+ } , [ ] ) ;
235+
176236 useEffect ( ( ) => {
177237 setFullConfig ( ( prev ) => ( {
178238 ...( prev ?? ( { } as FullConfigType ) ) ,
@@ -334,11 +394,6 @@ export function TabBarPreview() {
334394 return nextTabs ;
335395 } ) ;
336396 } }
337- onRenameTab = { ( tabId , newName ) => {
338- setTabs ( ( prevTabs ) =>
339- prevTabs . map ( ( tab ) => ( tab . tabId === tabId ? { ...tab , tabName : newName } : tab ) )
340- ) ;
341- } }
342397 />
343398 </ div >
344399 < IconButton
@@ -372,3 +427,4 @@ export function TabBarPreview() {
372427 </ div >
373428 ) ;
374429}
430+ TabBarPreviewInner . displayName = "TabBarPreviewInner" ;
0 commit comments