Skip to content

Commit 94f6de8

Browse files
committed
Merge branch 'master' into menu-in-access-sheet
2 parents 024d867 + 5ca3fcc commit 94f6de8

File tree

16 files changed

+584
-196
lines changed

16 files changed

+584
-196
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import {
1010
} from '@codesandbox/common/lib/types';
1111
import { getTextOperation } from '@codesandbox/common/lib/utils/diff';
1212
import { COMMENTS } from '@codesandbox/common/lib/utils/feature-flags';
13-
import { hasPermission } from '@codesandbox/common/lib/utils/permission';
1413
import { convertTypeToStatus } from '@codesandbox/common/lib/utils/notifications';
15-
import { NotificationStatus } from '@codesandbox/notifications';
14+
import { hasPermission } from '@codesandbox/common/lib/utils/permission';
1615
import { signInPageUrl } from '@codesandbox/common/lib/utils/url-generator';
16+
import { NotificationStatus } from '@codesandbox/notifications';
1717
import {
1818
Authorization,
1919
CollaboratorFragment,
@@ -472,6 +472,8 @@ export const moduleSelected: Action<
472472
> = ({ actions, effects, state }, { id, path }) => {
473473
effects.analytics.track('Open File');
474474

475+
state.editor.hasLoadedInitialModule = true;
476+
475477
const sandbox = state.editor.currentSandbox;
476478

477479
if (!sandbox) {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,11 @@ type State = {
8484
selectedCommentsFilter: CommentsFilterOption;
8585
currentCommentId: string | null;
8686
currentComment: Derive<State, Comment | null>;
87+
hasLoadedInitialModule: boolean;
8788
};
8889

8990
export const state: State = {
91+
hasLoadedInitialModule: false,
9092
comments: {},
9193
currentCommentId: null, // '5e5961e0c277a40fef1e391b',
9294
currentComment: ({ comments, currentSandbox, currentCommentId }) => {
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import styled, { css, keyframes } from 'styled-components';
2+
3+
const pulse = keyframes`
4+
0% { background-position: 100% 50%; }
5+
100% { background-position: -100% 50%; }
6+
`;
7+
8+
export const SkeletonTextBlock = styled.div(
9+
props => css`
10+
height: 16px;
11+
width: 200px;
12+
animation: ${pulse} 2s linear infinite;
13+
background: linear-gradient(
14+
90deg,
15+
${props.theme.colors?.sideBar.border + '80'} 0%,
16+
${props.theme.colors?.sideBar.border + '80'} 40%,
17+
${props.theme.colors?.sideBar.border + 'd6'} 50%,
18+
${props.theme.colors?.sideBar.border + '80'} 60%,
19+
${props.theme.colors?.sideBar.border + '80'} 100%
20+
);
21+
background-size: 200% 200%;
22+
`
23+
);
24+
25+
export const SkeletonWrapper = styled.div`
26+
position: absolute;
27+
font-family: Inter, sans-serif;
28+
opacity: 1;
29+
transition: opacity 0.5s ease-out;
30+
background-color: ${props =>
31+
props.theme.colors?.editor?.background || 'black'};
32+
width: 100%;
33+
height: 100%;
34+
display: flex;
35+
top: 0;
36+
left: 0;
37+
z-index: 10;
38+
`;
39+
40+
export const SkeletonExplorer = styled.div`
41+
flex: 0 0 272px;
42+
border-right: 1px solid
43+
${props => props.theme.colors?.sideBar.border || 'rgba(0, 0, 0, 0.5)'};
44+
background-color: ${props =>
45+
props.theme.colors?.sideBar.background || 'rgba(0, 0, 0, 0.5)'};
46+
color: ${props => props.theme.colors?.sideBar.foreground || '#ffffff'} + '80';
47+
`;
48+
49+
export const SkeletonEditor = styled.div`
50+
flex: 1;
51+
border-right: 1px solid
52+
${props => props.theme.colors?.sideBar.border || 'rgba(0, 0, 0, 0.5)'};
53+
`;
54+
export const SkeletonEditorTop = styled.div`
55+
height: 34px;
56+
border-bottom: 1px solid
57+
${props => props.theme.colors?.sideBar.border || 'rgba(0, 0, 0, 0.5)'};
58+
`;
59+
export const SkeletonDevtools = styled.div`
60+
flex: 1;
61+
`;
62+
export const SkeletonDevtoolsTop = styled.div`
63+
height: 34px;
64+
`;
65+
export const SkeletonDevtoolsNavigator = styled.div`
66+
height: 34px;
67+
border-bottom: 1px solid
68+
${props => props.theme.colors?.sideBar.border || 'rgba(0, 0, 0, 0.5)'};
69+
`;
70+
export const SkeletonDevtoolsIframe = styled.div`
71+
height: 100%;
72+
background-color: #fff;
73+
`;
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import Navigator from '@codesandbox/common/lib/components/Preview/Navigator';
2+
import { Collapsible, List, ListItem, Stack } from '@codesandbox/components';
3+
import css from '@styled-system/css';
4+
import React from 'react';
5+
6+
import {
7+
SkeletonDevtools,
8+
SkeletonDevtoolsIframe,
9+
SkeletonDevtoolsNavigator,
10+
SkeletonDevtoolsTop,
11+
SkeletonEditor,
12+
SkeletonEditorTop,
13+
SkeletonExplorer,
14+
SkeletonTextBlock,
15+
SkeletonWrapper,
16+
} from './elements';
17+
18+
export const ContentSkeleton = ({ style }) => (
19+
<SkeletonWrapper style={style}>
20+
<SkeletonExplorer>
21+
<SkeletonExplorerContents />
22+
</SkeletonExplorer>
23+
<SkeletonEditor>
24+
<SkeletonEditorTop />
25+
</SkeletonEditor>
26+
<SkeletonDevtools>
27+
<SkeletonDevtoolsTop />
28+
<SkeletonDevtoolsNavigator>
29+
<Navigator
30+
url=""
31+
onChange={() => {}}
32+
onConfirm={() => {}}
33+
onRefresh={() => {}}
34+
isProjectView
35+
/>
36+
</SkeletonDevtoolsNavigator>
37+
<SkeletonDevtoolsIframe />
38+
</SkeletonDevtools>
39+
</SkeletonWrapper>
40+
);
41+
42+
const SkeletonExplorerContents = () => (
43+
<>
44+
<Collapsible title="Files" defaultOpen>
45+
<List>
46+
<File type="folder" />
47+
<File type="folder" />
48+
<File type="file" nested />
49+
<File type="file" nested />
50+
<File type="file" nested />
51+
<File type="file" />
52+
</List>
53+
</Collapsible>
54+
<Collapsible title="Dependencies" defaultOpen>
55+
<List css={{ marginBottom: '32px' }}>
56+
<Dependency />
57+
<Dependency />
58+
<Dependency />
59+
</List>
60+
</Collapsible>
61+
<Collapsible title="External resources" />
62+
</>
63+
);
64+
65+
export const File = props => (
66+
<ListItem
67+
justify="space-between"
68+
align="center"
69+
css={{
70+
minHeight: '28px',
71+
paddingLeft: `calc(${props.nested ? 2 : 1}rem - 2px)`,
72+
}}
73+
{...props}
74+
>
75+
<Stack gap={2} align="center" css={css({ color: 'sideBar.border' })}>
76+
<span style={{ opacity: 0.5 }}>{icons[props.type]}</span>{' '}
77+
<SkeletonTextBlock />
78+
</Stack>
79+
</ListItem>
80+
);
81+
82+
const Dependency = () => (
83+
<ListItem justify="space-between">
84+
<SkeletonTextBlock />
85+
</ListItem>
86+
);
87+
88+
const icons = {
89+
folder: (
90+
<svg
91+
width="16"
92+
height="16"
93+
viewBox="0 0 16 16"
94+
fill="none"
95+
xmlns="http://www.w3.org/2000/svg"
96+
>
97+
<path
98+
d="M6.86667 2L8.33333 3.46667H14.2C15 3.46667 15.6667 4.13333 15.6667 4.93333V12.4C15.6667 13.2 15 13.8667 14.2 13.8667H2.46667C1.66667 14 1 13.3333 1 12.5333V3.46667C1 2.66667 1.66667 2 2.46667 2H6.86667Z"
99+
fill="currentColor"
100+
/>
101+
</svg>
102+
),
103+
file: (
104+
<svg
105+
width="12"
106+
height="12"
107+
viewBox="0 0 12 12"
108+
fill="none"
109+
xmlns="http://www.w3.org/2000/svg"
110+
>
111+
<rect width="12" height="12" rx="2" fill="currentColor" />
112+
</svg>
113+
),
114+
};

packages/app/src/app/pages/Sandbox/Editor/elements.ts

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -14,57 +14,3 @@ export const Container = styled.div`
1414
background-clip: padding-box;
1515
}
1616
`;
17-
18-
export const SkeletonWrapper = styled.div`
19-
position: absolute;
20-
transition: opacity 0.5s ease-out;
21-
opacity: 1;
22-
background-color: ${props =>
23-
props.theme.colors?.editor?.background || 'black'};
24-
width: 100%;
25-
height: 100%;
26-
display: flex;
27-
top: 0;
28-
left: 0;
29-
z-index: 10;
30-
`;
31-
32-
export const SkeletonExplorer = styled.div`
33-
flex: 0 0 272px;
34-
border-right: 1px solid
35-
${props => props.theme.colors?.sideBar.border || 'rgba(0, 0, 0, 0.5)'};
36-
background-color: ${props =>
37-
props.theme.colors?.sideBar.background || 'rgba(0, 0, 0, 0.5)'};
38-
`;
39-
export const SkeletonExplorerTop = styled.div`
40-
height: 35px;
41-
border-bottom: 1px solid
42-
${props =>
43-
props.theme.vscodeTheme.colors.editorGroupHeader?.tabsBackground ||
44-
'rgba(0, 0, 0, 0.5)'};
45-
`;
46-
export const SkeletonEditor = styled.div`
47-
flex: 1;
48-
border-right: 1px solid
49-
${props => props.theme.colors?.sideBar.border || 'rgba(0, 0, 0, 0.5)'};
50-
`;
51-
export const SkeletonEditorTop = styled.div`
52-
height: 35px;
53-
border-bottom: 1px solid
54-
${props => props.theme.colors?.sideBar.border || 'rgba(0, 0, 0, 0.5)'};
55-
`;
56-
export const SkeletonDevtools = styled.div`
57-
flex: 1;
58-
`;
59-
export const SkeletonDevtoolsTop = styled.div`
60-
height: 35px;
61-
`;
62-
export const SkeletonDevtoolsNavigator = styled.div`
63-
height: 35px;
64-
border-bottom: 1px solid
65-
${props => props.theme.colors?.sideBar.border || 'rgba(0, 0, 0, 0.5)'};
66-
`;
67-
export const SkeletonDevtoolsIframe = styled.div`
68-
height: 100%;
69-
background-color: #fff;
70-
`;

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

Lines changed: 26 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import Fullscreen from '@codesandbox/common/lib/components/flex/Fullscreen';
2-
import Navigator from '@codesandbox/common/lib/components/Preview/Navigator';
32
import getTemplateDefinition from '@codesandbox/common/lib/templates';
43
import codesandbox from '@codesandbox/common/lib/themes/codesandbox.json';
54
import { REDESIGNED_SIDEBAR } from '@codesandbox/common/lib/utils/feature-flags';
@@ -11,23 +10,13 @@ import SplitPane from 'react-split-pane';
1110
import styled, { ThemeProvider } from 'styled-components';
1211

1312
import Content from './Content';
14-
import {
15-
Container,
16-
SkeletonDevtools,
17-
SkeletonDevtoolsIframe,
18-
SkeletonDevtoolsNavigator,
19-
SkeletonDevtoolsTop,
20-
SkeletonEditor,
21-
SkeletonEditorTop,
22-
SkeletonExplorer,
23-
SkeletonExplorerTop,
24-
SkeletonWrapper,
25-
} from './elements';
13+
import { Container } from './elements';
2614
import ForkFrozenSandboxModal from './ForkFrozenSandboxModal';
2715
import { Header } from './Header';
2816
import { Header as HeaderOld } from './HeaderOld';
2917
import { Navigation } from './Navigation';
3018
import { Navigation as NavigationOld } from './NavigationOld';
19+
import { ContentSkeleton } from './Skeleton';
3120
import getVSCodeTheme from './utils/get-vscode-theme';
3221
import { Workspace } from './Workspace';
3322

@@ -39,41 +28,8 @@ const StatusBar = styled.div`
3928
}
4029
`;
4130

42-
const ContentSkeleton = ({ style, onTransitionEnd }) => {
43-
React.useEffect(() => {
44-
// In case we started already with opacity 0
45-
if (style.opacity === 0) {
46-
onTransitionEnd();
47-
}
48-
}, [onTransitionEnd, style.opacity]); // eslint-disable-line we don't want to check style on purpose
49-
50-
return (
51-
<SkeletonWrapper style={style} onTransitionEnd={onTransitionEnd}>
52-
<SkeletonExplorer>
53-
<SkeletonExplorerTop />
54-
</SkeletonExplorer>
55-
<SkeletonEditor>
56-
<SkeletonEditorTop />
57-
</SkeletonEditor>
58-
<SkeletonDevtools>
59-
<SkeletonDevtoolsTop />
60-
<SkeletonDevtoolsNavigator>
61-
<Navigator
62-
url=""
63-
onChange={() => {}}
64-
onConfirm={() => {}}
65-
onRefresh={() => {}}
66-
isProjectView
67-
/>
68-
</SkeletonDevtoolsNavigator>
69-
<SkeletonDevtoolsIframe />
70-
</SkeletonDevtools>
71-
</SkeletonWrapper>
72-
);
73-
};
74-
7531
const ContentSplit = () => {
76-
const { state, actions, effects } = useOvermind();
32+
const { state, actions, effects, reaction } = useOvermind();
7733
const statusbarEl = useRef(null);
7834
const [showSkeleton, setShowSkeleton] = useState(true);
7935
const [localState, setLocalState] = useState({
@@ -84,6 +40,20 @@ const ContentSplit = () => {
8440
customVSCodeTheme: null,
8541
});
8642

43+
useEffect(() => {
44+
let timeout;
45+
const dispose = reaction(
46+
reactionState => reactionState.editor.hasLoadedInitialModule,
47+
() => {
48+
timeout = setTimeout(() => setShowSkeleton(false), 500);
49+
}
50+
);
51+
return () => {
52+
dispose();
53+
clearTimeout(timeout);
54+
};
55+
}, [reaction]);
56+
8757
useEffect(() => {
8858
async function loadTheme() {
8959
const vsCodeTheme = state.preferences.settings.customVSCodeTheme;
@@ -201,12 +171,15 @@ const ContentSplit = () => {
201171
{showSkeleton ? (
202172
<NewThemeProvider theme={localState.theme.vscodeTheme}>
203173
<ContentSkeleton
204-
style={{
205-
opacity: state.editor.isLoading ? 1 : 0,
206-
}}
207-
onTransitionEnd={() => {
208-
setShowSkeleton(false);
209-
}}
174+
style={
175+
state.editor.hasLoadedInitialModule
176+
? {
177+
opacity: 0,
178+
}
179+
: {
180+
opacity: 1,
181+
}
182+
}
210183
/>
211184
</NewThemeProvider>
212185
) : null}

0 commit comments

Comments
 (0)