Skip to content

Commit

Permalink
feat: skeleton animation when fetching files (closes #63)
Browse files Browse the repository at this point in the history
  • Loading branch information
xnerhu committed Feb 21, 2020
1 parent c629f80 commit 925c3d5
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 27 deletions.
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"@types/gsap": "1.20.2",
"@types/keytar": "^4.4.2",
"@types/knex": "^0.16.1",
"@types/node": "^13.7.4",
"@types/pretty-bytes": "^5.2.0",
"@types/react": "16.9.21",
"@types/react-dom": "16.9.5",
Expand Down
1 change: 0 additions & 1 deletion src/renderer/app/components/File/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ export const StyledFile = styled.div`
display: flex;
align-items: center;
flex-direction: column;
background-color: rgba(0, 0, 0, 0.04);
&.selected {
background-color: rgba(98, 0, 234, 0.08);
Expand Down
23 changes: 15 additions & 8 deletions src/renderer/app/components/Page/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import React from 'react';
import { observer } from 'mobx-react-lite';
import { Selectable } from 'rectangle-selection';
import { IFile } from 'qusly-core';

import store from '../../store';
import { File } from '../File';
import { DragDrop, Droppable } from '~/renderer/components/FileDragDrop';
import { StyledPage } from './style';
import {
Skeleton,
SkeletonCircle,
SkeletonText,
} from '~/renderer/components/Skeleton';
import { IFile } from '~/renderer/interfaces';
import { FilesSkeleton } from '~/renderer/components/FilesSkeleton';
import { StyledPage, Grid } from './style';

const Button = observer(({ path }: { path: string }) => {
const page = store.pages.current;
Expand Down Expand Up @@ -41,12 +42,18 @@ export const Page = observer(() => {
}, []);

return (
<StyledPage onSelection={onSelection} onMouseDown={onMouseDown}>
{page?.files.list.map(r => (
<Selectable key={r.name} data={r}>
{innerRef => <File ref={innerRef} data={r} />}
</Selectable>
))}
<StyledPage>
{page?.loading === false ? (
<Grid onSelection={onSelection} onMouseDown={onMouseDown}>
{page?.files.list.map(r => (
<Selectable key={r.name} data={r}>
{innerRef => <File ref={innerRef} data={r} />}
</Selectable>
))}
</Grid>
) : (
<FilesSkeleton />
)}
</StyledPage>
);
});
Expand Down
16 changes: 12 additions & 4 deletions src/renderer/app/components/Page/style.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import styled from 'styled-components';
import styled, { css, keyframes } from 'styled-components';
import { SelectionArea } from 'rectangle-selection';

import { APPBAR_HEIGHT, FILE_HEIGHT } from '../../constants';

export const StyledPage = styled(SelectionArea)`
export const StyledPage = styled.div`
width: 100%;
height: calc(100% - ${APPBAR_HEIGHT}px);
overflow-y: auto;
`;

export const StyledPageGridBase = css`
width: 100%;
height: 100%;
display: grid;
grid-gap: 16px;
grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
grid-template-rows: 1fr;
grid-template-rows: repeat(auto-fill, ${FILE_HEIGHT}px);
background-color: rgba(0, 0, 0, 0.12);
`;

export const Grid = styled(SelectionArea)`
overflow-y: auto;
${StyledPageGridBase};
`;
9 changes: 0 additions & 9 deletions src/renderer/app/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,4 @@ export const Style = css`
* {
box-sizing: border-box;
}
@keyframes skeleton-animation {
0% {
left: -100%;
}
100% {
left: 100%;
}
}
`;
51 changes: 51 additions & 0 deletions src/renderer/components/FilesSkeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';

import { StyledFile } from '~/renderer/app/components/File/style';
import { SkeletonCircle, SkeletonText } from '../Skeleton';
import { getRandomNumber } from '~/renderer/utils';
import { StyledFilesSkeleton, ANIMATION_TIME } from './style';

const Item = () => {
return (
<StyledFile>
<SkeletonCircle style={{ width: 48, height: 48, margin: '8px 0px' }} />
<SkeletonText style={{ height: 16, borderRadius: 4 }} />
</StyledFile>
);
};

export const FilesSkeleton = () => {
const [count, setCount] = React.useState(0);
const ref = React.useRef<HTMLDivElement>();

const timeout = React.useRef<NodeJS.Timeout>();

const onTimeout = React.useCallback(() => {
if (!ref.current) return;

ref.current.style.display = 'none';

setCount(getRandomNumber(10, 30));

requestAnimationFrame(() => {
ref.current.style.display = 'grid';
setTimeout(onTimeout, ANIMATION_TIME);
});
}, []);

React.useEffect(() => {
setTimeout(onTimeout);

return () => {
clearTimeout(timeout.current);
};
}, []);

return (
<StyledFilesSkeleton ref={ref}>
{[...Array(count).keys()].map((_, index) => (
<Item key={index} />
))}
</StyledFilesSkeleton>
);
};
26 changes: 26 additions & 0 deletions src/renderer/components/FilesSkeleton/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import styled, { keyframes } from 'styled-components';

import { EASING_FUNCTION } from '~/renderer/app/constants';
import { StyledPageGridBase } from '~/renderer/app/components/Page/style';

export const ANIMATION_TIME = 1600;

const animation = keyframes`
0% {
opacity: 0;
transform: translateY(64px);
}
25%, 80% {
opacity: 1;
transform: translateY(0px);
}
100% {
opacity: 0;
}
`;

export const StyledFilesSkeleton = styled.div`
overflow: hidden;
animation: ${animation} ${ANIMATION_TIME}ms ${EASING_FUNCTION} infinite;
${StyledPageGridBase};
`;
13 changes: 11 additions & 2 deletions src/renderer/components/Skeleton/style.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import styled from 'styled-components';
import styled, { keyframes } from 'styled-components';

const animation = keyframes`
0% {
left: -100%;
}
100% {
left: 100%;
}
`;

export const Skeleton = styled.div`
border-radius: 8px;
Expand All @@ -14,7 +23,7 @@ export const Skeleton = styled.div`
top: 0;
left: -100%;
position: absolute;
animation: skeleton-animation 1.5s ease-in-out infinite;
animation: ${animation} 1.5s ease-in-out infinite;
background-image: linear-gradient(
90deg,
rgba(255, 255, 255, 0),
Expand Down

0 comments on commit 925c3d5

Please sign in to comment.