Skip to content

Commit b4f4aa1

Browse files
christianalfoniCompuIves
authored andcommitted
LivePage: refactor LivePage and make changedShortIds a derived (codesandbox#3208)
* refactor LivePageand make changedShortsids a derived * change how we handle signing into live * improve auth indication when joining live sandbox * fix type on setInterval
1 parent 621039e commit b4f4aa1

File tree

16 files changed

+207
-182
lines changed

16 files changed

+207
-182
lines changed

packages/app/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@
158158
"normalizr": "^3.2.3",
159159
"onigasm": "^2.2.1",
160160
"ot": "^0.0.15",
161-
"overmind": "^21.0.0-1575912749783",
161+
"overmind": "^21.0.0-1576231149763",
162162
"overmind-devtools": "^19.0.0",
163-
"overmind-react": "^22.0.0-1575912749783",
163+
"overmind-react": "^22.0.0-1576231149763",
164164
"phoenix": "^1.4.11",
165165
"postcss": "^6.0.9",
166166
"postcss-selector-parser": "^2.2.3",

packages/app/src/app/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ import { createOvermind } from 'overmind';
2525
import { Provider as ActualOvermindProvider } from 'overmind-react';
2626
import React from 'react';
2727
import { ApolloProvider } from 'react-apollo';
28+
import { DndProvider } from 'react-dnd';
2829
import { render } from 'react-dom';
2930
import { Router } from 'react-router-dom';
3031
import { ThemeProvider } from 'styled-components';
31-
import { DndProvider } from 'react-dnd';
3232

3333
import { config } from './overmind';
3434
import { Provider as OvermindProvider } from './overmind/Provider';

packages/app/src/app/overmind/effects/api/index.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ import {
1919
UploadedFilesInfo,
2020
UserSandbox,
2121
} from '@codesandbox/common/lib/types';
22-
import { client } from 'app/graphql/client';
2322
import { LIST_PERSONAL_TEMPLATES } from 'app/components/CreateNewSandbox/queries';
23+
import { client } from 'app/graphql/client';
2424

2525
import {
2626
transformDirectory,
@@ -116,10 +116,12 @@ export default {
116116
)
117117
.then(transformModule);
118118
},
119-
saveModules(sandboxId: string, modules: Module[]) {
120-
return api.put(`/sandboxes/${sandboxId}/modules/mupdate`, {
121-
modules,
122-
});
119+
saveModules(sandboxId: string, modules: Module[]): Promise<Module[]> {
120+
return api
121+
.put<IModuleAPIResponse[]>(`/sandboxes/${sandboxId}/modules/mupdate`, {
122+
modules,
123+
})
124+
.then(modulesResult => modulesResult.map(transformModule));
123125
},
124126
getGitChanges(sandboxId: string): Promise<GitChanges> {
125127
return api.get(`/sandboxes/${sandboxId}/git/diff`);

packages/app/src/app/overmind/factories.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import { IDerive, IState, json } from 'overmind';
33

44
import { AsyncAction } from '.';
55

6+
/*
7+
Ensures that we have loaded the app with the initial user
8+
and settings
9+
*/
610
export const withLoadApp = <T>(
711
continueAction?: AsyncAction<T>
812
): AsyncAction<T> => async (context, value) => {
@@ -18,6 +22,7 @@ export const withLoadApp = <T>(
1822

1923
state.isAuthenticating = true;
2024
state.jwt = effects.jwt.get() || null;
25+
2126
effects.connection.addListener(actions.connectionChanged);
2227
actions.internal.setStoredSettings();
2328
effects.keybindingManager.set(

packages/app/src/app/overmind/internalActions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export const signIn: AsyncAction<{ useExtraScopes?: boolean }> = async (
3636
effects.live.connect();
3737
actions.userNotifications.internal.initialize(); // Seemed a bit different originally?
3838
actions.refetchSandboxInfo();
39+
state.isAuthenticating = false;
3940
} catch (error) {
4041
actions.internal.handleError({
4142
message: 'Could not authenticate with Github',
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
export const forkFrozenModal = {
22
result: 'fork' as 'fork' | 'cancel' | 'unfreeze',
33
};
4+
5+
export const authenticateUserModal = {};

packages/app/src/app/overmind/namespaces/editor/actions.ts

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,6 @@ export const sandboxChanged: AsyncAction<{ id: string }> = withLoadApp<{
8787
state.editor.isLoading = !hasExistingSandbox;
8888
state.editor.notFound = false;
8989

90-
// Only reset changed modules if sandbox wasn't in memory, otherwise a fork
91-
// can mark real changed modules as unchanged
92-
state.editor.changedModuleShortids = [];
93-
9490
try {
9591
const sandbox = await effects.api.getSandbox(newId);
9692

@@ -232,17 +228,42 @@ export const codeChanged: Action<{
232228
export const saveClicked: AsyncAction = withOwnedSandbox(
233229
async ({ state, effects, actions }) => {
234230
const sandbox = state.editor.currentSandbox;
235-
const currentlyChangedModuleShortids = state.editor.changedModuleShortids.slice();
236231

237232
try {
238233
const changedModules = sandbox.modules.filter(module =>
239234
state.editor.changedModuleShortids.includes(module.shortid)
240235
);
241236

242-
state.editor.changedModuleShortids = [];
237+
const updatedModules = await effects.api.saveModules(
238+
sandbox.id,
239+
changedModules
240+
);
241+
242+
updatedModules.forEach(updatedModule => {
243+
const module = sandbox.modules.find(
244+
moduleItem => moduleItem.shortid === updatedModule.shortid
245+
);
243246

244-
await effects.api.saveModules(sandbox.id, changedModules);
245-
effects.moduleRecover.clearSandbox(sandbox.id);
247+
if (module) {
248+
module.insertedAt = updatedModule.insertedAt;
249+
module.updatedAt = updatedModule.updatedAt;
250+
251+
module.savedCode =
252+
updatedModule.code === module.code ? null : updatedModule.code;
253+
254+
effects.vscode.sandboxFsSync.writeFile(
255+
state.editor.modulesByPath,
256+
module
257+
);
258+
effects.moduleRecover.remove(sandbox.id, module);
259+
} else {
260+
// We might not have the module, as it was created by the server. In
261+
// this case we put it in. There is an edge case here where the user
262+
// might delete the module while it is being updated, but it will very
263+
// likely not happen
264+
sandbox.modules.push(updatedModule);
265+
}
266+
});
246267

247268
if (
248269
state.editor.currentSandbox.originalGit &&
@@ -253,13 +274,6 @@ export const saveClicked: AsyncAction = withOwnedSandbox(
253274

254275
effects.preview.executeCodeImmediately();
255276
} catch (error) {
256-
// Put back any unsaved modules taking into account that you
257-
// might have changed some modules waiting for saving
258-
currentlyChangedModuleShortids.forEach(moduleShortid => {
259-
if (!state.editor.changedModuleShortids.includes(moduleShortid)) {
260-
state.editor.changedModuleShortids.push(moduleShortid);
261-
}
262-
});
263277
actions.internal.handleError({
264278
message: 'There was a problem with saving the files, please try again',
265279
error,
@@ -510,11 +524,6 @@ export const discardModuleChanges: Action<{
510524

511525
module.updatedAt = new Date().toString();
512526
effects.vscode.revertModule(module);
513-
514-
state.editor.changedModuleShortids.splice(
515-
state.editor.changedModuleShortids.indexOf(moduleShortid),
516-
1
517-
);
518527
};
519528

520529
export const fetchEnvironmentVariables: AsyncAction = async ({

packages/app/src/app/overmind/namespaces/editor/internalActions.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,6 @@ export const saveCode: AsyncAction<{
120120
effects.vscode.sandboxFsSync.writeFile(state.editor.modulesByPath, module);
121121
effects.moduleRecover.remove(sandbox.id, module);
122122

123-
state.editor.changedModuleShortids.splice(
124-
state.editor.changedModuleShortids.indexOf(module.shortid),
125-
1
126-
);
127-
128123
if (cbID) {
129124
effects.vscode.callCallback(cbID);
130125
}
@@ -269,23 +264,11 @@ export const setModuleCode: Action<{
269264
code: string;
270265
}> = ({ state, effects }, { module, code }) => {
271266
const { currentSandbox } = state.editor;
272-
const hasChangedModuleId = state.editor.changedModuleShortids.includes(
273-
module.shortid
274-
);
275267

276268
if (module.savedCode === null) {
277269
module.savedCode = module.code;
278270
}
279271

280-
if (hasChangedModuleId && module.savedCode === code) {
281-
state.editor.changedModuleShortids.splice(
282-
state.editor.changedModuleShortids.indexOf(module.shortid),
283-
1
284-
);
285-
} else if (!hasChangedModuleId && module.savedCode !== code) {
286-
state.editor.changedModuleShortids.push(module.shortid);
287-
}
288-
289272
effects.vscode.runCommand('workbench.action.keepEditor');
290273

291274
const tabs = state.editor.tabs as ModuleTab[];

packages/app/src/app/overmind/namespaces/editor/state.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type State = {
3939
notFound: boolean;
4040
error: string | null;
4141
isResizing: boolean;
42-
changedModuleShortids: string[];
42+
changedModuleShortids: Derive<State, string[]>;
4343
currentTabId: string;
4444
tabs: Tabs;
4545
errors: ModuleError[];
@@ -79,7 +79,19 @@ export const state: State = {
7979
error: null,
8080
isResizing: false,
8181
modulesByPath: {},
82-
changedModuleShortids: [],
82+
changedModuleShortids: ({ currentSandbox }) => {
83+
if (!currentSandbox) {
84+
return [];
85+
}
86+
87+
return currentSandbox.modules.reduce((aggr, module) => {
88+
if (module.savedCode !== null && module.savedCode !== module.code) {
89+
return aggr.concat(module.shortid);
90+
}
91+
92+
return aggr;
93+
}, []);
94+
},
8395
currentTabId: null,
8496
tabs: [],
8597
errors: [],

packages/app/src/app/overmind/namespaces/live/actions.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,38 @@ import * as liveMessage from './liveMessageOperators';
99

1010
export const internal = internalActions;
1111

12+
export const signInToRoom: AsyncAction<{
13+
roomId: string;
14+
}> = withLoadApp(async ({ state, effects, actions }, { roomId }) => {
15+
await actions.internal.signIn({});
16+
17+
if (state.isLoggedIn) {
18+
await actions.live.roomJoined({
19+
roomId,
20+
});
21+
}
22+
});
23+
1224
export const roomJoined: AsyncAction<{
1325
roomId: string;
1426
}> = withLoadApp(async ({ state, effects, actions }, { roomId }) => {
27+
if (!state.isLoggedIn) {
28+
return;
29+
}
30+
1531
await effects.vscode.initialize;
1632
await effects.vscode.closeAllTabs();
33+
34+
if (state.live.isLive) {
35+
actions.live.internal.disconnect();
36+
}
37+
1738
const sandbox = await actions.live.internal.initialize(roomId);
1839

40+
if (!sandbox) {
41+
return;
42+
}
43+
1944
if (state.updateStatus === 'available') {
2045
const modal = 'liveVersionMismatch';
2146
effects.analytics.track('Open Modal', { modal });
@@ -36,7 +61,7 @@ export const roomJoined: AsyncAction<{
3661
effects.live.sendModuleStateSyncRequest();
3762
effects.vscode.openModule(state.editor.currentModule);
3863
effects.preview.executeCodeImmediately({ initialRender: true });
39-
state.live.isLoading = false;
64+
state.editor.isLoading = false;
4065
});
4166

4267
export const createLiveClicked: AsyncAction<string> = async (

0 commit comments

Comments
 (0)