Skip to content

Commit 80c25de

Browse files
Copilotsawka
andauthored
Add Stop, Restart, and Force Rebuild menu items to Tsunami view (#2483)
Adds settings menu items to the Tsunami app view for stopping and restarting the controller, with support for forcing rebuilds that bypass the build cache. ### Changes - **Added three menu items** to `TsunamiViewModel.getSettingsMenuItems()`: - "Stop WaveApp" - stops the running tsunami controller using `ControllerStopCommand` - "Restart WaveApp" - stops the controller, waits 300ms, then resyncs to restart it (uses existing cache if available) - "Restart WaveApp and Force Rebuild" - triggers `ControllerResyncCommand` with `forcerestart: true` (bypasses build cache per line 228 in `tsunamicontroller.go`) - **Refactored controller resync logic** - extracted common code into `doControllerResync()` helper with optional `triggerRestart` parameter to handle both user-initiated restarts and automatic mount sync - **Implemented proper restart behavior** - "Restart WaveApp" now performs a stop → wait → resync sequence to ensure the controller actually restarts instead of just resyncing to the already-running state ### Implementation Note No backend changes required. The existing `CommandControllerResyncData.ForceRestart` flag already controls cache bypass behavior in the tsunami controller's build logic, and `ControllerStopCommand` is used for stopping the controller. Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: sawka <[email protected]>
1 parent 755d978 commit 80c25de

File tree

1 file changed

+64
-11
lines changed

1 file changed

+64
-11
lines changed

frontend/app/view/tsunami/tsunami.tsx

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,26 +72,58 @@ class TsunamiViewModel extends WebViewModel {
7272
}, 300);
7373
}
7474

75-
resyncController() {
75+
private doControllerResync(forceRestart: boolean, logContext: string, triggerRestart: boolean = true) {
76+
if (triggerRestart) {
77+
if (globalStore.get(this.isRestarting)) {
78+
return;
79+
}
80+
this.triggerRestartAtom();
81+
}
7682
const prtn = RpcApi.ControllerResyncCommand(TabRpcClient, {
7783
tabid: globalStore.get(atoms.staticTabId),
7884
blockid: this.blockId,
79-
forcerestart: false,
85+
forcerestart: forceRestart,
8086
});
81-
prtn.catch((e) => console.log("error controller resync", e));
87+
prtn.catch((e) => console.log(`error controller resync (${logContext})`, e));
8288
}
8389

84-
forceRestartController() {
90+
resyncController() {
91+
this.doControllerResync(false, "resync", false);
92+
}
93+
94+
stopController() {
95+
const prtn = RpcApi.ControllerStopCommand(TabRpcClient, this.blockId);
96+
prtn.catch((e) => console.log("error stopping controller", e));
97+
}
98+
99+
async restartController() {
85100
if (globalStore.get(this.isRestarting)) {
86101
return;
87102
}
88103
this.triggerRestartAtom();
89-
const prtn = RpcApi.ControllerResyncCommand(TabRpcClient, {
90-
tabid: globalStore.get(atoms.staticTabId),
91-
blockid: this.blockId,
92-
forcerestart: true,
93-
});
94-
prtn.catch((e) => console.log("error controller resync (force restart)", e));
104+
try {
105+
// Stop the controller first
106+
await RpcApi.ControllerStopCommand(TabRpcClient, this.blockId);
107+
// Wait a bit for the controller to fully stop
108+
await new Promise((resolve) => setTimeout(resolve, 300));
109+
// Then resync to restart it
110+
await RpcApi.ControllerResyncCommand(TabRpcClient, {
111+
tabid: globalStore.get(atoms.staticTabId),
112+
blockid: this.blockId,
113+
forcerestart: false,
114+
});
115+
} catch (e) {
116+
console.log("error restarting controller", e);
117+
}
118+
}
119+
120+
restartAndForceRebuild() {
121+
this.doControllerResync(true, "force rebuild");
122+
}
123+
124+
forceRestartController() {
125+
// Keep this for backward compatibility with the Start button
126+
this.doControllerResync(true, "force restart");
95127
}
96128

97129
setAppMeta(meta: TsunamiAppMeta) {
@@ -125,7 +157,7 @@ class TsunamiViewModel extends WebViewModel {
125157
getSettingsMenuItems(): ContextMenuItem[] {
126158
const items = super.getSettingsMenuItems();
127159
// Filter out homepage and navigation-related menu items for tsunami view
128-
return items.filter((item) => {
160+
const filteredItems = items.filter((item) => {
129161
const label = item.label?.toLowerCase() || "";
130162
return (
131163
!label.includes("homepage") &&
@@ -134,6 +166,27 @@ class TsunamiViewModel extends WebViewModel {
134166
!label.includes("nav")
135167
);
136168
});
169+
170+
// Add tsunami-specific menu items at the beginning
171+
const tsunamiItems: ContextMenuItem[] = [
172+
{
173+
label: "Stop WaveApp",
174+
click: () => this.stopController(),
175+
},
176+
{
177+
label: "Restart WaveApp",
178+
click: () => this.restartController(),
179+
},
180+
{
181+
label: "Restart WaveApp and Force Rebuild",
182+
click: () => this.restartAndForceRebuild(),
183+
},
184+
{
185+
type: "separator",
186+
},
187+
];
188+
189+
return [...tsunamiItems, ...filteredItems];
137190
}
138191
}
139192

0 commit comments

Comments
 (0)