Skip to content

Commit 98924be

Browse files
sanchitrkclaude
andcommitted
fix(web): open a new workspace only once the list has it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 383c599 commit 98924be

4 files changed

Lines changed: 27 additions & 23 deletions

File tree

‎apps/web/src/settings/workspaces.tsx‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ import { iconOf, icons } from "../shell/icons";
2121
import { shortcutLabel } from "../shell/switcher";
2222
import { deskAtom, only, untag } from "../wm/instances";
2323
import {
24-
createWorkspace,
2524
deleteWorkspace,
2625
reorderWorkspaces,
2726
MAX_WORKSPACES,
2827
updateWorkspace,
28+
useCreateWorkspace,
2929
useWorkspaces,
3030
type Workspace,
3131
workspacesKey,
@@ -39,7 +39,7 @@ const sameOrder = (ids: readonly string[], workspaces: readonly Workspace[]) =>
3939
/** List, create, rename, re-icon, reorder (drag the grip), and delete workspaces. */
4040
export function WorkspacesSettings() {
4141
const workspaces = useWorkspaces();
42-
const create = useAtomSet(createWorkspace, { mode: "promise" });
42+
const create = useCreateWorkspace();
4343
const reorder = useAtomSet(reorderWorkspaces, { mode: "promise" });
4444
const [error, setError] = useState<string | null>(null);
4545
// The new workspace, whose name field takes focus.
@@ -59,10 +59,7 @@ export function WorkspacesSettings() {
5959

6060
const addWorkspace = () =>
6161
run(async () => {
62-
const workspace = await create({
63-
payload: { name: `Workspace ${workspaces.length + 1}`, icon: "app-window" },
64-
reactivityKeys: workspacesKey,
65-
});
62+
const workspace = await create({ name: `Workspace ${workspaces.length + 1}`, icon: "app-window" });
6663
setCreated(workspace.id);
6764
});
6865

‎apps/web/src/shell/titlebar.tsx‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { useAtomSet } from "@effect/atom-react";
21
import { Link, useCanGoBack, useNavigate, useRouter } from "@tanstack/react-router";
32
import { ChevronLeft, House, Plus, Settings } from "lucide-react";
43

5-
import { createWorkspace, MAX_WORKSPACES, useWorkspaces, workspaceRoute, workspacesKey } from "../wm/workspaces";
4+
import { MAX_WORKSPACES, useCreateWorkspace, useWorkspaces, workspaceRoute } from "../wm/workspaces";
65

76
/*
87
* Title-bar controls shared by the workspace shell and the start page, so the two bars behave alike.
@@ -45,13 +44,10 @@ export function HomeButton() {
4544
export function NewWorkspaceButton() {
4645
const workspaces = useWorkspaces();
4746
const navigate = useNavigate();
48-
const create = useAtomSet(createWorkspace, { mode: "promise" });
47+
const create = useCreateWorkspace();
4948
const full = workspaces.length >= MAX_WORKSPACES;
5049
const add = async () => {
51-
const workspace = await create({
52-
payload: { name: `Workspace ${workspaces.length + 1}`, icon: "app-window" },
53-
reactivityKeys: workspacesKey,
54-
});
50+
const workspace = await create({ name: `Workspace ${workspaces.length + 1}`, icon: "app-window" });
5551
void navigate(workspaceRoute(workspace));
5652
};
5753
return (

‎apps/web/src/wm/open.ts‎

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
import { useAtomSet, useAtomValue } from "@effect/atom-react";
1+
import { useAtomValue } from "@effect/atom-react";
22
import { useNavigate } from "@tanstack/react-router";
33

44
import type { OpenMode } from "../sdk";
55
import { deskAtom } from "./instances";
66
import {
7-
createWorkspace,
87
lastWorkspaceAtom,
98
MAX_WORKSPACES,
109
openInWorkspaceRoute,
10+
useCreateWorkspace,
1111
useWorkspaces,
1212
type Workspace,
13-
workspacesKey,
1413
workspaceTag,
1514
} from "./workspaces";
1615

@@ -26,7 +25,7 @@ export function useOpenElsewhere() {
2625
const workspaces = useWorkspaces();
2726
const { instances, order } = useAtomValue(deskAtom);
2827
const lastId = useAtomValue(lastWorkspaceAtom);
29-
const create = useAtomSet(createWorkspace, { mode: "promise" });
28+
const create = useCreateWorkspace();
3029
const navigate = useNavigate();
3130

3231
return async (address: string, name: string, mode: OpenMode) => {
@@ -43,10 +42,7 @@ export function useOpenElsewhere() {
4342
if (last !== undefined && shows(last).length === 0) return go(last);
4443

4544
if (workspaces.length < MAX_WORKSPACES) {
46-
const created = await create({
47-
payload: { name, icon: "messages-square", auto: true },
48-
reactivityKeys: workspacesKey,
49-
}).catch(() => undefined);
45+
const created = await create({ name, icon: "messages-square", auto: true }).catch(() => undefined);
5046
if (created !== undefined) return go(created);
5147
}
5248
if (last !== undefined) return go(last);

‎apps/web/src/wm/workspaces.ts‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { useAtomValue } from "@effect/atom-react";
1+
import { RegistryContext, useAtomSet, useAtomValue } from "@effect/atom-react";
22
import type { Workspace } from "@codeworksh/server/contract";
33
import { Atom, AsyncResult } from "effect/reactivity";
4+
import { useContext } from "react";
45
import { tagBit } from "webwm";
56

6-
import { Server } from "../kernel/rpc";
7+
import { runQuery, Server } from "../kernel/rpc";
78

89
export type { Workspace };
910

@@ -41,3 +42,17 @@ export const openInWorkspaceRoute = (workspace: Workspace, address: string, mode
4142
...workspaceRoute(workspace),
4243
search: { open: address, ...(mode === "new" ? { mode: "new" as const } : {}) },
4344
}) as const;
45+
46+
/**
47+
* Creates a workspace and resolves once the shared list includes it. Going to it before then would
48+
* find a stale list: the shell shows nothing, or sends an empty-looking app back to the start page.
49+
*/
50+
export function useCreateWorkspace() {
51+
const registry = useContext(RegistryContext);
52+
const create = useAtomSet(createWorkspace, { mode: "promise" });
53+
return async (payload: { readonly name: string; readonly icon: string; readonly auto?: boolean }) => {
54+
const workspace = await create({ payload, reactivityKeys: workspacesKey });
55+
await runQuery(registry, workspacesAtom);
56+
return workspace;
57+
};
58+
}

0 commit comments

Comments
 (0)