From f169de370a52b998abd00442720192087a5e97e6 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Wed, 23 Oct 2019 10:42:25 +0700 Subject: [PATCH] optimized scrolls --- .../containers/BlurWrapper/styles.scss | 6 +- .../containers/CommentWrapper/styles.scss | 1 + src/components/containers/PageCover/index.tsx | 7 +- .../containers/PageCover/styles.scss | 1 + .../EditorUploadCoverButton/styles.scss | 1 + src/components/flow/Cell/styles.scss | 1 + .../flow/HeroPlaceholder/style.scss | 4 +- src/components/main/Header/index.tsx | 6 +- src/components/media/AudioPlayer/index.tsx | 127 ++++++++++-------- src/components/node/Comment/index.tsx | 47 +++---- src/components/node/CommentContent/index.tsx | 6 +- .../node/NodeAudioImageBlock/styles.scss | 1 + 12 files changed, 110 insertions(+), 98 deletions(-) diff --git a/src/components/containers/BlurWrapper/styles.scss b/src/components/containers/BlurWrapper/styles.scss index 253b89c5..b081deff 100644 --- a/src/components/containers/BlurWrapper/styles.scss +++ b/src/components/containers/BlurWrapper/styles.scss @@ -1,7 +1,7 @@ .blur { filter: blur(0); transition: filter 0.25s; - max-height: 100vh; - width: 100vw; - overflow: visible auto; + // max-height: 100vh; + // width: 100vw; + // overflow: visible auto; } diff --git a/src/components/containers/CommentWrapper/styles.scss b/src/components/containers/CommentWrapper/styles.scss index 42897f16..4a8c3e24 100644 --- a/src/components/containers/CommentWrapper/styles.scss +++ b/src/components/containers/CommentWrapper/styles.scss @@ -55,6 +55,7 @@ border-radius: $panel_radius 0 0 $panel_radius; background-size: cover; flex: 0 0 $comment_height; + will-change: transform; @include tablet { height: 32px; diff --git a/src/components/containers/PageCover/index.tsx b/src/components/containers/PageCover/index.tsx index c461a2a8..cf4d05dc 100644 --- a/src/components/containers/PageCover/index.tsx +++ b/src/components/containers/PageCover/index.tsx @@ -1,4 +1,4 @@ -import React, { FC } from 'react'; +import React, { FC, memo } from 'react'; import * as styles from './styles.scss'; import { createPortal } from 'react-dom'; import { selectNode } from '~/redux/node/selectors'; @@ -10,7 +10,7 @@ const mapStateToProps = state => pick(['current_cover_image'], selectNode(state) type IProps = ReturnType & {}; -const PageCoverUnconnected: FC = ({ current_cover_image }) => +const PageCoverUnconnected: FC = memo(({ current_cover_image }) => current_cover_image ? createPortal(
= ({ current_cover_image }) => />, document.body ) - : null; + : null +); const PageCover = connect(mapStateToProps)(PageCoverUnconnected); export { PageCover }; diff --git a/src/components/containers/PageCover/styles.scss b/src/components/containers/PageCover/styles.scss index 2816ba7b..3081fccd 100644 --- a/src/components/containers/PageCover/styles.scss +++ b/src/components/containers/PageCover/styles.scss @@ -17,6 +17,7 @@ width: 100%; height: 100%; animation: fadeIn 2s; + will-change: transform, opacity; &::after { content: ' '; diff --git a/src/components/editors/EditorUploadCoverButton/styles.scss b/src/components/editors/EditorUploadCoverButton/styles.scss index ccb396ec..18237537 100644 --- a/src/components/editors/EditorUploadCoverButton/styles.scss +++ b/src/components/editors/EditorUploadCoverButton/styles.scss @@ -50,6 +50,7 @@ border-radius: ($upload_button_height / 2) !important; background: 50% 50% no-repeat; background-size: cover; + will-change: transform; display: flex; align-items: center; flex-direction: row; diff --git a/src/components/flow/Cell/styles.scss b/src/components/flow/Cell/styles.scss index f9b20df7..6ea16ac5 100644 --- a/src/components/flow/Cell/styles.scss +++ b/src/components/flow/Cell/styles.scss @@ -110,6 +110,7 @@ border-radius: $cell_radius + 2px; opacity: 0; transition: opacity 0.5s; + will-change: transform; & > img { opacity: 0; diff --git a/src/components/flow/HeroPlaceholder/style.scss b/src/components/flow/HeroPlaceholder/style.scss index ae7a9405..9d180bb9 100644 --- a/src/components/flow/HeroPlaceholder/style.scss +++ b/src/components/flow/HeroPlaceholder/style.scss @@ -1,9 +1,11 @@ .container { height: 280px; width: 100%; - background: transparentize(white, 0.9) url("http://37.192.131.144/hero/photos/photo-20140527-1639766.jpg") no-repeat 50% 30%; + background: transparentize(white, 0.9) + url('http://37.192.131.144/hero/photos/photo-20140527-1639766.jpg') no-repeat 50% 30%; background-size: cover; opacity: 0.7; + will-change: transform; //box-shadow: white 0 0 0 1px; //border-radius: $panel_radius $panel_radius 0 0; } diff --git a/src/components/main/Header/index.tsx b/src/components/main/Header/index.tsx index 7f1476c7..89b3aef7 100644 --- a/src/components/main/Header/index.tsx +++ b/src/components/main/Header/index.tsx @@ -1,4 +1,4 @@ -import React, { FC, useCallback } from 'react'; +import React, { FC, useCallback, memo } from 'react'; import { connect } from 'react-redux'; import { push as historyPush } from 'connected-react-router'; import { Link } from 'react-router-dom'; @@ -25,7 +25,7 @@ const mapDispatchToProps = { type IProps = ReturnType & typeof mapDispatchToProps & {}; -const HeaderUnconnected: FC = ({ user: { username, is_user, photo }, showDialog }) => { +const HeaderUnconnected: FC = memo(({ user: { username, is_user, photo }, showDialog }) => { const onLogin = useCallback(() => showDialog(DIALOGS.LOGIN), [showDialog]); return ( @@ -54,7 +54,7 @@ const HeaderUnconnected: FC = ({ user: { username, is_user, photo }, sho )}
); -}; +}); const Header = connect( mapStateToProps, diff --git a/src/components/media/AudioPlayer/index.tsx b/src/components/media/AudioPlayer/index.tsx index 5dcbf462..c5079e63 100644 --- a/src/components/media/AudioPlayer/index.tsx +++ b/src/components/media/AudioPlayer/index.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useState, useEffect } from 'react'; +import React, { useCallback, useState, useEffect, memo } from 'react'; import { connect } from 'react-redux'; import { selectPlayer } from '~/redux/player/selectors'; import * as PLAYER_ACTIONS from '~/redux/player/actions'; @@ -25,76 +25,85 @@ type Props = ReturnType & file: IFile; }; -const AudioPlayerUnconnected = ({ - file, - player: { file: current, status }, +const AudioPlayerUnconnected = memo( + ({ + file, + player: { file: current, status }, + playerSetFileAndPlay, + playerPlay, + playerPause, + playerSeek, + }: Props) => { + const [playing, setPlaying] = useState(false); + const [progress, setProgress] = useState({ + progress: 0, + current: 0, + total: 0, + }); - playerSetFileAndPlay, - playerPlay, - playerPause, - playerSeek, -}: Props) => { - const [playing, setPlaying] = useState(false); - const [progress, setProgress] = useState({ progress: 0, current: 0, total: 0 }); + const onPlay = useCallback(() => { + if (current && current.id === file.id) { + if (status === PLAYER_STATES.PLAYING) return playerPause(); + return playerPlay(); + } - const onPlay = useCallback(() => { - if (current && current.id === file.id) { - if (status === PLAYER_STATES.PLAYING) return playerPause(); - return playerPlay(); - } + playerSetFileAndPlay(file); + }, [file, current, status, playerPlay, playerPause, playerSetFileAndPlay]); - playerSetFileAndPlay(file); - }, [file, current, status, playerPlay, playerPause, playerSetFileAndPlay]); + const onProgress = useCallback( + ({ detail }: { detail: IPlayerProgress }) => { + if (!detail || !detail.total) return; + setProgress(detail); + }, + [setProgress] + ); - const onProgress = useCallback( - ({ detail }: { detail: IPlayerProgress }) => { - if (!detail || !detail.total) return; - setProgress(detail); - }, - [setProgress] - ); + const onSeek = useCallback( + event => { + event.stopPropagation(); + const { clientX, target } = event; + const { left, width } = target.getBoundingClientRect(); + playerSeek((clientX - left) / width); + }, + [playerSeek] + ); - const onSeek = useCallback( - event => { - event.stopPropagation(); - const { clientX, target } = event; - const { left, width } = target.getBoundingClientRect(); - playerSeek((clientX - left) / width); - }, - [playerSeek] - ); + useEffect(() => { + const active = current && current.id === file.id; + setPlaying(current && current.id === file.id); - useEffect(() => { - const active = current && current.id === file.id; - setPlaying(current && current.id === file.id); + if (active) Player.on('playprogress', onProgress); - if (active) Player.on('playprogress', onProgress); + return () => { + if (active) Player.off('playprogress', onProgress); + }; + }, [file, current, setPlaying, onProgress]); - return () => { - if (active) Player.off('playprogress', onProgress); - }; - }, [file, current, setPlaying, onProgress]); + const title = + file.metadata && + (file.metadata.title || + [file.metadata.id3artist, file.metadata.id3title].filter(el => !!el).join(' - ')); - const title = - file.metadata && - (file.metadata.title || - [file.metadata.id3artist, file.metadata.id3title].filter(el => !!el).join(' - ')); + return ( +
+
+ {playing && status === PLAYER_STATES.PLAYING ? ( + + ) : ( + + )} +
+
+
{title || 'Unknown'}
- return ( -
-
- {playing && status === PLAYER_STATES.PLAYING ? : } -
-
-
{title || 'Unknown'}
- -
-
+
+
+
-
- ); -}; + ); + } +); export const AudioPlayer = connect( mapStateToProps, diff --git a/src/components/node/Comment/index.tsx b/src/components/node/Comment/index.tsx index e3b1f3b0..52298ba0 100644 --- a/src/components/node/Comment/index.tsx +++ b/src/components/node/Comment/index.tsx @@ -1,4 +1,4 @@ -import React, { FC, HTMLAttributes } from 'react'; +import React, { FC, HTMLAttributes, memo } from 'react'; import { CommentWrapper } from '~/components/containers/CommentWrapper'; import { ICommentGroup } from '~/redux/types'; import { getURL } from '~/utils/dom'; @@ -12,30 +12,25 @@ type IProps = HTMLAttributes & { is_same?: boolean; }; -const Comment: FC = ({ - comment_group, - is_empty, - is_same, - is_loading, - className, - ...props -}) => { - return ( - -
- {comment_group.comments.map(comment => ( - - ))} -
-
- ); -}; +const Comment: FC = memo( + ({ comment_group, is_empty, is_same, is_loading, className, ...props }) => { + return ( + +
+ {comment_group.comments.map(comment => ( + + ))} +
+
+ ); + } +); export { Comment }; diff --git a/src/components/node/CommentContent/index.tsx b/src/components/node/CommentContent/index.tsx index ed4503cc..cbba18a2 100644 --- a/src/components/node/CommentContent/index.tsx +++ b/src/components/node/CommentContent/index.tsx @@ -1,4 +1,4 @@ -import React, { FC, useMemo } from 'react'; +import React, { FC, useMemo, memo } from 'react'; import { IComment, IFile } from '~/redux/types'; import path from 'ramda/es/path'; import { formatCommentText, getURL, getPrettyDate } from '~/utils/dom'; @@ -15,7 +15,7 @@ interface IProps { comment: IComment; } -const CommentContent: FC = ({ comment }) => { +const CommentContent: FC = memo(({ comment }) => { const groupped = useMemo>( () => reduce( @@ -68,7 +68,7 @@ const CommentContent: FC = ({ comment }) => { )} ); -}; +}); export { CommentContent }; diff --git a/src/components/node/NodeAudioImageBlock/styles.scss b/src/components/node/NodeAudioImageBlock/styles.scss index 8d235c9e..34c81e8a 100644 --- a/src/components/node/NodeAudioImageBlock/styles.scss +++ b/src/components/node/NodeAudioImageBlock/styles.scss @@ -29,4 +29,5 @@ background: no-repeat 50% 30%; background-size: cover; z-index: 1; + will-change: transform; }