Skip to content

Commit 98aa0bb

Browse files
committed
Add refresh states for explorers
1 parent c1c87ad commit 98aa0bb

File tree

9 files changed

+166
-121
lines changed

9 files changed

+166
-121
lines changed

remote-workspace/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ async function startServers() {
4444
`API server is running at ${isHttps ? "https" : "http"}://${address}:${serverPort}/api-${workspaceId}`,
4545
);
4646

47-
await addTerminalServer(server, workspaceId);
47+
await addTerminalServer(server, "api-" + workspaceId);
4848
console.log(
4949
`Terminal server is running at ${isHttps ? "wss" : "ws"}://${address}:${serverPort}/api-${workspaceId}/terminal/ws`,
5050
);

remote-workspace/src/servers/api-server/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ async function createEndpoints(
4242
res.redirect(url.toString());
4343
});
4444

45-
app.get("/:instanceId/test", (req, res) => {
45+
app.get("/:instanceId/check-health", (req, res) => {
4646
const id = req.params.instanceId;
4747
if (id !== instanceId) {
4848
return res.status(400).send("Invalid instance ID");

web/components/app-loaders/sandbox-app-loader.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ export default function SandboxAppLoader({
178178
getHandlerMap(viewModel),
179179
);
180180
}
181-
}, [viewModel, editorContext?.editorStates, editorContext?.persistSettings]);
181+
}, [viewModel, editorContext?.editorStates, editorContext?.persistSettings, platformApi]);
182182

183183
function getHandlerMap(model: ViewModel) {
184184
const newMap = new Map<IMCMessageTypeEnum, ReceiverHandler>();

web/components/explorer/file-system/fs-explorer.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { IMCContext } from "@/components/providers/imc-provider";
44
import { PlatformEnum } from "@/lib/enums";
55
import { usePlatformApi } from "@/lib/hooks/use-platform-api";
66
import { useTabViewManager } from "@/lib/hooks/use-tab-view-manager";
7+
import { useWorkspace } from "@/lib/hooks/use-workspace";
78
import { getPlatform } from "@/lib/platform-api/platform-checker";
89
import { TreeViewGroupRef } from "@/lib/types";
910
import { addToast, Button, Spinner } from "@heroui/react";
@@ -23,8 +24,9 @@ export default function FileSystemExplorer({
2324
const imcContext = useContext(IMCContext);
2425

2526
const platform = getPlatform();
26-
const { platformApi, refreshWorkspaceContent } = usePlatformApi();
27+
const { platformApi } = usePlatformApi();
2728
const { activeTabView } = useTabViewManager();
29+
const { refreshWorkspaceContent } = useWorkspace();
2830

2931
const [isLoading, setIsLoading] = useState(true);
3032

web/components/explorer/file-system/tree-view.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,9 @@ const TreeViewNode = forwardRef(function TreeViewNode(
329329
setContextMenuState({ x: 0, y: 0, isOpen: false });
330330
}}
331331
>
332-
<p className="w-full text-start">Delete</p>
332+
<p className="text-danger-foreground w-full text-start">
333+
Delete
334+
</p>
333335
</Button>
334336
</div>
335337
</ContextMenu>

web/components/explorer/workspace/workspace-explorer.tsx

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@ export default function WorkspaceExplorer() {
1313
const editorContext = useContext(EditorContext);
1414

1515
const workspaceHook = useWorkspace();
16-
const { platformApi, refreshWorkspaceContent } = usePlatformApi();
16+
const { platformApi } = usePlatformApi();
17+
const { refreshWorkspaceContent, isWorkspaceRunning } = useWorkspace();
1718

1819
const [isWorkspaceSettingsModalOpen, setIsWorkspaceSettingsModalOpen] =
1920
useState(false);
2021

21-
const [isCreatingWorkspace, setIsCreatingWorkspace] = useState(false);
22-
2322
useEffect(() => {
2423
async function openProjectInWorkspace() {
2524
if (!platformApi) {
@@ -28,29 +27,32 @@ export default function WorkspaceExplorer() {
2827

2928
if (getPlatform() === PlatformEnum.Electron && !workspaceHook.workspace) {
3029
await refreshWorkspaceContent();
31-
} else {
32-
if (isCreatingWorkspace && workspaceHook.workspace) {
33-
const homePath = editorContext?.persistSettings?.projectHomePath;
34-
const projectName = editorContext?.editorStates.project;
35-
if (!projectName) {
36-
return;
37-
}
30+
} else if (workspaceHook.workspace) {
31+
const homePath = editorContext?.persistSettings?.projectHomePath;
32+
const projectName = editorContext?.editorStates.project;
33+
if (!projectName) {
34+
return;
35+
}
3836

39-
const uri = homePath + "/" + projectName;
40-
const hasPath = await platformApi.hasPath(uri);
37+
await workspaceHook.waitUntilWorkspaceRunning();
4138

42-
if (!hasPath) {
43-
await platformApi.createFolder(uri);
44-
}
39+
const uri = homePath + "/" + projectName;
40+
const hasPath = await platformApi.hasPath(uri);
4541

46-
await refreshWorkspaceContent();
47-
setIsCreatingWorkspace(false);
42+
if (!hasPath) {
43+
await platformApi.createFolder(uri);
4844
}
45+
46+
await refreshWorkspaceContent();
4947
}
5048
}
5149

5250
openProjectInWorkspace();
53-
}, [platformApi]);
51+
}, [
52+
platformApi,
53+
workspaceHook.workspace,
54+
workspaceHook.waitUntilWorkspaceRunning,
55+
]);
5456

5557
return (
5658
<div className="flex h-full w-full flex-col">
@@ -79,7 +81,7 @@ export default function WorkspaceExplorer() {
7981
}
8082
size="sm"
8183
disabledKeys={workspaceHook.workspace ? [] : ["settings"]}
82-
onSelectionChange={(key) => {
84+
onSelectionChange={async (key) => {
8385
if (
8486
key.currentKey === "__internal-create-new" ||
8587
key.currentKey === "__internal-settings"
@@ -89,11 +91,7 @@ export default function WorkspaceExplorer() {
8991
const selectedWorkspace = workspaceHook.cloudWorkspaces?.find(
9092
(workspace) => workspace.id === key.currentKey,
9193
);
92-
workspaceHook.selectWorkspace(selectedWorkspace?.id);
93-
if (selectedWorkspace) {
94-
// Create project path inside workspace if it doesn't exist
95-
setIsCreatingWorkspace(true);
96-
}
94+
await workspaceHook.selectWorkspace(selectedWorkspace?.id);
9795
}}
9896
>
9997
<>
@@ -139,14 +137,18 @@ export default function WorkspaceExplorer() {
139137
</div>
140138
{getPlatform() === PlatformEnum.Electron ||
141139
workspaceHook.workspace ? (
142-
<FileSystemExplorer
143-
setIsMenuOpen={() => {
144-
editorContext?.setEditorStates((prev) => ({
145-
...prev,
146-
isSideMenuOpen: false,
147-
}));
148-
}}
149-
/>
140+
!isWorkspaceRunning ? (
141+
<div>Workspace is starting</div>
142+
) : (
143+
<FileSystemExplorer
144+
setIsMenuOpen={() => {
145+
editorContext?.setEditorStates((prev) => ({
146+
...prev,
147+
isSideMenuOpen: false,
148+
}));
149+
}}
150+
/>
151+
)
150152
) : (
151153
<div className="flex h-full flex-col items-center justify-center px-4 pb-24">
152154
<p>

web/lib/hooks/use-platform-api.ts

Lines changed: 7 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,30 @@
1-
import { EditorContext } from "@/components/providers/editor-context-provider";
2-
import { PlatformEnum } from "@/lib/enums";
3-
import { useCallback, useContext, useEffect, useState } from "react";
1+
import { useEffect, useState } from "react";
42
import { AbstractPlatformAPI } from "../platform-api/abstract-platform-api";
5-
import { CloudAPI } from "../platform-api/cloud/cloud-api";
6-
import { ElectronAPI } from "../platform-api/electron/electron-api";
7-
import { getPlatform } from "../platform-api/platform-checker";
3+
import { getAbstractPlatformAPI } from "../platform-api/get-platform-api";
84
import { useWorkspace } from "./use-workspace";
95

106
export function usePlatformApi() {
11-
const editorContext = useContext(EditorContext);
12-
137
const { workspace } = useWorkspace();
148

159
const [platformApi, setPlatformApi] = useState<
1610
AbstractPlatformAPI | undefined
1711
>(undefined);
1812

19-
const refreshWorkspaceContent = useCallback(async () => {
20-
if (!workspace) {
21-
// Reset all content
22-
editorContext?.setEditorStates((prev) => {
23-
return {
24-
...prev,
25-
workspaceContent: undefined,
26-
explorerSelectedNodeRefs: [],
27-
};
28-
});
29-
return;
30-
}
31-
32-
const api = getAbstractPlatformAPI();
33-
34-
const projectUri =
35-
editorContext?.persistSettings?.projectHomePath +
36-
"/" +
37-
editorContext?.editorStates.project;
38-
const objects = await api?.listPathContent(projectUri, {
39-
include: "all",
40-
isRecursive: true,
41-
});
42-
43-
editorContext?.setEditorStates((prev) => {
44-
return {
45-
...prev,
46-
workspaceContent: objects,
47-
explorerSelectedNodeRefs: [],
48-
};
49-
});
50-
51-
console.log("Found project content:", objects);
52-
}, [
53-
workspace,
54-
editorContext?.persistSettings?.projectHomePath,
55-
editorContext?.editorStates.project,
56-
]);
57-
5813
useEffect(() => {
59-
const api = getAbstractPlatformAPI();
14+
const api = getAbstractPlatformAPI(workspace);
6015
setPlatformApi(api);
6116
}, []);
6217

63-
// When workspace changes, reset platform API if needed
18+
// When workspace changes, update platform API if needed.
19+
// So the platform api switch to the latest workspace context.
6420
useEffect(() => {
65-
if (platformApi && workspace) {
66-
const api = getAbstractPlatformAPI();
21+
if (workspace) {
22+
const api = getAbstractPlatformAPI(workspace);
6723
setPlatformApi(api);
6824
}
6925
}, [workspace]);
7026

71-
// When workspace changes, re-fetch content
72-
useEffect(() => {
73-
refreshWorkspaceContent();
74-
}, [refreshWorkspaceContent]);
75-
76-
function getAbstractPlatformAPI(): AbstractPlatformAPI {
77-
const platform = getPlatform();
78-
79-
if (platform === PlatformEnum.Capacitor) {
80-
// return new CapacitorAPI();
81-
return new CloudAPI(workspace);
82-
} else if (platform === PlatformEnum.Electron) {
83-
return new ElectronAPI();
84-
} else if (
85-
platform === PlatformEnum.Web ||
86-
platform === PlatformEnum.WebMobile
87-
) {
88-
return new CloudAPI(workspace);
89-
} else if (platform === PlatformEnum.VSCode) {
90-
// platformApi.current = new VSCodeAPI();
91-
throw new Error("VSCode API not implemented");
92-
} else {
93-
throw new Error("Unknown platform");
94-
}
95-
}
96-
9727
return {
9828
platformApi,
99-
refreshWorkspaceContent,
10029
};
10130
}

0 commit comments

Comments
 (0)