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