From 9dcb96839b8a205da4e709107be4a543eec66784 Mon Sep 17 00:00:00 2001 From: Himself65 Date: Tue, 11 Apr 2023 23:48:42 -0500 Subject: [PATCH] fix(component): affine loading (#1887) --- .../src/components/pure/loading/Loading.tsx | 20 ---- .../components/pure/loading/PageLoading.tsx | 17 +++- .../web/src/components/pure/loading/index.tsx | 2 +- .../web/src/components/pure/loading/styled.ts | 94 ------------------- .../src/components/affine-loading/index.tsx | 18 +++- .../src/components/internal-lottie/index.tsx | 48 +++++++++- .../src/stories/AffineLoading.stories.tsx | 17 +++- 7 files changed, 91 insertions(+), 125 deletions(-) delete mode 100644 apps/web/src/components/pure/loading/Loading.tsx delete mode 100644 apps/web/src/components/pure/loading/styled.ts diff --git a/apps/web/src/components/pure/loading/Loading.tsx b/apps/web/src/components/pure/loading/Loading.tsx deleted file mode 100644 index 099d50beb1..0000000000 --- a/apps/web/src/components/pure/loading/Loading.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { - StyledLoading, - StyledLoadingItem, - StyledLoadingWrapper, -} from './styled'; - -export const Loading = ({ size = 40 }: { size?: number }) => { - return ( - - - - - - - - - ); -}; - -export default Loading; diff --git a/apps/web/src/components/pure/loading/PageLoading.tsx b/apps/web/src/components/pure/loading/PageLoading.tsx index d01c9ba71c..9a99585071 100644 --- a/apps/web/src/components/pure/loading/PageLoading.tsx +++ b/apps/web/src/components/pure/loading/PageLoading.tsx @@ -1,7 +1,22 @@ import { styled } from '@affine/component'; +import { AffineLoading } from '@affine/component/affine-loading'; import { useTranslation } from '@affine/i18n'; +import { memo, Suspense } from 'react'; -import Loading from './Loading'; +export const Loading = memo(function Loading() { + return ( +
+ + + +
+ ); +}); // Used for the full page loading const StyledLoadingContainer = styled('div')(() => { diff --git a/apps/web/src/components/pure/loading/index.tsx b/apps/web/src/components/pure/loading/index.tsx index 49aaacec80..df9e6fac61 100644 --- a/apps/web/src/components/pure/loading/index.tsx +++ b/apps/web/src/components/pure/loading/index.tsx @@ -1,3 +1,3 @@ -import Loading from './Loading'; +import { Loading } from './PageLoading'; export * from './PageLoading'; export default Loading; diff --git a/apps/web/src/components/pure/loading/styled.ts b/apps/web/src/components/pure/loading/styled.ts deleted file mode 100644 index 7ed7cce7a2..0000000000 --- a/apps/web/src/components/pure/loading/styled.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { styled } from '@affine/component'; - -// Inspired by https://codepen.io/graphilla/pen/rNvBMYY -export const StyledLoadingWrapper = styled('div', { - shouldForwardProp: prop => { - return !['size'].includes(prop as string); - }, -})<{ size?: number }>(({ size = 40 }) => { - return { - width: size * 4, - height: size * 4, - position: 'relative', - }; -}); -export const StyledLoading = styled('div')` - position: absolute; - left: 25%; - top: 50%; - transform: rotateX(55deg) rotateZ(-45deg); - @keyframes slide { - 0% { - transform: translate(var(--sx), var(--sy)); - } - 65% { - transform: translate(var(--ex), var(--sy)); - } - 95%, - 100% { - transform: translate(var(--ex), var(--ey)); - } - } -`; - -export const StyledLoadingItem = styled('div')<{ size: number }>( - ({ size = 40 }) => { - return ` - position: absolute; - width: ${size}px; - height: ${size}px; - background: #9dacf9; - animation: slide 0.9s cubic-bezier(0.65, 0.53, 0.59, 0.93) infinite; - - &::before, - &::after { - content: ''; - position: absolute; - width: 100%; - height: 100%; - } - - &::before { - background: #5260b9; - transform: skew(0deg, -45deg); - right: 100%; - top: 50%; - } - - &::after { - background: #6880ff; - transform: skew(-45deg, 0deg); - top: 100%; - right: 50%; - } - - &:nth-of-type(1) { - --sx: 50%; - --sy: -50%; - --ex: 150%; - --ey: 50%; - } - - &:nth-of-type(2) { - --sx: -50%; - --sy: -50%; - --ex: 50%; - --ey: -50%; - } - - &:nth-of-type(3) { - --sx: 150%; - --sy: 50%; - --ex: 50%; - --ey: 50%; - } - - &:nth-of-type(4) { - --sx: 50%; - --sy: 50%; - --ex: -50%; - --ey: -50%; - } -`; - } -); diff --git a/packages/component/src/components/affine-loading/index.tsx b/packages/component/src/components/affine-loading/index.tsx index 6a98207fb9..aeb5490838 100644 --- a/packages/component/src/components/affine-loading/index.tsx +++ b/packages/component/src/components/affine-loading/index.tsx @@ -1,18 +1,30 @@ import { useTheme } from '@mui/material'; +import type { FC } from 'react'; import { InternalLottie } from '../internal-lottie'; import dark from './loading-black.json'; import light from './loading-white.json'; -export const AffineLoading = () => { +export type AffineLoadingProps = { + loop?: boolean; + autoplay?: boolean; + autoReverse?: boolean; +}; + +export const AffineLoading: FC = ({ + loop = false, + autoplay = false, + autoReverse = false, +}) => { const theme = useTheme(); const isDark = theme.palette.mode === 'dark'; return ( = ({ height, }) => { const element = useRef(null); - const lottieInstance = useRef(); + const lottieInstance = useRef(); const lottie = useAtomValue(lottieAtom); + const directionRef = useRef<1 | -1>(1); useEffect(() => { + const callback = () => { + if (!lottieInstance.current) { + return; + } + const frame = lottieInstance.current.currentFrame.toFixed(0); + if (frame === '1' || frame === '0') { + directionRef.current = 1; + lottieInstance.current.setDirection(directionRef.current); + lottieInstance.current.goToAndStop(0, true); + lottieInstance.current.play(); + } else { + directionRef.current = -1; + lottieInstance.current.setDirection(directionRef.current); + lottieInstance.current.goToAndStop( + lottieInstance.current.totalFrames - 1, + true + ); + lottieInstance.current.play(); + } + }; if (element.current) { - lottieInstance.current = lottie.loadAnimation({ - ...options, - container: element.current, - }); + if (options.autoReverse && options.autoplay) { + lottieInstance.current = lottie.loadAnimation({ + ...options, + autoplay: false, + loop: false, + container: element.current, + }); + } else { + lottieInstance.current = lottie.loadAnimation({ + ...options, + container: element.current, + }); + } + if (options.autoReverse) { + lottieInstance.current.addEventListener('complete', callback); + } } return () => { + if (options.autoReverse) { + lottieInstance.current?.removeEventListener('complete', callback); + } lottieInstance.current?.destroy(); }; }, [lottie, options]); diff --git a/packages/component/src/stories/AffineLoading.stories.tsx b/packages/component/src/stories/AffineLoading.stories.tsx index a551099a98..7f89f101fa 100644 --- a/packages/component/src/stories/AffineLoading.stories.tsx +++ b/packages/component/src/stories/AffineLoading.stories.tsx @@ -7,4 +7,19 @@ export default { component: AffineLoading, }; -export const Default: StoryFn = () => ; +export const Default: StoryFn = ({ width, loop, autoplay, autoReverse }) => ( +
+ +
+); +Default.args = { + width: 100, + loop: true, + autoplay: true, + autoReverse: true, +};