Skip to content

Commit

Permalink
Delay the readyPromise until the workspace is loaded, add skillmap lo…
Browse files Browse the repository at this point in the history
…ader to main page (#8597) (#8599)

* Delay the readyPromise until the workspace is loaded, add skillmap loader to main page

* Remove leftover CSS class

* Fix spacing in loader component

Co-authored-by: Joey Wunderlich <[email protected]>

* Flush message queue when workspace is ready

* Only set syncingLocalState to false if it is currently true

Co-authored-by: Joey Wunderlich <[email protected]>

Co-authored-by: Joey Wunderlich <[email protected]>
  • Loading branch information
shakao and jwunderl authored Nov 13, 2021
1 parent 838618e commit 0ed760e
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 19 deletions.
37 changes: 24 additions & 13 deletions skillmap/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { InfoPanel } from './components/InfoPanel';

import { parseSkillMap } from './lib/skillMapParser';
import { parseHash, getMarkdownAsync, MarkdownSource, parseQuery,
setPageTitle, setPageSourceUrl, ParsedHash } from './lib/browserUtils';
setPageTitle, setPageSourceUrl, ParsedHash, resolvePath } from './lib/browserUtils';

import { MakeCodeFrame } from './components/makecodeFrame';
import { getLocalUserStateAsync, getUserStateAsync, saveUserStateAsync } from './lib/workspaceProvider';
Expand Down Expand Up @@ -70,6 +70,7 @@ interface AppState {
error?: string;
cloudSyncCheckHasFinished: boolean;
badgeSyncLock: boolean;
syncingLocalState?: boolean;
}

class AppImpl extends React.Component<AppProps, AppState> {
Expand Down Expand Up @@ -234,8 +235,9 @@ class AppImpl extends React.Component<AppProps, AppState> {
protected async cloudSyncCheckAsync() {
const res = await this.ready();
if (!await authClient.loggedInAsync()) {
this.setState({cloudSyncCheckHasFinished: true});
this.setState({cloudSyncCheckHasFinished: true, syncingLocalState: false});
} else {
this.setState({syncingLocalState: true});
const doCloudSyncCheckAsync = async () => {
const state = store.getState();
const localUser = await getLocalUserStateAsync();
Expand Down Expand Up @@ -313,14 +315,14 @@ class AppImpl extends React.Component<AppProps, AppState> {
action: "requestprojectcloudstatus",
headerIds: getFlattenedHeaderIds(currentUser, state.pageSourceUrl)
} as pxt.editor.EditorMessageRequestProjectCloudStatus);
this.setState({cloudSyncCheckHasFinished: true});
this.setState({cloudSyncCheckHasFinished: true, syncingLocalState: false});
}
// Timeout if cloud sync check doesn't complete in a reasonable timeframe.
const TIMEOUT_MS = 10 * 1000;
await Promise.race([
pxt.U.delay(TIMEOUT_MS).then(() => {
if (!this.state.cloudSyncCheckHasFinished)
this.setState({cloudSyncCheckHasFinished: true});
this.setState({cloudSyncCheckHasFinished: true, syncingLocalState: false});
}),
doCloudSyncCheckAsync()]);
}
Expand Down Expand Up @@ -352,18 +354,22 @@ class AppImpl extends React.Component<AppProps, AppState> {

render() {
const { skillMaps, activityOpen, backgroundImageUrl, theme } = this.props;
const { error } = this.state;
const { error, syncingLocalState } = this.state;
const maps = Object.keys(skillMaps).map((id: string) => skillMaps[id]);
return (<div className={`app-container ${pxt.appTarget.id}`}>
<HeaderBar />
<div className={`skill-map-container ${activityOpen ? "hidden" : ""}`} style={{ backgroundColor: theme.backgroundColor }}>
{ error
? <div className="skill-map-error">{error}</div>
: <SkillGraphContainer maps={maps} backgroundImageUrl={backgroundImageUrl} />
}
{ !error && <InfoPanel />}
</div>
<MakeCodeFrame onFrameLoaded={this.onMakeCodeFrameLoaded}/>
{syncingLocalState && <div className={"makecode-frame-loader"}>
<img src={resolvePath("assets/logo.svg")} alt={lf("MakeCode Logo")} />
<div className="makecode-frame-loader-text">{lf("Saving to cloud...")}</div>
</div>}
<div className={`skill-map-container ${activityOpen ? "hidden" : ""}`} style={{ backgroundColor: theme.backgroundColor }}>
{ error
? <div className="skill-map-error">{error}</div>
: <SkillGraphContainer maps={maps} backgroundImageUrl={backgroundImageUrl} />
}
{ !error && <InfoPanel />}
</div>
<MakeCodeFrame onWorkspaceReady={this.onMakeCodeFrameLoaded}/>
<AppModal />
<UserProfile />
</div>);
Expand Down Expand Up @@ -427,6 +433,11 @@ class AppImpl extends React.Component<AppProps, AppState> {
}
}

if ((!this.props.signedIn || (this.props.signedIn && this.state.cloudSyncCheckHasFinished))
&& this.state.syncingLocalState) {
this.setState({ syncingLocalState: false });
}

await this.syncBadgesAsync();
}

Expand Down
15 changes: 9 additions & 6 deletions skillmap/src/components/makecodeFrame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ interface MakeCodeFrameProps {
dispatchSetShareStatus: (headerId?: string, url?: string) => void;
dispatchShowLoginPrompt: () => void;
dispatchSetCloudStatus: (headerId: string, status: string) => void;
onFrameLoaded: (sendMessageAsync: (message: any) => Promise<any>) => void;
onWorkspaceReady: (sendMessageAsync: (message: any) => Promise<any>) => void;
}

type FrameState = "loading" | "no-project" | "opening-project" | "project-open" | "closing-project";
Expand Down Expand Up @@ -143,8 +143,6 @@ class MakeCodeFrameImpl extends React.Component<MakeCodeFrameProps, MakeCodeFram

const root = document.getElementById("root");
if (root) pxt.BrowserUtils.addClass(root, "editor");

this.props.onFrameLoaded((message) => this.sendMessageAsync(message));
}
}

Expand All @@ -165,6 +163,11 @@ class MakeCodeFrameImpl extends React.Component<MakeCodeFrameProps, MakeCodeFram

switch (data.action) {
case "newproject":
if (!this.state.workspaceReady) {
this.setState({ workspaceReady: true });
this.sendMessageAsync(); // Flush message queue
this.props.onWorkspaceReady((message) => this.sendMessageAsync(message));
}
if (this.state.frameState === "loading") {
this.setState({ frameState: "no-project" });
}
Expand All @@ -182,7 +185,7 @@ class MakeCodeFrameImpl extends React.Component<MakeCodeFrameProps, MakeCodeFram
}
}

protected sendMessageAsync(message: any) {
protected sendMessageAsync(message?: any) {
return new Promise(resolve => {
const sendMessageCore = (message: any) => {
message.response = true;
Expand All @@ -195,14 +198,14 @@ class MakeCodeFrameImpl extends React.Component<MakeCodeFrameProps, MakeCodeFram
}

if (this.ref) {
if (!this.ref.contentWindow) {
if (!this.state.workspaceReady) {
this.messageQueue.push(message);
}
else {
while (this.messageQueue.length) {
sendMessageCore(this.messageQueue.shift());
}
sendMessageCore(message);
if (message) sendMessageCore(message);
}
}
});
Expand Down

0 comments on commit 0ed760e

Please sign in to comment.