Skip to content

Commit 4edcf09

Browse files
committed
feat: add option to close dashboard when starting project
1 parent 30db93b commit 4edcf09

File tree

5 files changed

+123
-40
lines changed

5 files changed

+123
-40
lines changed

editor/src/dashboard/create.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { EditorProjectPackageManager, IEditorProject, EditorProjectTemplate } fr
2525

2626
export interface IDashboardCreateProjectDialogProps {
2727
isOpened: boolean;
28+
closeDashboardOnProjectOpen: boolean;
2829
onClose: () => void;
2930
}
3031

@@ -101,7 +102,7 @@ export function DashboardCreateProjectDialog(props: IDashboardCreateProjectDialo
101102
});
102103

103104
if (result) {
104-
ipcRenderer.send("dashboard:open-project", projectAbsolutePath);
105+
ipcRenderer.send("dashboard:open-project", projectAbsolutePath, props.closeDashboardOnProjectOpen);
105106
}
106107
} catch (e) {
107108
showAlert("An unexpected error occured", e.message);

editor/src/dashboard/item.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { DashboardProgressComponent } from "./progress";
2727
export interface IDashboardProjectItemProps {
2828
isOpened: boolean;
2929
project: ProjectType;
30-
30+
closeDashboardOnProjectOpen: boolean;
3131
onRemove: () => void;
3232
}
3333

@@ -127,6 +127,10 @@ export function DashboardProjectItem(props: IDashboardProjectItemProps) {
127127
setPlayingAddress("");
128128
}
129129

130+
function handleLoadProject() {
131+
ipcRenderer.send("dashboard:open-project", props.project.absolutePath, props.closeDashboardOnProjectOpen);
132+
}
133+
130134
function handleOpenInVisualStudioCode() {
131135
execNodePty(`code "${dirname(props.project.absolutePath)}"`);
132136
}
@@ -135,7 +139,7 @@ export function DashboardProjectItem(props: IDashboardProjectItemProps) {
135139
<ContextMenu onOpenChange={(o) => setContextMenuOpen(o)}>
136140
<ContextMenuTrigger>
137141
<div
138-
onDoubleClick={() => ipcRenderer.send("dashboard:open-project", props.project.absolutePath)}
142+
onDoubleClick={handleLoadProject}
139143
className={`
140144
group
141145
flex flex-col w-full rounded-lg cursor-pointer select-none
@@ -169,7 +173,7 @@ export function DashboardProjectItem(props: IDashboardProjectItemProps) {
169173
</Button>
170174
</DropdownMenuTrigger>
171175
<DropdownMenuContent>
172-
<DropdownMenuItem onClick={() => ipcRenderer.send("dashboard:open-project", props.project.absolutePath)}>Open</DropdownMenuItem>
176+
<DropdownMenuItem onClick={handleLoadProject}>Open</DropdownMenuItem>
173177
<DropdownMenuItem className="flex items-center gap-2" onClick={() => ipcRenderer.send("editor:show-item", props.project.absolutePath)}>
174178
{`Show in ${isDarwin() ? "Finder" : "Explorer"}`}
175179
</DropdownMenuItem>
@@ -214,7 +218,7 @@ export function DashboardProjectItem(props: IDashboardProjectItemProps) {
214218
</div>
215219
</ContextMenuTrigger>
216220
<ContextMenuContent>
217-
<ContextMenuItem onClick={() => ipcRenderer.send("dashboard:open-project", props.project.absolutePath)}>Open</ContextMenuItem>
221+
<ContextMenuItem onClick={handleLoadProject}>Open</ContextMenuItem>
218222
<ContextMenuItem className="flex items-center gap-2" onClick={() => ipcRenderer.send("editor:show-item", props.project.absolutePath)}>
219223
{`Show in ${isDarwin() ? "Finder" : "Explorer"}`}
220224
</ContextMenuItem>

editor/src/dashboard/main.tsx

Lines changed: 76 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,20 @@ import { wait } from "../tools/tools";
1515
import { openSingleFileDialog } from "../tools/dialog";
1616
import { ProjectType, projectsKey } from "../tools/project";
1717
import { checkNodeJSAvailable, nodeJSAvailable } from "../tools/process";
18-
import { tryAddProjectToLocalStorage, tryGetProjectsFromLocalStorage } from "../tools/local-storage";
18+
import {
19+
tryAddProjectToLocalStorage,
20+
tryGetCloseDashboardOnProjectOpenFromLocalStorage,
21+
tryGetProjectsFromLocalStorage,
22+
trySetCloseDashboardOnProjectOpenInLocalStorage,
23+
} from "../tools/local-storage";
1924

2025
import { DashboardProjectItem } from "./item";
2126
import { DashboardCreateProjectDialog } from "./create";
2227
import { DashboardWindowControls } from "./window-controls";
2328

2429
import packageJson from "../../package.json";
30+
import { Switch } from "../ui/shadcn/ui/switch";
31+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/shadcn/ui/tooltip";
2532

2633
export function createDashboard(): void {
2734
const theme = localStorage.getItem("editor-theme") ?? "dark";
@@ -48,6 +55,7 @@ export interface IDashboardState {
4855
openedProjects: string[];
4956

5057
createProject: boolean;
58+
closeDashboardOnProjectOpen: boolean;
5159
}
5260

5361
export class Dashboard extends Component<IDashboardProps, IDashboardState> {
@@ -59,48 +67,61 @@ export class Dashboard extends Component<IDashboardProps, IDashboardState> {
5967
projects: tryGetProjectsFromLocalStorage(),
6068

6169
createProject: false,
70+
closeDashboardOnProjectOpen: tryGetCloseDashboardOnProjectOpenFromLocalStorage(),
6271
};
6372

6473
webFrame.setZoomFactor(0.8);
6574
}
6675

6776
public render(): ReactNode {
68-
return (
69-
<>
70-
<div className="flex flex-col gap-4 w-screen h-screen p-5 select-none overflow-x-hidden pt-10">
71-
<DashboardWindowControls />
72-
73-
<Fade delay={0}>
74-
<div className="flex justify-between items-end w-full mt-1">
75-
<div className="text-5xl font-semibold">Dashboard</div>
77+
const handleKeepDashboardChanged = (checked: boolean): void => {
78+
const shouldClose = !checked;
7679

77-
<div className="flex flex-col items-end gap-2">
78-
<img alt="" src="assets/babylonjs_icon.png" className="w-[48px] object-contain" />
79-
<div className="text-xs">Babylon.js Editor v{packageJson.version}</div>
80-
</div>
81-
</div>
82-
</Fade>
80+
this.setState({
81+
closeDashboardOnProjectOpen: shouldClose,
82+
});
8383

84-
<Fade delay={250}>
85-
<Separator />
86-
</Fade>
84+
trySetCloseDashboardOnProjectOpenInLocalStorage(shouldClose);
85+
};
8786

88-
<Fade delay={500}>
89-
<div className="flex justify-between items-center">
90-
<div className="text-3xl font-semibold">Projects</div>
91-
92-
<div className="flex gap-2">
93-
<Button variant="secondary" className="font-semibold" onClick={() => this._handleImportProject()}>
94-
Import project
95-
</Button>
96-
<Button className="font-semibold" onClick={() => this.setState({ createProject: true })}>
97-
Create project
98-
</Button>
87+
return (
88+
<>
89+
<div className="flex flex-col gap-4 w-screen h-screen p-5 select-none pt-10">
90+
<div className="flex flex-col gap-4 flex-[0_0_auto]">
91+
<DashboardWindowControls />
92+
93+
<Fade delay={0}>
94+
<div className="flex justify-between items-end w-full mt-1">
95+
<div className="text-5xl font-semibold">Dashboard</div>
96+
97+
<div className="flex flex-col items-end gap-2">
98+
<img alt="" src="assets/babylonjs_icon.png" className="w-[48px] object-contain" />
99+
<div className="text-xs">Babylon.js Editor v{packageJson.version}</div>
100+
</div>
99101
</div>
100-
</div>
101-
</Fade>
102+
</Fade>
103+
104+
<Fade delay={250}>
105+
<Separator />
106+
</Fade>
107+
108+
<Fade delay={500}>
109+
<div className="flex justify-between items-center">
110+
<div className="text-3xl font-semibold">Projects</div>
111+
112+
<div className="flex gap-2">
113+
<Button variant="secondary" className="font-semibold" onClick={() => this._handleImportProject()}>
114+
Import project
115+
</Button>
116+
<Button className="font-semibold" onClick={() => this.setState({ createProject: true })}>
117+
Create project
118+
</Button>
119+
</div>
120+
</div>
121+
</Fade>
122+
</div>
102123

103-
<Fade delay={750}>
124+
<Fade delay={750} className="flex-auto overflow-y-auto p-2">
104125
{!this.state.projects.length && <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">No project found.</div>}
105126

106127
{this.state.projects.length && (
@@ -110,16 +131,39 @@ export class Dashboard extends Component<IDashboardProps, IDashboardState> {
110131
project={project}
111132
key={project.absolutePath}
112133
isOpened={this.state.openedProjects.includes(project.absolutePath)}
134+
closeDashboardOnProjectOpen={this.state.closeDashboardOnProjectOpen}
113135
onRemove={() => this._tryRemoveProjectFromLocalStorage(project)}
114136
/>
115137
))}
116138
</div>
117139
)}
118140
</Fade>
141+
142+
<Fade delay={1000} className="flex-[0_0_auto]">
143+
<div>
144+
<Separator />
145+
<div className="flex justify-end pt-3 pb-1">
146+
<TooltipProvider>
147+
<Tooltip>
148+
<TooltipTrigger className="flex items-center gap-2 cursor-auto">
149+
<Switch checked={!this.state.closeDashboardOnProjectOpen} onCheckedChange={handleKeepDashboardChanged} />
150+
<span>Keep dashboard open</span>
151+
</TooltipTrigger>
152+
<TooltipContent align="end" side="top" collisionPadding={8}>
153+
If enabled, the dashboard will stay open when a project starts.
154+
<br />
155+
If disabled, the dashboard will close when a project starts and reopen after the project is closed.
156+
</TooltipContent>
157+
</Tooltip>
158+
</TooltipProvider>
159+
</div>
160+
</div>
161+
</Fade>
119162
</div>
120163

121164
<DashboardCreateProjectDialog
122165
isOpened={this.state.createProject}
166+
closeDashboardOnProjectOpen={this.state.closeDashboardOnProjectOpen}
123167
onClose={() => {
124168
this.setState({
125169
createProject: false,

editor/src/index.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,20 @@ async function openDashboard(): Promise<void> {
107107
dashboardWindow.focus();
108108
}
109109

110-
ipcMain.on("dashboard:open-project", (_, file) => {
110+
function closeDashboard(): void {
111+
if (dashboardWindow) {
112+
dashboardWindow.close();
113+
dashboardWindow = null;
114+
}
115+
}
116+
117+
ipcMain.on("dashboard:open-project", (_, file: string, shouldCloseDashboard?: boolean) => {
111118
openProject(file);
112119
dashboardWindow?.minimize();
120+
121+
if (shouldCloseDashboard) {
122+
closeDashboard();
123+
}
113124
});
114125

115126
ipcMain.on("dashboard:update-projects", () => {
@@ -138,7 +149,7 @@ async function openProject(filePath: string): Promise<void> {
138149
notifyWindows("dashboard:opened-projects", openedProjects);
139150

140151
if (openedProjects.length === 0) {
141-
dashboardWindow?.restore();
152+
openDashboard();
142153
}
143154
});
144155

editor/src/tools/local-storage.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export function tryGetExperimentalFeaturesEnabledFromLocalStorage(): boolean {
5454
}
5555

5656
/**
57-
* Sets wether or not experimental features are enabled in the local storage.
57+
* Sets whether or not experimental features are enabled in the local storage.
5858
* @param enabled defines wether or not experimental features are enabled.
5959
*/
6060
export function trySetExperimentalFeaturesEnabledInLocalStorage(enabled: boolean): void {
@@ -64,3 +64,26 @@ export function trySetExperimentalFeaturesEnabledInLocalStorage(enabled: boolean
6464
// Catch silently.
6565
}
6666
}
67+
68+
/**
69+
* Returns wether or not the dashboard should be closed when a project is opened.
70+
*/
71+
export function tryGetCloseDashboardOnProjectOpenFromLocalStorage(): boolean {
72+
try {
73+
return localStorage.getItem("babylonjs-editor-close-dashboard-on-project-open") === "true";
74+
} catch (e) {
75+
return false;
76+
}
77+
}
78+
79+
/**
80+
* Sets whether or not the dashboard should be closed when a project is opened.
81+
* @param enabled defines whether or not the dashboard should be closed when a project is opened.
82+
*/
83+
export function trySetCloseDashboardOnProjectOpenInLocalStorage(enabled: boolean): void {
84+
try {
85+
localStorage.setItem("babylonjs-editor-close-dashboard-on-project-open", JSON.stringify(enabled));
86+
} catch (e) {
87+
// Catch silently.
88+
}
89+
}

0 commit comments

Comments
 (0)