diff --git a/frontend/app/block/blockframe.tsx b/frontend/app/block/blockframe.tsx index d473433a1..99facd9cb 100644 --- a/frontend/app/block/blockframe.tsx +++ b/frontend/app/block/blockframe.tsx @@ -5,6 +5,7 @@ import { blockViewToIcon, blockViewToName, ConnectionButton, + ControllerStatusIcon, getBlockHeaderIcon, IconButton, Input, @@ -192,6 +193,7 @@ const BlockFrame_Header = ({ ); headerTextElems.unshift(connButtonElem); } + headerTextElems.unshift(); return (
diff --git a/frontend/app/block/blockutil.tsx b/frontend/app/block/blockutil.tsx index 57e31f8a0..26debf54a 100644 --- a/frontend/app/block/blockutil.tsx +++ b/frontend/app/block/blockutil.tsx @@ -2,7 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 import { useLongClick } from "@/app/hook/useLongClick"; -import { getConnStatusAtom } from "@/app/store/global"; +import { getConnStatusAtom, waveEventSubscribe, WOS } from "@/app/store/global"; +import * as services from "@/app/store/services"; +import { makeORef } from "@/app/store/wos"; import * as util from "@/util/util"; import clsx from "clsx"; import * as jotai from "jotai"; @@ -150,6 +152,51 @@ interface ConnectionButtonProps { changeConnModalAtom: jotai.PrimitiveAtom; } +export const ControllerStatusIcon = React.memo(({ blockId }: { blockId: string }) => { + const [blockData] = WOS.useWaveObjectValue(WOS.makeORef("block", blockId)); + const hasController = !util.isBlank(blockData?.meta?.controller); + const [controllerStatus, setControllerStatus] = React.useState(null); + const connection = blockData?.meta?.connection ?? "local"; + const connStatusAtom = getConnStatusAtom(connection); + const connStatus = jotai.useAtomValue(connStatusAtom); + React.useEffect(() => { + if (!hasController) { + return; + } + const initialRTStatus = services.BlockService.GetControllerStatus(blockId); + initialRTStatus.then((rts) => { + setControllerStatus(rts); + }); + const unsubFn = waveEventSubscribe("controllerstatus", makeORef("block", blockId), (event) => { + const cstatus: BlockControllerRuntimeStatus = event.data; + setControllerStatus(cstatus); + }); + return () => { + unsubFn(); + }; + }, [hasController]); + if (!hasController) { + return null; + } + if ( + controllerStatus == null || + (controllerStatus?.status == "running" && controllerStatus?.shellprocstatus == "running") + ) { + return null; + } + if (connStatus?.status != "connected") { + return null; + } + const controllerStatusElem = ( + + ); + return controllerStatusElem; +}); + export const ConnectionButton = React.memo( React.forwardRef( ({ connection, changeConnModalAtom }: ConnectionButtonProps, ref) => { diff --git a/pkg/blockcontroller/blockcontroller.go b/pkg/blockcontroller/blockcontroller.go index 10d61ffe4..1b116ee53 100644 --- a/pkg/blockcontroller/blockcontroller.go +++ b/pkg/blockcontroller/blockcontroller.go @@ -22,6 +22,7 @@ import ( "github.com/wavetermdev/thenextwave/pkg/shellexec" "github.com/wavetermdev/thenextwave/pkg/wavebase" "github.com/wavetermdev/thenextwave/pkg/waveobj" + "github.com/wavetermdev/thenextwave/pkg/wps" "github.com/wavetermdev/thenextwave/pkg/wshrpc" "github.com/wavetermdev/thenextwave/pkg/wshutil" "github.com/wavetermdev/thenextwave/pkg/wstore" @@ -124,12 +125,21 @@ func (bc *BlockController) UpdateControllerAndSendUpdate(updateFn func() bool) { sendUpdate = updateFn() }) if sendUpdate { - log.Printf("sending blockcontroller update %#v\n", bc.GetRuntimeStatus()) + rtStatus := bc.GetRuntimeStatus() + log.Printf("sending blockcontroller update %#v\n", rtStatus) go eventbus.SendEvent(eventbus.WSEventType{ EventType: eventbus.WSEvent_BlockControllerStatus, ORef: waveobj.MakeORef(waveobj.OType_Block, bc.BlockId).String(), - Data: bc.GetRuntimeStatus(), + Data: rtStatus, }) + waveEvent := wshrpc.WaveEvent{ + Event: wshrpc.Event_ControllerStatus, + Scopes: []string{ + waveobj.MakeORef(waveobj.OType_Tab, bc.TabId).String(), + }, + Data: rtStatus, + } + wps.Broker.Publish(waveEvent) } } diff --git a/pkg/wshrpc/wshrpctypes.go b/pkg/wshrpc/wshrpctypes.go index 583cdb25e..a107da5bb 100644 --- a/pkg/wshrpc/wshrpctypes.go +++ b/pkg/wshrpc/wshrpctypes.go @@ -25,9 +25,10 @@ const ( ) const ( - Event_BlockClose = "blockclose" - Event_ConnChange = "connchange" - Event_SysInfo = "sysinfo" + Event_BlockClose = "blockclose" + Event_ConnChange = "connchange" + Event_SysInfo = "sysinfo" + Event_ControllerStatus = "controllerstatus" ) const (