Skip to content

Commit 15bf744

Browse files
authored
Added button for hiding debug/dev tools, made debug info ignore cursor events (#484)
1 parent 25a23a6 commit 15bf744

File tree

7 files changed

+108
-48
lines changed

7 files changed

+108
-48
lines changed

frontend/src/App.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { DrawerContent, GuiState } from "@framework/GuiMessageBroker";
55
import { LayoutElement, Workbench } from "@framework/Workbench";
66
import { NavBar } from "@framework/internal/components/NavBar";
77
import { SettingsContentPanels } from "@framework/internal/components/SettingsContentPanels";
8+
import { ToggleDevToolsButton } from "@framework/internal/components/ToggleDevToolsButton";
89
import { AuthState, useAuthProvider } from "@framework/internal/providers/AuthProvider";
910
import { Button } from "@lib/components/Button";
1011
import { WebvizSpinner } from "@lib/components/WebvizSpinner";
@@ -136,6 +137,7 @@ function App() {
136137
<NavBar workbench={workbench.current} />
137138
<SettingsContentPanels workbench={workbench.current} />
138139
</div>
140+
<ToggleDevToolsButton guiMessageBroker={workbench.current.getGuiMessageBroker()} />
139141
</>
140142
);
141143
}

frontend/src/framework/GuiMessageBroker.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from "react";
22

3+
import { isDevMode } from "@lib/utils/devMode";
34
import { Point } from "@lib/utils/geometry";
45

56
import { GlobalCursor } from "./internal/GlobalCursor";
@@ -17,6 +18,7 @@ export enum GuiState {
1718
SettingsPanelWidthInPercent = "settingsPanelWidthInPercent",
1819
ActiveModuleInstanceId = "activeModuleInstanceId",
1920
DataChannelConnectionLayerVisible = "dataChannelConnectionLayerVisible",
21+
DevToolsVisible = "devToolsVisible",
2022
}
2123

