From f24facb68414bbd16de97c92813d30e1329d7eb2 Mon Sep 17 00:00:00 2001 From: Zoia <43918051+zizi62@users.noreply.github.com> Date: Wed, 13 Jan 2021 07:20:42 -0500 Subject: [PATCH] Ott 704 photo preloader (#273) --- src/features/Common/Image/index.tsx | 26 +++++++++++++++- .../components/PlayersList/index.tsx | 31 ++++++++++++++++++- .../components/PlayersList/styled.tsx | 20 +++++++++++- src/features/ProfileLogo/index.tsx | 8 +++++ 4 files changed, 82 insertions(+), 3 deletions(-) diff --git a/src/features/Common/Image/index.tsx b/src/features/Common/Image/index.tsx index 8fb790ee..b1e87936 100644 --- a/src/features/Common/Image/index.tsx +++ b/src/features/Common/Image/index.tsx @@ -1,5 +1,11 @@ import type { BaseSyntheticEvent } from 'react' -import { useCallback } from 'react' +import { + RefObject, + useCallback, + useEffect, + useRef, + useState, +} from 'react' import styled from 'styled-components/macro' @@ -10,6 +16,8 @@ type Props = { className?: string, dataSrc?: string, fallbackSrc?: string, + imagesList?: Array>, + setImagesList?: (imagesList: Array>) => void, src: string, title?: string, } @@ -19,9 +27,23 @@ export const Image = ({ className, dataSrc, fallbackSrc, + imagesList = [], + setImagesList, src, title, }: Props) => { + const imgRef = useRef(null) + const [loaded, setLoaded] = useState(false) + + useEffect( + () => { + if (!setImagesList || !loaded) return + setImagesList([...imagesList, imgRef]) + }, + // eslint-disable-next-line + [loaded], + ) + const onError = useCallback((e: BaseSyntheticEvent) => { // eslint-disable-next-line no-param-reassign e.target.onError = '' @@ -36,6 +58,8 @@ export const Image = ({ data-src={dataSrc} className={className} onError={onError} + onLoad={() => setLoaded(true)} + ref={imgRef} title={title} /> ) diff --git a/src/features/MatchPopup/components/PlayersList/index.tsx b/src/features/MatchPopup/components/PlayersList/index.tsx index 06bcc3c8..0f5e5245 100644 --- a/src/features/MatchPopup/components/PlayersList/index.tsx +++ b/src/features/MatchPopup/components/PlayersList/index.tsx @@ -1,13 +1,22 @@ +import React, { + RefObject, + useEffect, + useState, +} from 'react' + import map from 'lodash/map' +import size from 'lodash/size' import { ProfileTypes, SportTypes } from 'config' import { PlayerPlaylistOptions, PlayerPlaylistOption } from 'features/MatchPage/types' import { useMatchPopupStore } from 'features/MatchPopup/store' +import { Loader } from 'features/Loader' import { Teams } from '../../types' import { List, + LoaderWrapper, Item, Logo, PlayerName, @@ -28,19 +37,39 @@ export const PlayersList = ({ team, }: Props) => { const { match } = useMatchPopupStore() + const [imagesList, setImagesList] = useState< + Array> + >([]) + + const [allImagesReady, setAllImagesReady] = useState(false) + + useEffect(() => { + if (size(imagesList) === size(players)) { + setAllImagesReady(true) + } + }, [imagesList, players]) + if (!match) return null return ( + {!allImagesReady + && ( + + + + )} { map(players, (player) => ( - + diff --git a/src/features/MatchPopup/components/PlayersList/styled.tsx b/src/features/MatchPopup/components/PlayersList/styled.tsx index e42ef882..eb2617e6 100644 --- a/src/features/MatchPopup/components/PlayersList/styled.tsx +++ b/src/features/MatchPopup/components/PlayersList/styled.tsx @@ -11,6 +11,18 @@ type ListProps = { team: Teams, } +type ItemProps = { + isReady?: boolean, +} + +export const LoaderWrapper = styled.div` + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +` + export const List = styled.ul` width: calc((100% - 30px) / 2); display: flex; @@ -29,10 +41,16 @@ export const List = styled.ul` } ` -export const Item = styled.li` +export const Item = styled.li` width: 76px; height: 95px; margin: 10px; + transition: .3s; + opacity: ${({ isReady }) => ( + isReady + ? '1' + : '0' + )}; @media ${devices.mobile} { width: 100%; diff --git a/src/features/ProfileLogo/index.tsx b/src/features/ProfileLogo/index.tsx index 517f759d..42952c20 100644 --- a/src/features/ProfileLogo/index.tsx +++ b/src/features/ProfileLogo/index.tsx @@ -1,3 +1,5 @@ +import { RefObject } from 'react' + import { ProfileTypes, SportTypes } from 'config' import { getProfileFallbackLogo, getProfileLogo } from 'helpers' @@ -10,10 +12,12 @@ type ProfileImageProps = { altNameObj?: ObjectWithName, className?: string, id: number, + imagesList?: Array>, lazy?: boolean, nameAsTitle?: boolean, prefix?: string, profileType: ProfileTypes, + setImagesList?: (imagesList: Array>) => void, size?: number, sportType: SportTypes, title?: string, @@ -24,10 +28,12 @@ export const ProfileLogo = ({ altNameObj, className, id, + imagesList, lazy = false, nameAsTitle, prefix, profileType, + setImagesList, size, sportType, title, @@ -52,6 +58,8 @@ export const ProfileLogo = ({ dataSrc={lazy ? src : ''} fallbackSrc={fallbackSrc} className={className} + imagesList={imagesList} + setImagesList={setImagesList} title={titleText} /> )