Skip to content

Commit b1e2f9a

Browse files
Revised fix for cross-tab issues (#623)
* Revert "Import a JSON project like a hex file (#622)" This reverts commit f001f97. * Revised fix for cross-tab issues The previous fix still had issues when creating a new project in a second tab and switching between them. I initially fixed this by taking the same approach for new project (via MakeCode) but it's slow and you see the old project render. The loading states that we'd need don't seen proportionate. So I've gone with: - updating MakeCode only as needed - ensuring import from .org has a header id by setting one explicitly - carefully tracking when we expect to get new content from MakeCode in editorChange Fixes #618
1 parent f001f97 commit b1e2f9a

File tree

5 files changed

+156
-111
lines changed

5 files changed

+156
-111
lines changed

src/hooks/project-hooks.tsx

Lines changed: 8 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,7 @@ import {
2828
PostImportDialogState,
2929
SaveStep,
3030
} from "../model";
31-
import {
32-
renameProject,
33-
untitledProjectName as untitled,
34-
} from "../project-name";
31+
import { untitledProjectName as untitled } from "../project-name";
3532
import { useStore } from "../store";
3633
import {
3734
createCodePageUrl,
@@ -59,10 +56,6 @@ interface ProjectContext {
5956
project: MakeCodeProject;
6057
projectEdited: boolean;
6158
resetProject: () => void;
62-
importProject: (
63-
project: MakeCodeProject,
64-
projectNameOverride: string
65-
) => void;
6659
loadFile: (file: File, type: LoadType) => void;
6760
/**
6861
* Called to request a save.
@@ -137,7 +130,8 @@ export const ProjectProvider = ({
137130
const openEditorTimedOutDialog = useStore(
138131
(s) => () => s.setIsEditorTimedOutDialogOpen(true)
139132
);
140-
const expectChangedHeader = useStore((s) => s.setChangedHeaderExpected);
133+
const setEditorLoadingFile = useStore((s) => s.setEditorLoadingFile);
134+
const setEditorImportingState = useStore((s) => s.setEditorImportingState);
141135
const projectFlushedToEditor = useStore((s) => s.projectFlushedToEditor);
142136
const checkIfProjectNeedsFlush = useStore((s) => s.checkIfProjectNeedsFlush);
143137
const getCurrentProject = useStore((s) => s.getCurrentProject);
@@ -225,8 +219,8 @@ export const ProjectProvider = ({
225219
logging.log("[MakeCode] Importing project");
226220
await editorReadyPromise.promise;
227221
const project = getCurrentProject();
228-
expectChangedHeader();
229222
try {
223+
setEditorImportingState();
230224
await driverRef.current.importProject({ project });
231225
logging.log("[MakeCode] Project import succeeded");
232226
projectFlushedToEditor();
@@ -267,7 +261,7 @@ export const ProjectProvider = ({
267261
logging,
268262
editorReadyPromise.promise,
269263
getCurrentProject,
270-
expectChangedHeader,
264+
setEditorImportingState,
271265
projectFlushedToEditor,
272266
langChangeFlushedToEditor,
273267
checkIfEditorStartUpTimedOut,
@@ -339,6 +333,7 @@ export const ProjectProvider = ({
339333
return;
340334
}
341335
// This triggers the code in editorChanged to update actions etc.
336+
setEditorLoadingFile();
342337
driverRef.current!.importFile({
343338
filename: file.name,
344339
parts: [hex],
@@ -353,42 +348,13 @@ export const ProjectProvider = ({
353348
[
354349
checkIfEditorStartUpTimedOut,
355350
driverRef,
356-
editorReadyPromise,
351+
editorReadyPromise.promise,
357352
loadDataset,
358353
logging,
359354
navigate,
360355
openEditorTimedOutDialog,
361356
setPostImportDialogState,
362-
]
363-
);
364-
365-
const importProject = useCallback(
366-
async (
367-
project: MakeCodeProject,
368-
projectNameOverride: string
369-
): Promise<void> => {
370-
const hasTimedOut = await checkIfEditorStartUpTimedOut(
371-
editorReadyPromise.promise
372-
);
373-
if (hasTimedOut) {
374-
openEditorTimedOutDialog();
375-
return;
376-
}
377-
try {
378-
// This triggers the code in editorChanged to update actions etc.
379-
await driverRef.current!.importProject({
380-
project: renameProject(project, projectNameOverride),
381-
});
382-
} catch (e) {
383-
setPostImportDialogState(PostImportDialogState.Error);
384-
}
385-
},
386-
[
387-
checkIfEditorStartUpTimedOut,
388-
driverRef,
389-
editorReadyPromise.promise,
390-
openEditorTimedOutDialog,
391-
setPostImportDialogState,
357+
setEditorLoadingFile,
392358
]
393359
);
394360

@@ -493,7 +459,6 @@ export const ProjectProvider = ({
493459
const value = useMemo(
494460
() => ({
495461
loadFile,
496-
importProject,
497462
openEditor,
498463
browserNavigationToEditor,
499464
project,
@@ -512,7 +477,6 @@ export const ProjectProvider = ({
512477
}),
513478
[
514479
loadFile,
515-
importProject,
516480
openEditor,
517481
browserNavigationToEditor,
518482
project,

src/pages/ImportPage.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,21 @@ const ImportPage = () => {
7575
});
7676
}, [activitiesBaseUrl, defaultProjectName, intl, logging, params]);
7777

78-
const { importProject } = useProject();
78+
const loadProject = useStore((s) => s.loadProject);
7979
const newSession = useStore((s) => s.newSession);
8080
const timestamp = useStore((s) => s.timestamp);
8181

8282
const handleStartSession = useCallback(() => {
8383
if (project) {
84-
importProject(project, name);
84+
loadProject(project, name);
8585
navigate(createDataSamplesPageUrl());
8686
} else {
8787
// If no resource fetched, start as new empty session
8888
// with provided project name
8989
newSession(name);
9090
navigate(createDataSamplesPageUrl());
9191
}
92-
}, [importProject, name, navigate, newSession, project]);
92+
}, [loadProject, name, navigate, newSession, project]);
9393

9494
const { saveHex } = useProject();
9595
const handleSave = useCallback(() => {

src/pages/OpenSharedProjectPage.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,21 +68,21 @@ const contentStackProps: Partial<StackProps> = {
6868
const OpenSharedProjectPage = () => {
6969
const logging = useLogging();
7070
const navigate = useNavigate();
71-
const { importProject } = useProject();
71+
const loadProject = useStore((s) => s.loadProject);
7272
const [name, setName] = useState("");
7373
const { sharedState, header, dataset, projectText } =
7474
useProjectPreload(setName);
7575
const { shortId } = useParams();
7676

7777
const handleOpenProject = useCallback(() => {
7878
if (!header || !projectText) return;
79-
importProject({ header: { ...header, name }, text: projectText }, name);
79+
loadProject({ header: { ...header, name }, text: projectText }, name);
8080
logging.event({
8181
type: "import-shared-project-complete",
8282
detail: { shortId },
8383
});
8484
navigate(createDataSamplesPageUrl());
85-
}, [importProject, header, projectText, name, navigate, logging, shortId]);
85+
}, [loadProject, header, projectText, name, navigate, logging, shortId]);
8686

8787
if (sharedState === SharedState.Failed) {
8888
return <ErrorPreloading />;

src/project-name.ts

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import { MakeCodeProject } from "@microbit/makecode-embed";
2-
import { filenames } from "./makecode/utils";
3-
41
/**
52
* (c) 2024, Micro:bit Educational Foundation and contributors
63
*
@@ -10,26 +7,3 @@ export const untitledProjectName = "Untitled";
107
export const validateProjectName = (name: string): boolean => {
118
return name.trim().length > 0;
129
};
13-
14-
export const renameProject = (
15-
project: MakeCodeProject,
16-
name: string
17-
): MakeCodeProject => {
18-
const pxtString = project.text?.[filenames.pxtJson];
19-
const pxt = JSON.parse(pxtString ?? "{}") as Record<string, unknown>;
20-
21-
return {
22-
...project,
23-
header: {
24-
...project.header!,
25-
name,
26-
},
27-
text: {
28-
...project.text,
29-
[filenames.pxtJson]: JSON.stringify({
30-
...pxt,
31-
name,
32-
}),
33-
},
34-
};
35-
};

0 commit comments

Comments
 (0)