Skip to content

Commit deffd66

Browse files
fixed smooth forking and containers
1 parent ad436b4 commit deffd66

File tree

5 files changed

+76
-28
lines changed

5 files changed

+76
-28
lines changed
Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1+
import { blocker } from 'app/utils/blocker';
2+
13
import { Reaction } from '..';
24

3-
let _preview;
5+
let _preview = blocker<any>();
46
let _reaction: Reaction;
57

68
export default {
79
initialize(reaction: Reaction) {
810
_reaction = reaction;
911
},
1012
initializePreview(preview: any) {
11-
_preview = preview;
13+
_preview.resolve(preview);
1214

1315
const dispose = _reaction(
1416
state => [
@@ -21,32 +23,30 @@ export default {
2123
isAllModulesSynced &&
2224
(template === 'static' || !livePreviewEnabled)
2325
) {
24-
_preview.handleRefresh();
26+
preview.handleRefresh();
2527
}
2628
}
2729
);
2830

2931
return () => {
30-
_preview = null;
3132
dispose();
33+
_preview = blocker<any>();
3234
};
3335
},
34-
executeCodeImmediately(initialRender?: boolean) {
35-
if (!_preview) {
36-
return;
37-
}
38-
_preview.executeCodeImmediately(initialRender);
36+
async executeCodeImmediately(initialRender?: boolean) {
37+
const preview = await _preview.promise;
38+
preview.executeCodeImmediately(initialRender);
39+
},
40+
async executeCode() {
41+
const preview = await _preview.promise;
42+
preview.executeCode();
3943
},
40-
executeCode() {
41-
if (!_preview) {
42-
return;
43-
}
44-
_preview.executeCode();
44+
async refresh() {
45+
const preview = await _preview.promise;
46+
preview.handleRefresh();
4547
},
46-
refresh() {
47-
if (!_preview) {
48-
return;
49-
}
50-
_preview.handleRefresh();
48+
async refreshUrl() {
49+
const preview = await _preview.promise;
50+
preview.refreshUrl();
5151
},
5252
};

packages/app/src/app/overmind/effects/vscode/sandboxFsSync/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ class SandboxFsSync {
148148
writeFile(fs, json(module));
149149

150150
this.send('write-file', module);
151+
152+
if (module.title === 'package.json') {
153+
this.syncDependencyTypings();
154+
}
151155
}
152156

153157
public rename(fs: SandboxFs, fromPath: string, toPath: string) {

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

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export const saveCode: AsyncAction<{
7373
code: string;
7474
moduleShortid: string;
7575
cbID?: string | null;
76-
}> = async ({ state, effects, actions }, { moduleShortid, cbID }) => {
76+
}> = async ({ state, effects, actions }, { code, moduleShortid, cbID }) => {
7777
effects.analytics.track('Save Code');
7878

7979
const sandbox = state.editor.currentSandbox;
@@ -83,6 +83,8 @@ export const saveCode: AsyncAction<{
8383
return;
8484
}
8585

86+
module.code = code;
87+
8688
try {
8789
const updatedModule = await effects.api.saveModuleCode(sandbox.id, module);
8890

@@ -296,10 +298,27 @@ export const forkSandbox: AsyncAction<{
296298
});
297299
}
298300

299-
await actions.internal.setCurrentSandbox(forkedSandbox);
300-
state.editor.modulesByPath = effects.vscode.fs.create(forkedSandbox);
301-
await effects.vscode.changeSandbox(forkedSandbox);
302-
effects.vscode.openModule(state.editor.currentModule);
301+
// When we have a server we want to set a brand new sandbox,
302+
// as the preview also needs to be managed correctly
303+
if (getTemplateDefinition(forkedSandbox.template).isServer) {
304+
await effects.vscode.closeAllTabs();
305+
actions.internal.setCurrentSandbox(forkedSandbox);
306+
state.editor.modulesByPath = effects.vscode.fs.create(forkedSandbox);
307+
await effects.vscode.changeSandbox(forkedSandbox);
308+
effects.vscode.openModule(state.editor.currentModule);
309+
effects.preview.executeCodeImmediately(true);
310+
311+
// When not server we "piggyback" the existing Sandbox to avoid any rerenders and need
312+
// for new bundler. We do not reference the sandbox by `currentId` anywhere,
313+
// so this should be safe. The url of the preview is updated
314+
} else {
315+
Object.assign(
316+
state.editor.sandboxes[state.editor.currentId],
317+
forkedSandbox
318+
);
319+
effects.preview.refreshUrl();
320+
}
321+
303322
effects.notificationToast.success('Forked sandbox!');
304323
effects.router.updateSandboxUrl(forkedSandbox);
305324
} catch (error) {

packages/app/src/app/pages/Sandbox/Editor/Content/Preview/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import BasePreview from '@codesandbox/common/lib/components/Preview';
22
import RunOnClick from '@codesandbox/common/lib/components/RunOnClick';
3+
import { useOvermind } from 'app/overmind';
34
// @flow
45
import React, { FC, useState } from 'react';
5-
import { useOvermind } from 'app/overmind';
66

77
type Props = {
88
hidden?: boolean;
@@ -43,7 +43,7 @@ const PreviewComponent: FC<Props> = props => {
4343

4444
return running ? (
4545
<BasePreview
46-
onInitialized={effects.preview.initializePreview}
46+
onMount={effects.preview.initializePreview}
4747
sandbox={state.editor.currentSandbox}
4848
privacy={state.editor.currentSandbox.privacy}
4949
previewSecret={state.editor.currentSandbox.previewSecret}

packages/common/src/components/Preview/index.tsx

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
import debounce from 'lodash/debounce';
99
import React from 'react';
1010
import { Spring } from 'react-spring/renderprops.cjs';
11+
1112
import { getModulePath } from '../../sandbox/modules';
1213
import getTemplate from '../../templates';
1314
import { generateFileFromSandbox } from '../../templates/configuration/package-json';
@@ -44,6 +45,7 @@ export type Props = {
4445
alignDirection?: 'right' | 'bottom';
4546
delay?: number;
4647
className?: string;
48+
onMount?: (preview: BasePreview) => () => void;
4749
overlayMessage?: string;
4850
/**
4951
* Whether to show a screenshot in the preview as a "placeholder" while loading
@@ -76,6 +78,7 @@ interface IModulesByPath {
7678
class BasePreview extends React.Component<Props, State> {
7779
serverPreview: boolean;
7880
element: HTMLIFrameElement;
81+
onUnmount: () => void;
7982

8083
constructor(props: Props) {
8184
super(props);
@@ -133,6 +136,12 @@ class BasePreview extends React.Component<Props, State> {
133136
}
134137
}
135138

139+
componentDidMount() {
140+
if (this.props.onMount) {
141+
this.onUnmount = this.props.onMount(this);
142+
}
143+
}
144+
136145
/**
137146
* We have a different domain for the preview (currently :id.csb.app), some corporate
138147
* firewalls block calls to these domains. Which is why we ping the domain here, if it
@@ -219,12 +228,18 @@ class BasePreview extends React.Component<Props, State> {
219228
if (this.disposeInitializer) {
220229
this.disposeInitializer();
221230
}
231+
if (this.onUnmount) {
232+
this.onUnmount();
233+
}
222234
}
223235

224236
componentDidUpdate(prevProps: Props) {
225237
if (prevProps.privacy !== this.props.privacy) {
226238
this.handlePrivacyChange();
227239
}
240+
if (prevProps.sandbox.id !== this.props.sandbox.id) {
241+
this.handleSandboxChange();
242+
}
228243
}
229244

230245
openNewWindow = () => {
@@ -246,8 +261,8 @@ class BasePreview extends React.Component<Props, State> {
246261
this.sendPreviewSecret();
247262
};
248263

249-
handleSandboxChange = (sandbox: Sandbox) => {
250-
this.serverPreview = getTemplate(sandbox.template).isServer;
264+
handleSandboxChange = () => {
265+
this.serverPreview = getTemplate(this.props.sandbox.template).isServer;
251266

252267
resetState();
253268

@@ -271,6 +286,16 @@ class BasePreview extends React.Component<Props, State> {
271286
);
272287
};
273288

289+
refreshUrl() {
290+
const url = this.currentUrl();
291+
292+
this.setState({
293+
urlInAddressBar: url,
294+
url,
295+
showScreenshot: false,
296+
});
297+
}
298+
274299
handleDependenciesChange = () => {
275300
this.handleRefresh();
276301
};

0 commit comments

Comments
 (0)