2224
export enum GuiEvent {
@@ -70,14 +72,17 @@ type GuiStateValueTypes = {
7072
[GuiState.SettingsPanelWidthInPercent]: number;
7173
[GuiState.ActiveModuleInstanceId]: string;
7274
[GuiState.DataChannelConnectionLayerVisible]: boolean;
75+
[GuiState.DevToolsVisible]: boolean;
7376
};
7477

7578
const defaultStates: Map<GuiState, any> = new Map();
7679
defaultStates.set(GuiState.DrawerContent, DrawerContent.ModuleSettings);
7780
defaultStates.set(GuiState.SettingsPanelWidthInPercent, 30);
7881
defaultStates.set(GuiState.ActiveModuleInstanceId, "");
82+
defaultStates.set(GuiState.DataChannelConnectionLayerVisible, false);
83+
defaultStates.set(GuiState.DevToolsVisible, isDevMode());
7984

80-
const persistentStates: GuiState[] = [GuiState.SettingsPanelWidthInPercent];
85+
const persistentStates: GuiState[] = [GuiState.SettingsPanelWidthInPercent, GuiState.DevToolsVisible];
8186

8287
export class GuiMessageBroker {
8388
private _eventListeners: Map<GuiEvent, Set<(event: any) => void>>;

frontend/src/framework/internal/components/Content/private-components/ViewWrapper/private-components/viewContent.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ export const ViewContent = React.memo((props: ViewContentProps) => {
121121
id={`${props.moduleInstance.getId()}-view`}
122122
statusController={props.moduleInstance.getStatusController()}
123123
source={StatusSource.View}
124+
guiMessageBroker={props.workbench.getGuiMessageBroker()}
124125
>
125126
<View
126127
moduleContext={props.moduleInstance.getContext()}

frontend/src/framework/internal/components/DebugProfiler/debugProfiler.tsx

+52-47
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from "react";
22

3+
import { GuiMessageBroker, GuiState, useGuiValue } from "@framework/GuiMessageBroker";
34
import { StatusSource } from "@framework/ModuleInstanceStatusController";
45
import {
56
ModuleInstanceStatusControllerInternal,
@@ -43,6 +44,7 @@ export type DebugProfilerProps = {
4344
children: React.ReactNode;
4445
statusController: ModuleInstanceStatusControllerInternal;
4546
source: StatusSource;
47+
guiMessageBroker: GuiMessageBroker;
4648
};
4749

4850
type RenderInfo = {
@@ -69,6 +71,7 @@ export const DebugProfiler: React.FC<DebugProfilerProps> = (props) => {
6971
props.statusController,
7072
props.source === StatusSource.View ? "viewDebugMessage" : "settingsDebugMessage"
7173
);
74+
const debugInfoVisible = useGuiValue(props.guiMessageBroker, GuiState.DevToolsVisible);
7275

7376
const handleRender = React.useCallback(
7477
(
@@ -103,55 +106,57 @@ export const DebugProfiler: React.FC<DebugProfilerProps> = (props) => {
103106
<DebugProfilerWrapper id={props.id} onRender={handleRender}>
104107
{props.children}
105108
</DebugProfilerWrapper>
106-
<div className="absolute bottom-1 w-full flex gap-2 flex-wrap">
107-
{renderInfo && (
108-
<>
109-
{reportedRenderCount !== null && (
110-
<DebugProfilerRenderInfo title="Reported component render count">
111-
Component RC: {reportedRenderCount}
109+
{debugInfoVisible && (
110+
<div className="absolute bottom-1 w-full flex gap-2 flex-wrap pointer-events-none">
111+
{renderInfo && (
112+
<>
113+
{reportedRenderCount !== null && (
114+
<DebugProfilerRenderInfo title="Reported component render count">
115+
Component RC: {reportedRenderCount}
116+
</DebugProfilerRenderInfo>
117+
)}
118+
{customDebugMessage && (
119+
<DebugProfilerRenderInfo title="Custom debug message">
120+
Message: {customDebugMessage}
121+
</DebugProfilerRenderInfo>
122+
)}
123+
<DebugProfilerRenderInfo title="Tree render count">
124+
Tree RC: {renderInfo.renderCount}
112125
</DebugProfilerRenderInfo>
113-
)}
114-
{customDebugMessage && (
115-
<DebugProfilerRenderInfo title="Custom debug message">
116-
Message: {customDebugMessage}
126+
<DebugProfilerRenderInfo title="Phase">P: {renderInfo.phase}</DebugProfilerRenderInfo>
127+
<DebugProfilerRenderInfo
128+
title={
129+
"Actual duration: The number of milliseconds spent rendering the module and its descendants for the current update. " +
130+
"This indicates how well the subtree makes use of memoization (e.g. memo and useMemo). " +
131+
"Ideally this value should decrease significantly after the initial mount as many of the descendants will only " +
132+
"need to re-render if their specific props change."
133+
}
134+
>
135+
AD: {renderInfo.actualDuration.toFixed(2)}ms
117136
</DebugProfilerRenderInfo>
118-
)}
119-
<DebugProfilerRenderInfo title="Tree render count">
120-
Tree RC: {renderInfo.renderCount}
121-
</DebugProfilerRenderInfo>
122-
<DebugProfilerRenderInfo title="Phase">P: {renderInfo.phase}</DebugProfilerRenderInfo>
123-
<DebugProfilerRenderInfo
124-
title={
125-
"Actual duration: The number of milliseconds spent rendering the module and its descendants for the current update. " +
126-
"This indicates how well the subtree makes use of memoization (e.g. memo and useMemo). " +
127-
"Ideally this value should decrease significantly after the initial mount as many of the descendants will only " +
128-
"need to re-render if their specific props change."
129-
}
130-
>
131-
AD: {renderInfo.actualDuration.toFixed(2)}ms
132-
</DebugProfilerRenderInfo>
133-
<DebugProfilerRenderInfo
134-
title={
135-
"Base Duration: The number of milliseconds estimating how much time it would take to re-render the entire module subtree without any optimizations. " +
136-
"It is calculated by summing up the most recent render durations of each component in the tree. " +
137-
"This value estimates a worst-case cost of rendering (e.g. the initial mount or a tree with no memoization). " +
138-
"Compare actualDuration against it to see if memoization is working."
139-
}
140-
>
141-
BD: {renderInfo.baseDuration.toFixed(2)}ms
142-
</DebugProfilerRenderInfo>
143-
<DebugProfilerRenderInfo title="The number of milliseconds of the fastest render duration.">
144-
MIN: {renderInfo.minTime.toFixed(2)}ms
145-
</DebugProfilerRenderInfo>
146-
<DebugProfilerRenderInfo title="The number of milliseconds of the slowest render duration.">
147-
MAX: {renderInfo.maxTime.toFixed(2)}ms
148-
</DebugProfilerRenderInfo>
149-
<DebugProfilerRenderInfo title="The number of milliseconds of the average render duration.">
150-
AVG: {renderInfo.avgTime.toFixed(2)}ms
151-
</DebugProfilerRenderInfo>
152-
</>
153-
)}
154-
</div>
137+
<DebugProfilerRenderInfo
138+
title={
139+
"Base Duration: The number of milliseconds estimating how much time it would take to re-render the entire module subtree without any optimizations. " +
140+
"It is calculated by summing up the most recent render durations of each component in the tree. " +
141+
"This value estimates a worst-case cost of rendering (e.g. the initial mount or a tree with no memoization). " +
142+
"Compare actualDuration against it to see if memoization is working."
143+
}
144+
>
145+
BD: {renderInfo.baseDuration.toFixed(2)}ms
146+
</DebugProfilerRenderInfo>
147+
<DebugProfilerRenderInfo title="The number of milliseconds of the fastest render duration.">
148+
MIN: {renderInfo.minTime.toFixed(2)}ms
149+
</DebugProfilerRenderInfo>
150+
<DebugProfilerRenderInfo title="The number of milliseconds of the slowest render duration.">
151+
MAX: {renderInfo.maxTime.toFixed(2)}ms
152+
</DebugProfilerRenderInfo>
153+
<DebugProfilerRenderInfo title="The number of milliseconds of the average render duration.">
154+
AVG: {renderInfo.avgTime.toFixed(2)}ms
155+
</DebugProfilerRenderInfo>
156+
</>
157+
)}
158+
</div>
159+
)}
155160
</>
156161
);
157162
}

frontend/src/framework/internal/components/Settings/private-components/setting.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ export const Setting: React.FC<SettingProps> = (props) => {
9696
id={`${props.moduleInstance.getId()}-settings`}
9797
source={StatusSource.Settings}
9898
statusController={props.moduleInstance.getStatusController()}
99+
guiMessageBroker={props.workbench.getGuiMessageBroker()}
99100
>
100101
<Settings
101102
moduleContext={props.moduleInstance.getContext()}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { ToggleDevToolsButton } from "./toggleDevToolsButton";
2+
export type { ToggleDevToolsButtonProps } from "./toggleDevToolsButton";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React from "react";
2+
3+
import { GuiMessageBroker, GuiState, useGuiState } from "@framework/GuiMessageBroker";
4+
import { isDevMode } from "@lib/utils/devMode";
5+
import { resolveClassNames } from "@lib/utils/resolveClassNames";
6+
import { BugReport } from "@mui/icons-material";
7+
8+
export type ToggleDevToolsButtonProps = {
9+
guiMessageBroker: GuiMessageBroker;
10+
};
11+
12+
export const ToggleDevToolsButton: React.FC<ToggleDevToolsButtonProps> = (props) => {
13+
const [devToolsVisible, setDevToolsVisible] = useGuiState(props.guiMessageBroker, GuiState.DevToolsVisible);
14+
15+
React.useEffect(() => {
16+
if (!devToolsVisible) {
17+
document.querySelector(".tsqd-parent-container")?.classList.add("hidden");
18+
} else {
19+
document.querySelector(".tsqd-parent-container")?.classList.remove("hidden");
20+
}
21+
}, [devToolsVisible]);
22+
23+
if (!isDevMode()) {
24+
return null;
25+
}
26+
27+
return (
28+
<div
29+
className={resolveClassNames(
30+
"absolute bottom-2 shadow left-3 z-50 m-2 p-2 rounded-full flex items-center justify-center w-8 h-8 bg-gray-800 text-white text-m cursor-pointer",
31+
{
32+
"bg-green-700 hover: hover:bg-green-600": devToolsVisible,
33+
"bg-gray-800 hover:bg-gray-700": !devToolsVisible,
34+
}
35+
)}
36+
title={devToolsVisible ? "Hide dev tools" : "Show dev tools"}
37+
onClick={() => {
38+
setDevToolsVisible(!devToolsVisible);
39+
}}
40+
>
41+
<BugReport fontSize="inherit" />
42+
</div>
43+
);
44+
};

0 commit comments

Comments
 (0)