[251119] feat: FloatingGradientLayer..Experimental..2
🕐 커밋 시간: 2025. 11. 19. 19:24:28 📊 변경 통계: • 총 파일: 10개 • 추가: +95줄 • 삭제: -181줄 📝 수정된 파일: ~ com.twin.app.shoptime/src/App/App.js ~ com.twin.app.shoptime/src/actions/panelActions.js ~ com.twin.app.shoptime/src/views/DetailPanel/DetailPanel.jsx ~ com.twin.app.shoptime/src/views/DetailPanel/components/DetailPanelBackground/DetailPanelBackground.jsx ~ com.twin.app.shoptime/src/views/HomePanel/HomePanel.jsx ~ com.twin.app.shoptime/src/views/HomePanel/HomePanel.module.less ~ com.twin.app.shoptime/src/views/MainView/MainView.jsx ~ com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx 🗑️ 삭제된 파일: - com.twin.app.shoptime/src/components/FloatingGradientBackground/FloatingGradientBackground.jsx - com.twin.app.shoptime/src/components/FloatingGradientBackground/FloatingGradientBackground.module.less 🔧 주요 변경 내용: • 핵심 비즈니스 로직 개선 • UI 컴포넌트 아키텍처 개선 • 소규모 기능 개선 • 코드 정리 및 최적화 • 모듈 구조 개선 Performance: 코드 최적화로 성능 개선 기대
This commit is contained in:
@@ -46,7 +46,6 @@ import { enqueuePanelHistory } from '../actions/panelHistoryActions';
|
|||||||
import NotSupportedVersion from '../components/NotSupportedVersion/NotSupportedVersion';
|
import NotSupportedVersion from '../components/NotSupportedVersion/NotSupportedVersion';
|
||||||
import ToastContainer from '../components/TToast/ToastContainer';
|
import ToastContainer from '../components/TToast/ToastContainer';
|
||||||
import GlobalPopup from '../components/GlobalPopup/GlobalPopup';
|
import GlobalPopup from '../components/GlobalPopup/GlobalPopup';
|
||||||
import FloatingGradientBackground from '../components/FloatingGradientBackground/FloatingGradientBackground';
|
|
||||||
import usePrevious from '../hooks/usePrevious';
|
import usePrevious from '../hooks/usePrevious';
|
||||||
import { lunaTest } from '../lunaSend/lunaTest';
|
import { lunaTest } from '../lunaSend/lunaTest';
|
||||||
import { store } from '../store/store';
|
import { store } from '../store/store';
|
||||||
@@ -442,9 +441,6 @@ if (typeof Spotlight !== 'undefined' && Spotlight.addEventListener) {
|
|||||||
|
|
||||||
function AppBase(props) {
|
function AppBase(props) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
// 그라데이션 배경 표시 상태 관리 (기본적으로 숨김)
|
|
||||||
const [showGradientBackground, setShowGradientBackground] = React.useState(false);
|
|
||||||
const httpHeader = useSelector((state) => state.common.httpHeader);
|
const httpHeader = useSelector((state) => state.common.httpHeader);
|
||||||
const httpHeaderRef = useRef(httpHeader);
|
const httpHeaderRef = useRef(httpHeader);
|
||||||
const webOSVersion = useSelector((state) => state.common.appStatus.webOSVersion);
|
const webOSVersion = useSelector((state) => state.common.appStatus.webOSVersion);
|
||||||
@@ -896,24 +892,8 @@ function AppBase(props) {
|
|||||||
);
|
);
|
||||||
}, [dispatch, initService]);
|
}, [dispatch, initService]);
|
||||||
|
|
||||||
// ✅ 그라데이션 배경 제어 함수를 전역에 노출
|
|
||||||
useEffect(() => {
|
|
||||||
window.toggleFloatingGradient = setShowGradientBackground;
|
|
||||||
window.showFloatingGradient = () => setShowGradientBackground(true);
|
|
||||||
window.hideFloatingGradient = () => setShowGradientBackground(false);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
delete window.toggleFloatingGradient;
|
|
||||||
delete window.showFloatingGradient;
|
|
||||||
delete window.hideFloatingGradient;
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
{/* 항상 메모리에 로드되는 떠 있는 그라데이션 배경 */}
|
|
||||||
<FloatingGradientBackground visible={showGradientBackground} />
|
|
||||||
|
|
||||||
{webOSVersion === '' ? null : Number(webOSVersion) < 4 ? (
|
{webOSVersion === '' ? null : Number(webOSVersion) < 4 ? (
|
||||||
<NotSupportedVersion />
|
<NotSupportedVersion />
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -104,10 +104,13 @@ export const navigateToDetail = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ✅ 그라데이션 배경 표시 - HomePanel→DetailPanel 전환 시
|
// ✅ 그라데이션 배경 표시 - HomePanel→DetailPanel 전환 시
|
||||||
if (window.showFloatingGradient) {
|
dispatch(updateHomeInfo({
|
||||||
window.showFloatingGradient();
|
name: panel_names.HOME_PANEL,
|
||||||
console.log('[navigateToDetail] Floating gradient background shown');
|
panelInfo: {
|
||||||
}
|
showGradientBackground: true,
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
console.log('[TRACE-GRADIENT] 🟢 navigateToDetail set showGradientBackground: true - source:', sourceMenu);
|
||||||
|
|
||||||
// sourceMenu에 따른 사전 처리
|
// sourceMenu에 따른 사전 처리
|
||||||
switch (sourceMenu) {
|
switch (sourceMenu) {
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
import React, { useCallback, useEffect, useRef } from 'react';
|
|
||||||
import { createPortal } from 'react-dom';
|
|
||||||
|
|
||||||
import css from './FloatingGradientBackground.module.less';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HomePanel과 분리된 별도의 그라데이션 배경
|
|
||||||
* React Portal로 전역 body에 직접 렌더링됨
|
|
||||||
* 항상 메모리에 로드되지만 visible prop으로 표시/숨김 제어
|
|
||||||
*/
|
|
||||||
export default function FloatingGradientBackground({ visible = false }) {
|
|
||||||
// 전역 DOM에 렌더링할 container 참조
|
|
||||||
const containerRef = useRef(null);
|
|
||||||
|
|
||||||
// portal container 생성 (마운트 시 한 번만)
|
|
||||||
useEffect(() => {
|
|
||||||
// body에 직접 div 추가
|
|
||||||
const portalContainer = document.createElement('div');
|
|
||||||
portalContainer.id = 'floating-gradient-background-container';
|
|
||||||
portalContainer.style.position = 'fixed';
|
|
||||||
portalContainer.style.top = '0';
|
|
||||||
portalContainer.style.left = '0';
|
|
||||||
portalContainer.style.width = '100%';
|
|
||||||
portalContainer.style.height = '100%';
|
|
||||||
portalContainer.style.pointerEvents = 'none';
|
|
||||||
portalContainer.style.zIndex = '20'; // HomePanel과 DetailPanel 사이 (HomePanel < 20 < DetailPanel(21))
|
|
||||||
|
|
||||||
document.body.appendChild(portalContainer);
|
|
||||||
containerRef.current = portalContainer;
|
|
||||||
|
|
||||||
console.log('[FloatingGradientBackground] Portal container created');
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
// 언마운트 시 portal container 제거
|
|
||||||
if (containerRef.current && containerRef.current.parentNode) {
|
|
||||||
containerRef.current.parentNode.removeChild(containerRef.current);
|
|
||||||
console.log('[FloatingGradientBackground] Portal container removed');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Portal로 렌더링될 그라데이션 컴포넌트
|
|
||||||
const gradientContent = (
|
|
||||||
<div className={`${css.gradientBackground} ${visible ? css.visible : ''}`} aria-hidden="true">
|
|
||||||
{/* 1. 270도 방향 그라데이션 (왼쪽→오른쪽, 투명→불투명) */}
|
|
||||||
<div className={css.gradientLayer1} />
|
|
||||||
{/* 2. 180도 방향 그라데이션 (위→아래, 투명→불투명) */}
|
|
||||||
<div className={css.gradientLayer2} />
|
|
||||||
{/* 3. 투명 그라데이션 */}
|
|
||||||
<div className={css.gradientLayer3} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
// container가 준비되면 portal로 렌더링
|
|
||||||
if (!containerRef.current) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return createPortal(gradientContent, containerRef.current);
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
@import "../../style/CommonStyle.module.less";
|
|
||||||
@import "../../style/utils.module.less";
|
|
||||||
|
|
||||||
// 그라데이션 배경 - 전역 body에 렌더링됨
|
|
||||||
.gradientBackground {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
pointer-events: none; // 클릭 이벤트가 아래로 통과하도록
|
|
||||||
|
|
||||||
// 기본 상태에서는 숨김
|
|
||||||
display: none;
|
|
||||||
|
|
||||||
// 활성화 상태
|
|
||||||
&.visible {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 그라데이션 레이어 1: 270도 방향 (왼쪽→오른쪽, 투명→불투명)
|
|
||||||
// linear-gradient(270deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.77) 70%, rgba(0, 0, 0, 1) 100%)
|
|
||||||
.gradientLayer1 {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: linear-gradient(
|
|
||||||
270deg,
|
|
||||||
rgba(0, 0, 0, 0) 0%,
|
|
||||||
rgba(0, 0, 0, 0.77) 70%,
|
|
||||||
rgba(0, 0, 0, 1) 100%
|
|
||||||
);
|
|
||||||
z-index: 1; // container 내부 상대적 zIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
// 그라데이션 레이어 2: 180도 방향 (위→아래, 투명→불투명)
|
|
||||||
// linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100%)
|
|
||||||
.gradientLayer2 {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: linear-gradient(
|
|
||||||
180deg,
|
|
||||||
rgba(0, 0, 0, 0) 0%,
|
|
||||||
rgba(0, 0, 0, 1) 100%
|
|
||||||
);
|
|
||||||
z-index: 2; // gradientLayer1보다 높게
|
|
||||||
}
|
|
||||||
|
|
||||||
// 그라데이션 레이어 3: 투명 그라데이션
|
|
||||||
// linear-gradient(0deg, rgba(0, 0, 0, 0))
|
|
||||||
.gradientLayer3 {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: linear-gradient(0deg, rgba(0, 0, 0, 0));
|
|
||||||
z-index: 3; // 가장 높은 레이어
|
|
||||||
}
|
|
||||||
@@ -152,29 +152,37 @@ export default function DetailPanel({ panelInfo, isOnTop, spotlightId }) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// DOM이 렌더링된 후 약간의 지연 시간을 두고 그라데이션 숨김
|
// DOM이 렌더링된 후 약간의 지연 시간을 두고 그라데이션 숨김
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
if (window.hideFloatingGradient) {
|
dispatch(updateHomeInfo({
|
||||||
window.hideFloatingGradient();
|
name: panel_names.HOME_PANEL,
|
||||||
console.log('[DetailPanel] Floating gradient background hidden');
|
panelInfo: {
|
||||||
}
|
showGradientBackground: false,
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
console.log('[TRACE-GRADIENT] 🔴 DetailPanel mounted 100ms timeout set showGradientBackground: false');
|
||||||
}, 100); // 100ms 지연으로 DOM 렌더링 완료 후 실행
|
}, 100); // 100ms 지연으로 DOM 렌더링 완료 후 실행
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
clearTimeout(timer); // 컴포넌트 언마운트 시 타이머 정리
|
clearTimeout(timer); // 컴포넌트 언마운트 시 타이머 정리
|
||||||
|
console.log('[TRACE-GRADIENT] 🔴 DetailPanel unmount - gradient timer cleared');
|
||||||
};
|
};
|
||||||
}, []); // 마운트 시 한 번만 실행
|
}, [dispatch]); // dispatch 포함
|
||||||
|
|
||||||
// ✅ [251118] DetailPanel이 사라질 때 HomePanel의 비디오 재생 활성화
|
// ✅ [251118] DetailPanel이 사라질 때 HomePanel 활성화
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
// DetailPanel이 unmount되는 시점
|
// DetailPanel이 unmount되는 시점
|
||||||
console.log('[DetailPanel] unmount - HomePanel 활성화 신호 전송');
|
console.log('[DetailPanel] unmount - HomePanel 활성화 신호 전송');
|
||||||
|
|
||||||
// HomePanel에서 비디오 재생을 다시 시작하도록 신호 보내기
|
// HomePanel에서 비디오 재생을 다시 시작하도록 신호 보내기
|
||||||
|
console.log('[TRACE-GRADIENT] 🔶 DetailPanel unmount - Creating new panelInfo');
|
||||||
|
console.log('[TRACE-GRADIENT] 🔶 DetailPanel unmount - Existing panelInfo before update:', JSON.stringify(panelInfo));
|
||||||
|
|
||||||
dispatch(updateHomeInfo({
|
dispatch(updateHomeInfo({
|
||||||
name: panel_names.HOME_PANEL,
|
name: panel_names.HOME_PANEL,
|
||||||
panelInfo: {
|
panelInfo: {
|
||||||
shouldResumeVideo: true, // ✅ 신호
|
shouldResumeVideo: true, // ✅ 신호
|
||||||
lastDetailPanelClosed: Date.now(), // ✅ 시점 기록
|
lastDetailPanelClosed: Date.now(), // ✅ 시점 기록
|
||||||
|
showGradientBackground: false, // ✅ 명시적으로 그라데이션 끔기
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,14 +43,9 @@ export default function DetailPanelBackground({ launchedFromPlayer = false, patn
|
|||||||
return BG_MAP[patnrId] || qvc;
|
return BG_MAP[patnrId] || qvc;
|
||||||
}, [patnrId]);
|
}, [patnrId]);
|
||||||
|
|
||||||
// ✅ [251119] 프리로드된 이미지 사용 로직
|
// ✅ [251119] 프리로드된 이미지 사용 로직 수정
|
||||||
|
// launchedFromPlayer와 상관없이 항상 배경 이미지를 표시하도록 수정
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (launchedFromPlayer) {
|
|
||||||
// PlayerPanel에서 진입한 경우 이미지가 필요 없음
|
|
||||||
setImageReady(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 이미지가 프리로드되었는지 확인
|
// 이미지가 프리로드되었는지 확인
|
||||||
if (ImagePreloader.isLoaded(detailPanelBg)) {
|
if (ImagePreloader.isLoaded(detailPanelBg)) {
|
||||||
console.log('[DetailPanelBackground] Using preloaded image:', detailPanelBg);
|
console.log('[DetailPanelBackground] Using preloaded image:', detailPanelBg);
|
||||||
@@ -69,7 +64,7 @@ export default function DetailPanelBackground({ launchedFromPlayer = false, patn
|
|||||||
setImageReady(true);
|
setImageReady(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [detailPanelBg, launchedFromPlayer]);
|
}, [detailPanelBg]); // launchedFromPlayer 제거
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('[DetailPanelBackground] 배경 이미지 경로:', detailPanelBg);
|
console.log('[DetailPanelBackground] 배경 이미지 경로:', detailPanelBg);
|
||||||
@@ -82,15 +77,15 @@ export default function DetailPanelBackground({ launchedFromPlayer = false, patn
|
|||||||
return (
|
return (
|
||||||
<div className={css.backgroundContainer}>
|
<div className={css.backgroundContainer}>
|
||||||
{/* 이미지가 준비되지 않았을 때 placeholder 표시 */}
|
{/* 이미지가 준비되지 않았을 때 placeholder 표시 */}
|
||||||
{!imageReady && !launchedFromPlayer && (
|
{!imageReady && (
|
||||||
<div
|
<div
|
||||||
className={css.backgroundPlaceholder}
|
className={css.backgroundPlaceholder}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 실제 배경 이미지 - 프리로드된 경우 즉시 표시 */}
|
{/* 실제 배경 이미지 - 항상 표시되도록 수정 */}
|
||||||
{!launchedFromPlayer && imageReady && (
|
{imageReady && (
|
||||||
<img
|
<img
|
||||||
src={detailPanelBg}
|
src={detailPanelBg}
|
||||||
alt=""
|
alt=""
|
||||||
@@ -101,7 +96,7 @@ export default function DetailPanelBackground({ launchedFromPlayer = false, patn
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 그라데이션 레이어들 - CSS의 linear-gradient를 div로 구현 */}
|
{/* 그라데이션 레이어들 - launchedFromPlayer일 때만 추가 */}
|
||||||
{/* 1. 270도 방향 그라데이션 (왼쪽→오른쪽, 투명→불투명) */}
|
{/* 1. 270도 방향 그라데이션 (왼쪽→오른쪽, 투명→불투명) */}
|
||||||
{launchedFromPlayer && (
|
{launchedFromPlayer && (
|
||||||
<div className={css.gradientLayer1} aria-hidden="true" />
|
<div className={css.gradientLayer1} aria-hidden="true" />
|
||||||
|
|||||||
@@ -94,9 +94,21 @@ export const TEMPLATE_CODE_CONF = {
|
|||||||
PICK_FOR_YOU: 'DSP00106',
|
PICK_FOR_YOU: 'DSP00106',
|
||||||
};
|
};
|
||||||
|
|
||||||
const HomePanel = ({ isOnTop }) => {
|
const HomePanel = ({ isOnTop, showGradientBackground = false }) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
// ✅ showGradientBackground prop 변경 추적 로그
|
||||||
|
const prevShowGradientBackground = usePrevious(showGradientBackground);
|
||||||
|
useEffect(() => {
|
||||||
|
if (prevShowGradientBackground !== showGradientBackground) {
|
||||||
|
console.log('[TRACE-GRADIENT] 📊 HomePanel prop changed:', {
|
||||||
|
prev: prevShowGradientBackground,
|
||||||
|
current: showGradientBackground,
|
||||||
|
isOnTop: isOnTop
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [showGradientBackground, prevShowGradientBackground, isOnTop]);
|
||||||
|
|
||||||
useDebugKey({ isLandingPage: true });
|
useDebugKey({ isLandingPage: true });
|
||||||
|
|
||||||
// 🔽 HomeBanner 외부 7개 아이콘들의 focusHistory 추적
|
// 🔽 HomeBanner 외부 7개 아이콘들의 focusHistory 추적
|
||||||
@@ -805,7 +817,8 @@ const HomePanel = ({ isOnTop }) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (detailPanelClosedTime && isOnTop) {
|
if (detailPanelClosedTime && isOnTop) {
|
||||||
// if (isOnTop) {
|
// if (isOnTop) {
|
||||||
console.log('@@[HomePanel] *** ✅ HomePanel isOnTop = true');
|
console.log('[TRACE-GRADIENT] 🔄 lastDetailPanelClosed triggered - HomePanel reactivated');
|
||||||
|
console.log('[HomePanel] *** ✅ HomePanel isOnTop = true');
|
||||||
console.log('[HomePanel] *** lastDetailPanelClosed:', detailPanelClosedTime);
|
console.log('[HomePanel] *** lastDetailPanelClosed:', detailPanelClosedTime);
|
||||||
console.log('[HomePanel] *** isOnTop:', isOnTop);
|
console.log('[HomePanel] *** isOnTop:', isOnTop);
|
||||||
console.log('[HomePanel] *** videoPlayIntentRef.current:', videoPlayIntentRef.current);
|
console.log('[HomePanel] *** videoPlayIntentRef.current:', videoPlayIntentRef.current);
|
||||||
@@ -978,6 +991,12 @@ const HomePanel = ({ isOnTop }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{/* HomePanel용 메모리 상주 그라데이션 배경 */}
|
||||||
|
<div
|
||||||
|
className={classNames(css.gradientBackground, { [css.visible]: showGradientBackground })}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
|
||||||
<TPanel className={css.panel} onCancel={onCancel}>
|
<TPanel className={css.panel} onCancel={onCancel}>
|
||||||
{homeLayoutInfo && (
|
{homeLayoutInfo && (
|
||||||
<TBody
|
<TBody
|
||||||
|
|||||||
@@ -53,3 +53,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HomePanel용 메모리 상주 단색 배경
|
||||||
|
.gradientBackground {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 20; // HomePanel 위, DetailPanel(21) 아래
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: none; // 클릭 이벤트가 아래로 통과하도록
|
||||||
|
|
||||||
|
// 기본 상태에서는 숨김
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
// 활성화 상태 - 전체 화면을 어둡게 하는 단색 배경
|
||||||
|
&.visible {
|
||||||
|
display: block;
|
||||||
|
background: rgba(0, 0, 0, 0.85); // 85% 투명도의 검은색으로 전체 화면 어둡게
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ export default function MainView({ className, initService }) {
|
|||||||
const { showLoadingPanel, toast, toastText, isLoading, webOSVersion, deviceId } = useSelector(
|
const { showLoadingPanel, toast, toastText, isLoading, webOSVersion, deviceId } = useSelector(
|
||||||
(state) => state.common.appStatus
|
(state) => state.common.appStatus
|
||||||
);
|
);
|
||||||
|
const homeInfo = useSelector((state) => state.home.homeInfo);
|
||||||
const skipEndOfServicePopup = useSelector((state) => state.localSettings.skipEndOfServicePopup);
|
const skipEndOfServicePopup = useSelector((state) => state.localSettings.skipEndOfServicePopup);
|
||||||
const isInternetConnected = useSelector((state) => state.common.appStatus.isInternetConnected);
|
const isInternetConnected = useSelector((state) => state.common.appStatus.isInternetConnected);
|
||||||
|
|
||||||
@@ -269,7 +270,11 @@ export default function MainView({ className, initService }) {
|
|||||||
(panels[0]?.name === Config.panel_names.PLAYER_PANEL ||
|
(panels[0]?.name === Config.panel_names.PLAYER_PANEL ||
|
||||||
panels[0]?.name === Config.panel_names.PLAYER_PANEL_NEW ||
|
panels[0]?.name === Config.panel_names.PLAYER_PANEL_NEW ||
|
||||||
panels[0]?.name === Config.panel_names.MEDIA_PANEL))) && (
|
panels[0]?.name === Config.panel_names.MEDIA_PANEL))) && (
|
||||||
<HomePanel key={Config.panel_names.HOME_PANEL} isOnTop={isHomeOnTop} />
|
<HomePanel
|
||||||
|
key={Config.panel_names.HOME_PANEL}
|
||||||
|
isOnTop={isHomeOnTop}
|
||||||
|
showGradientBackground={homeInfo?.panelInfo?.showGradientBackground || false}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{renderingPanels.map((panel, index) => {
|
{renderingPanels.map((panel, index) => {
|
||||||
const Component = panelMap[panel.name];
|
const Component = panelMap[panel.name];
|
||||||
@@ -323,11 +328,17 @@ export default function MainView({ className, initService }) {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else if (isHomeOnTop) {
|
} else if (isHomeOnTop) {
|
||||||
return <HomePanel key={Config.panel_names.HOME_PANEL} isOnTop={isHomeOnTop} />;
|
return (
|
||||||
|
<HomePanel
|
||||||
|
key={Config.panel_names.HOME_PANEL}
|
||||||
|
isOnTop={isHomeOnTop}
|
||||||
|
showGradientBackground={homeInfo?.panelInfo?.showGradientBackground || false}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}, [panels, tabActivated, isHomeOnTop]);
|
}, [panels, tabActivated, isHomeOnTop, homeInfo]);
|
||||||
|
|
||||||
const onTabActivated = useCallback((activated) => {
|
const onTabActivated = useCallback((activated) => {
|
||||||
setTabActivated(activated);
|
setTabActivated(activated);
|
||||||
|
|||||||
@@ -2006,15 +2006,17 @@ const MediaPanel = React.forwardRef(
|
|||||||
|
|
||||||
const onEnded = useCallback((e) => {
|
const onEnded = useCallback((e) => {
|
||||||
if (panelInfoRef.current.shptmBanrTpNm === 'MEDIA') {
|
if (panelInfoRef.current.shptmBanrTpNm === 'MEDIA') {
|
||||||
dispatch(
|
// ⚠️ 배경 설정 복원 취소 - DetailPanel 업데이트 없이 바로 패널 제거
|
||||||
updatePanel({
|
// dispatch(
|
||||||
name: panel_names.DETAIL_PANEL,
|
// updatePanel({
|
||||||
panelInfo: {
|
// name: panel_names.DETAIL_PANEL,
|
||||||
launchedFromPlayer: true,
|
// panelInfo: {
|
||||||
isPlayerFinished: true,
|
// launchedFromPlayer: true,
|
||||||
},
|
// isPlayerFinished: true,
|
||||||
})
|
// },
|
||||||
);
|
// })
|
||||||
|
// );
|
||||||
|
console.log('[MediaPanel] 🚫 Skipping background restoration for ended media');
|
||||||
Spotlight.pause();
|
Spotlight.pause();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
Spotlight.resume();
|
Spotlight.resume();
|
||||||
|
|||||||
Reference in New Issue
Block a user