[SHOPTIME-2753] Launching Animation 끊김 현상 수정

원인 : 애니메이션 이미지의 첫프레임과 마지막 프레임을 분리하여 타이밍
별로 3단계 이미징 하는데 마지막 이미지를 표기하는 타이밍이 실제
애니메이션 시간과 맞지 않음
대책: 마지막 이미지는 교체 필요없음. 애니메이션 종료시 마지막 프레임이
표시되므로, 이미지 교체를 2단계로 축소
This commit is contained in:
yonghyon
2024-10-02 12:23:10 +09:00
parent 80fcfe3ed9
commit aaf7d68bb0

View File

@@ -1,45 +1,28 @@
import React, { import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import classNames from 'classnames'; import classNames from "classnames";
import { import { useDispatch, useSelector } from "react-redux";
useDispatch,
useSelector,
} from 'react-redux';
import { Job } from '@enact/core/util'; import { Job } from "@enact/core/util";
import { Panel } from '@enact/sandstone/Panels'; import { Panel } from "@enact/sandstone/Panels";
import Region from '@enact/sandstone/Region'; import Region from "@enact/sandstone/Region";
import Spotlight from '@enact/spotlight'; import Spotlight from "@enact/spotlight";
import Cancelable from '@enact/ui/Cancelable'; import Cancelable from "@enact/ui/Cancelable";
import LoadingPreloadImage import LoadingPreloadImage from "../../../assets/images/intro/splash_02_stop.webp";
from '../../../assets/images/intro/splash_02_stop.webp'; import LoadingAnimation from "../../../assets/images/intro/splash_03_end.webp";
import LoadingAnimation from '../../../assets/images/intro/splash_03_end.webp'; import LoadingCompleteImage from "../../../assets/images/intro/splash_04_end.webp";
import LoadingCompleteImage import LoadingShopOnTvImage from "../../../assets/images/intro/splash_end.jpg";
from '../../../assets/images/intro/splash_04_end.webp'; import { changeAppStatus, loadingComplete } from "../../actions/commonActions";
import LoadingShopOnTvImage from '../../../assets/images/intro/splash_end.jpg'; import CustomImage from "../../components/CustomImage/CustomImage";
import { import Loader from "../../components/Loader/Loader";
changeAppStatus, import PreloadImage from "../../components/PreloadImage/PreloadImage";
loadingComplete, import TPopUp from "../../components/TPopUp/TPopUp";
} from '../../actions/commonActions'; import { $L } from "../../utils/helperMethods";
import CustomImage from '../../components/CustomImage/CustomImage'; import css from "./LoadingPanel.module.less";
import Loader from '../../components/Loader/Loader'; import useWhyDidYouUpdate from "../../hooks/useWhyDidYouUpdate";
import PreloadImage from '../../components/PreloadImage/PreloadImage';
import TPopUp from '../../components/TPopUp/TPopUp';
import { $L } from '../../utils/helperMethods';
import css from './LoadingPanel.module.less';
const loadingImages = [ const loadingImages = [LoadingPreloadImage, LoadingAnimation, LoadingCompleteImage];
LoadingPreloadImage,
LoadingAnimation,
LoadingCompleteImage,
];
const MIN_SHOWING_TIME = { launching: 4500, wait: 300, default: 1000 }; const MIN_SHOWING_TIME = { launching: 4500, wait: 300, default: 1000 };
const MAX_SHOWING_TIME = 60000; const MAX_SHOWING_TIME = 60000;
@@ -47,32 +30,29 @@ const MAX_SHOWING_TIME_UNLIMITED = Number.MAX_SAFE_INTEGER;
const DUMMY_DELAY = 1000; const DUMMY_DELAY = 1000;
const HIDING_TIME = 300; const HIDING_TIME = 300;
const CancelablePanel = Cancelable( const CancelablePanel = Cancelable({ modal: true, onCancel: "handleCancel" }, Panel);
{ modal: true, onCancel: "handleCancel" },
Panel
);
let minShowingTimeJob, hidingJob, maxShowingTimeJob; let minShowingTimeJob, hidingJob, maxShowingTimeJob;
export default function LoadingPanel({ showLoadingPanel, ...rest }) { export default function LoadingPanel({ showLoadingPanel, ...rest }) {
const { USE_STATE, USE_SELECTOR } = useWhyDidYouUpdate("LoadingPanel", {
showLoadingPanel,
...rest,
});
const dispatch = useDispatch(); const dispatch = useDispatch();
const [showingStatus, setShowingStatus] = useState({ const [showingStatus, setShowingStatus] = USE_STATE("showingStatus", {
showing: true, showing: true,
hiding: false, hiding: false,
}); });
const [loadingSign, setLoadingSign] = useState(""); const [loadingType, setLoadingType] = USE_STATE("loadingType", "wait");
const [loadingType, setLoadingType] = useState("wait"); const [readyToAni, setReadyToAni] = USE_STATE("readyToAni", false);
const [loadingImage, setLoadingImage] = useState(""); const [readyToHide, setReadyToHide] = USE_STATE("readyToHide", false);
const [readyToAni, setReadyToAni] = useState(false);
const [readyToHide, setReadyToHide] = useState(false);
const [loadingStep, setLoadingStep] = useState(0); const [loadingStep, setLoadingStep] = USE_STATE("loadingStep", 0);
const [isVisible, setIsVisible] = useState(false); const [isVisible, setIsVisible] = USE_STATE("isVisible", false);
const webOSVersion = useSelector( const webOSVersion = USE_SELECTOR("webOSVersion", (state) => state.common.appStatus?.webOSVersion);
(state) => state.common.appStatus?.webOSVersion
);
const httpHeader = useSelector((state) => state.common.httpHeader); const httpHeader = USE_SELECTOR("httpHeader", (state) => state.common.httpHeader);
const deviceCountryCode = httpHeader?.["X-Device-Country"] || ""; const deviceCountryCode = httpHeader?.["X-Device-Country"] || "";
const resumeSpotlightTimeoutRef = useRef(null); const resumeSpotlightTimeoutRef = useRef(null);
@@ -126,6 +106,7 @@ export default function LoadingPanel({ showLoadingPanel, ...rest }) {
} else { } else {
setReadyToHide(false); setReadyToHide(false);
setReadyToAni(false); setReadyToAni(false);
minShowingTimeJob && minShowingTimeJob.stop(); minShowingTimeJob && minShowingTimeJob.stop();
hidingJob && hidingJob.stop(); hidingJob && hidingJob.stop();
maxShowingTimeJob && maxShowingTimeJob.stop(); maxShowingTimeJob && maxShowingTimeJob.stop();
@@ -156,39 +137,13 @@ export default function LoadingPanel({ showLoadingPanel, ...rest }) {
useEffect(() => { useEffect(() => {
if (showLoadingPanel.show) { if (showLoadingPanel.show) {
if (!maxShowingTimeJob) { if (!maxShowingTimeJob) {
maxShowingTimeJob = new Job( maxShowingTimeJob = new Job(() => {
() => { setShowingStatus({ showing: false, hiding: true });
setShowingStatus({ showing: false, hiding: true }); });
},
showLoadingPanel.type === "wait"
? MAX_SHOWING_TIME_UNLIMITED
: MAX_SHOWING_TIME
);
} }
maxShowingTimeJob.startAfter(showLoadingPanel.type === "wait" ? MAX_SHOWING_TIME_UNLIMITED : MAX_SHOWING_TIME);
maxShowingTimeJob.start();
setShowingStatus({ showing: true, hiding: false }); setShowingStatus({ showing: true, hiding: false });
let signText = "",
img = "";
switch (showLoadingPanel.type) {
case "launching": {
signText = $L("Loading");
img = LoadingAnimation;
break;
}
case "wait": {
signText = $L("Please wait");
img = LoadingAnimation;
break;
}
}
setLoadingSign(signText);
setLoadingImage(img);
setLoadingType(showLoadingPanel.type); setLoadingType(showLoadingPanel.type);
} }
}, [showLoadingPanel]); }, [showLoadingPanel]);
@@ -232,14 +187,11 @@ export default function LoadingPanel({ showLoadingPanel, ...rest }) {
useEffect(() => { useEffect(() => {
let timer; let timer;
if (isVisible) { if (isVisible) {
if (loadingStep < 2) { if (loadingStep < 1) {
timer = setTimeout( timer = setTimeout(() => {
() => { setIsVisible(false); // 다음 이미지를 로드하기 전에 숨김
setIsVisible(false); // 다음 이미지를 로드하기 전에 숨김 setLoadingStep((prevStep) => prevStep + 1);
setLoadingStep((prevStep) => prevStep + 1); }, 1000);
},
loadingStep === 0 ? 1000 : loadingStep === 1 ? 1500 : 2000
);
} else { } else {
return; return;
} }
@@ -247,11 +199,6 @@ export default function LoadingPanel({ showLoadingPanel, ...rest }) {
return () => clearTimeout(timer); return () => clearTimeout(timer);
}, [isVisible, loadingStep]); }, [isVisible, loadingStep]);
// const getImageSrc = () => {
// if (webOSVersion && Number(webOSVersion) < 5) return LoadingCompleteImage;
// else return loadingImages[loadingStep];
// };
const renderImages = useCallback(() => { const renderImages = useCallback(() => {
switch (loadingType) { switch (loadingType) {
case "launching": case "launching":
@@ -265,14 +212,9 @@ export default function LoadingPanel({ showLoadingPanel, ...rest }) {
alt="Loading Image" alt="Loading Image"
/> />
) : webOSVersion && Number(webOSVersion) < 5 ? ( // webOs5.0 미만 loading image ) : webOSVersion && Number(webOSVersion) < 5 ? ( // webOs5.0 미만 loading image
<img <img className={css.fullpageImage} src={LoadingCompleteImage} onLoad={handleLoad} alt="Loading Image" />
className={css.fullpageImage}
src={LoadingCompleteImage}
onLoad={handleLoad}
alt="Loading Image"
/>
) : ( ) : (
loadingStep < 3 && ( // normal loading image loadingStep < 2 && ( // normal loading image
<img <img
className={css.fullpageImage} className={css.fullpageImage}
src={loadingImages[loadingStep]} src={loadingImages[loadingStep]}
@@ -295,23 +237,13 @@ export default function LoadingPanel({ showLoadingPanel, ...rest }) {
} }
}, [loadingType, loadingStep, deviceCountryCode, webOSVersion]); }, [loadingType, loadingStep, deviceCountryCode, webOSVersion]);
const hidingStyle = showingStatus.hiding const hidingStyle = showingStatus.hiding ? { transition: "opacity " + HIDING_TIME + "ms ease", opacity: 0 } : {};
? { transition: "opacity " + HIDING_TIME + "ms ease", opacity: 0 }
: {};
if (showingStatus.showing || showingStatus.hiding) { if (showingStatus.showing || showingStatus.hiding) {
return ( return (
<Region title={"LG Shoptime logo"} aria-label="LG Shoptime logo"> <Region title={"LG Shoptime logo"} aria-label="LG Shoptime logo">
<CancelablePanel <CancelablePanel {...rest} className={css.panel} style={hidingStyle} handleCancel={handleCancel}>
{...rest} <PreloadImage preloadImages={loadingImages} onLoadComplete={onPreImageLoadComplete} />
className={css.panel}
style={hidingStyle}
handleCancel={handleCancel}
>
<PreloadImage
preloadImages={[loadingImage]}
onLoadComplete={onPreImageLoadComplete}
/>
{readyToAni && ( {readyToAni && (
<div <div
className={classNames( className={classNames(