diff --git a/com.twin.app.shoptime/src/App/App.js b/com.twin.app.shoptime/src/App/App.js index a52e5f09..91e499b9 100644 --- a/com.twin.app.shoptime/src/App/App.js +++ b/com.twin.app.shoptime/src/App/App.js @@ -46,6 +46,7 @@ import { enqueuePanelHistory } from '../actions/panelHistoryActions'; import NotSupportedVersion from '../components/NotSupportedVersion/NotSupportedVersion'; import ToastContainer from '../components/TToast/ToastContainer'; import GlobalPopup from '../components/GlobalPopup/GlobalPopup'; +import FloatingGradientBackground from '../components/FloatingGradientBackground/FloatingGradientBackground'; import usePrevious from '../hooks/usePrevious'; import { lunaTest } from '../lunaSend/lunaTest'; import { store } from '../store/store'; @@ -441,6 +442,9 @@ if (typeof Spotlight !== 'undefined' && Spotlight.addEventListener) { function AppBase(props) { const dispatch = useDispatch(); + + // 그라데이션 배경 표시 상태 관리 (기본적으로 숨김) + const [showGradientBackground, setShowGradientBackground] = React.useState(false); const httpHeader = useSelector((state) => state.common.httpHeader); const httpHeaderRef = useRef(httpHeader); const webOSVersion = useSelector((state) => state.common.appStatus.webOSVersion); @@ -892,8 +896,24 @@ function AppBase(props) { ); }, [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 ( + {/* 항상 메모리에 로드되는 떠 있는 그라데이션 배경 */} + + {webOSVersion === '' ? null : Number(webOSVersion) < 4 ? ( ) : ( diff --git a/com.twin.app.shoptime/src/actions/panelActions.js b/com.twin.app.shoptime/src/actions/panelActions.js index 72bd8d59..e7d492a1 100644 --- a/com.twin.app.shoptime/src/actions/panelActions.js +++ b/com.twin.app.shoptime/src/actions/panelActions.js @@ -103,6 +103,12 @@ export const navigateToDetail = ({ timestamp: Date.now(), }); + // ✅ 그라데이션 배경 표시 - HomePanel→DetailPanel 전환 시 + if (window.showFloatingGradient) { + window.showFloatingGradient(); + console.log('[navigateToDetail] Floating gradient background shown'); + } + // sourceMenu에 따른 사전 처리 switch (sourceMenu) { case SOURCE_MENUS.HOME_BEST_SELLER: diff --git a/com.twin.app.shoptime/src/components/FloatingGradientBackground/FloatingGradientBackground.jsx b/com.twin.app.shoptime/src/components/FloatingGradientBackground/FloatingGradientBackground.jsx new file mode 100644 index 00000000..72066e04 --- /dev/null +++ b/com.twin.app.shoptime/src/components/FloatingGradientBackground/FloatingGradientBackground.jsx @@ -0,0 +1,60 @@ +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 = ( +