From ef04d805ded32a52aa76afc7d723c9cd7e243633 Mon Sep 17 00:00:00 2001 From: optrader Date: Sat, 15 Nov 2025 22:53:23 +0900 Subject: [PATCH] [251115] fix: DetailPanel FullScreen Size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ๐Ÿ• ์ปค๋ฐ‹ ์‹œ๊ฐ„: 2025. 11. 15. 22:53:23 ๐Ÿ“Š ๋ณ€๊ฒฝ ํ†ต๊ณ„: โ€ข ์ด ํŒŒ์ผ: 6๊ฐœ โ€ข ์ถ”๊ฐ€: +211์ค„ โ€ข ์‚ญ์ œ: -76์ค„ ๐Ÿ“ ์ˆ˜์ •๋œ ํŒŒ์ผ: ~ com.twin.app.shoptime/src/actions/mediaActions.js ~ com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.module.less ~ com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx ~ com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx ~ com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.module.less ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/PlayerOverlayContents.jsx ๐Ÿ”ง ํ•จ์ˆ˜ ๋ณ€๊ฒฝ ๋‚ด์šฉ: ๐Ÿ“„ com.twin.app.shoptime/src/actions/mediaActions.js (javascript): โœ… Added: minimizeModalMedia() ๐Ÿ“„ com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.module.less (unknown): โœ… Added: gradient() โŒ Deleted: gradient() ๐Ÿ“„ com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx (javascript): โœ… Added: handleScrollReset() ๐Ÿ”„ Modified: extractProductMeta() ๐Ÿ“„ com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx (javascript): โœ… Added: attemptRestore() ๐Ÿ”„ Modified: normalizeModalStyle() ๐Ÿ“„ com.twin.app.shoptime/src/views/PlayerPanel/PlayerOverlay/PlayerOverlayContents.jsx (javascript): ๐Ÿ”„ Modified: SpotlightContainerDecorator() ๐Ÿ”ง ์ฃผ์š” ๋ณ€๊ฒฝ ๋‚ด์šฉ: โ€ข ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๊ฐœ์„  โ€ข UI ์ปดํฌ๋„ŒํŠธ ์•„ํ‚คํ…์ฒ˜ ๊ฐœ์„  --- .../src/actions/mediaActions.js | 8 ++ .../VideoPlayer/VideoPlayer.v3.module.less | 89 +++++++++++-------- .../ProductAllSection/ProductAllSection.jsx | 26 ++++++ .../src/views/MediaPanel/MediaPanel.v3.jsx | 67 +++++++++++++- .../MediaPanel/MediaPanel.v3.module.less | 78 ++++++++++------ .../PlayerOverlay/PlayerOverlayContents.jsx | 14 +-- 6 files changed, 211 insertions(+), 71 deletions(-) diff --git a/com.twin.app.shoptime/src/actions/mediaActions.js b/com.twin.app.shoptime/src/actions/mediaActions.js index 9e50c714..ad053994 100644 --- a/com.twin.app.shoptime/src/actions/mediaActions.js +++ b/com.twin.app.shoptime/src/actions/mediaActions.js @@ -284,6 +284,14 @@ export const minimizeModalMedia = () => (dispatch, getState) => { export const restoreModalMedia = () => (dispatch, getState) => { const panels = getState().panels.panels; + if (typeof window !== 'undefined' && window.detailPanelScrollTop !== 0) { + console.log( + '[restoreModalMedia] Blocked restore because detail panel scroll not zero:', + window.detailPanelScrollTop + ); + return; + } + // console.log('[Restore]] ========== Called =========='); // console.log('[Restore] Total panels:', panels.length); // console.log( diff --git a/com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.module.less b/com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.module.less index 57000fb7..d3c91ed5 100644 --- a/com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.module.less +++ b/com.twin.app.shoptime/src/components/VideoPlayer/VideoPlayer.v3.module.less @@ -1,17 +1,19 @@ // VideoPlayer.module.less // -@import "~@enact/sandstone/styles/variables.less"; +@import "~@enact/sandstone/styles/variables.less"; @import "~@enact/sandstone/styles/mixins.less"; @import "~@enact/sandstone/styles/skin.less"; @import "../../style/utils.module.less"; @import "../../style/CommonStyle.module.less"; -.videoPlayer { - // Set by counting the IconButtons inside the side components. - --liftDistance: 0px; - - overflow: hidden; - padding: 2px; - box-sizing: border-box; +.fullscreen .videoPlayer, +.videoPlayer { + // Set by counting the IconButtons inside the side components. + --liftDistance: 0px; + + overflow: hidden; + padding: 2px; + margin: 0; + box-sizing: border-box; :focus { outline: none !important; @@ -19,34 +21,51 @@ box-shadow: none !important; } - .video { - height: calc(100% - 4px); - width: calc(100% - 4px); - background: #000; - } + &.fullscreen { + width: 100%; + height: 100%; + } + + .video { + height: 100%; + width: 100%; + background: #000; + max-width: none; + max-height: none; + } - .media { - height: var(--media-height, calc(100% - 4px)); - width: var(--media-width, calc(100% - 4px)); - background: #000; - - &.mediaBackground { - &:after { - width: 560px; - height: 200px; - position: absolute; - left: 0; - bottom: 0; - content: ""; - background: linear-gradient( - to top, - rgba(255, 255, 255, 1), - transparent - ); - opacity: 0.2; - } - } - } + .media { + height: var(--media-height, calc(100% - 4px)); + width: var(--media-width, calc(100% - 4px)); + background: #000; + + &.mediaBackground { + &:after { + width: 560px; + height: 200px; + position: absolute; + left: 0; + bottom: 0; + content: ""; + background: linear-gradient( + to top, + rgba(255, 255, 255, 1), + transparent + ); + opacity: 0.2; + } + } + } + + &.fullscreen { + --media-width: 100vw; + --media-height: 100vh; + } + + .fullscreen .videoPlayer .media { + --media-width: 100vw; + --media-height: 100vh; + } .preloadVideo { display: none; diff --git a/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx b/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx index 75c5646c..ee18f332 100644 --- a/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx +++ b/com.twin.app.shoptime/src/views/DetailPanel/ProductAllSection/ProductAllSection.jsx @@ -537,6 +537,29 @@ export default function ProductAllSection({ }, []); const scrollContainerRef = useRef(null); + useEffect(() => { + if (typeof window !== 'undefined') { + window.detailPanelScrollTop = 0; + } + }, []); + useEffect(() => { + const handleScrollReset = () => { + const container = scrollContainerRef.current; + if (!container) return; + if (typeof container.scrollTo === 'function') { + container.scrollTo({ top: 0, behavior: 'auto' }); + } else if (typeof container.scrollTop === 'number') { + container.scrollTop = 0; + } + }; + + if (typeof document === 'undefined') return () => {}; + + document.addEventListener('detailpanel-scroll-reset', handleScrollReset); + return () => { + document.removeEventListener('detailpanel-scroll-reset', handleScrollReset); + }; + }, []); const productDetailRef = useRef(null); //๋†’์ด๊ฐ’ ๋ณ€๊ฒฝ๋•Œ๋ฌธ const descriptionRef = useRef(null); const reviewRef = useRef(null); @@ -666,6 +689,9 @@ export default function ProductAllSection({ const handleScroll = useCallback( (e) => { const currentScrollTop = e.scrollTop; + if (typeof window !== 'undefined') { + window.detailPanelScrollTop = Math.max(0, currentScrollTop); + } const prevScrollTop = prevScrollTopRef.current; scrollPositionRef.current = currentScrollTop; diff --git a/com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx b/com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx index 1ae72ccc..60718922 100644 --- a/com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx +++ b/com.twin.app.shoptime/src/views/MediaPanel/MediaPanel.v3.jsx @@ -913,6 +913,7 @@ const MediaPanel = React.forwardRef( if (!panelInfo.modal) { dispatch(PanelActions.popPanel()); dispatch(changeAppStatus({ cursorVisible: false })); + document?.dispatchEvent?.(new CustomEvent('detailpanel-scroll-reset')); //๋”ฎ๋งํฌ๋กœ ํ”Œ๋ ˆ์ด์–ด ์ง„์ž… ํ›„ ์ด์ „๋ฒ„ํŠผ ํด๋ฆญ์‹œ if (panels.length === 1) { @@ -1120,9 +1121,34 @@ const MediaPanel = React.forwardRef( dispatch(minimizeModalMedia()); }, [dispatch]); + const requestDetailScrollReset = useCallback(() => { + if (typeof document !== 'undefined') { + document.dispatchEvent(new CustomEvent('detailpanel-scroll-reset')); + } + }, []); + + const canRestoreFromDetailPanel = useCallback(() => { + if (typeof window === 'undefined') return true; + return window.detailPanelScrollTop === 0; + }, []); + + const restoreWhenScrollZero = useCallback(() => { + let attempts = 0; + const attemptRestore = () => { + if (canRestoreFromDetailPanel()) { + dispatch(restoreModalMedia()); + } else if (attempts < 5) { + attempts += 1; + requestDetailScrollReset(); + setTimeout(attemptRestore, 50); + } + }; + attemptRestore(); + }, [canRestoreFromDetailPanel, dispatch, requestDetailScrollReset]); + const restoreViaRef = useCallback(() => { - dispatch(restoreModalMedia()); - }, [dispatch]); + restoreWhenScrollZero(); + }, [restoreWhenScrollZero]); useImperativeHandle( ref, @@ -1641,7 +1667,9 @@ const MediaPanel = React.forwardRef( setModalStyle({}); setModalScale(1); } else if (isOnTop && !panelInfo.modal && videoPlayer.current) { - console.log('[MediaPanel] Condition 3: Playing fullscreen video'); + console.log( + '[MediaPanel] Condition 3: Playing fullscreen video - enforcing 1920x1080 rendering' + ); if (videoPlayer.current?.getMediaState()?.paused) { videoPlayer.current.play(); } @@ -1652,6 +1680,14 @@ const MediaPanel = React.forwardRef( } }, [panelInfo, isOnTop, dispatch]); + useEffect(() => { + if (!panelInfo.modal) { + console.log('[MediaPanel] modal=false - resetting inline styles for fullscreen'); + setModalStyle({}); + setModalScale(1); + } + }, [panelInfo.modal]); + const smallestOffsetHourIndex = useMemo(() => { if (shopNowInfo) { const filteredVideos = shopNowInfo.filter((video) => video.offsetHour >= currentTime); @@ -2184,6 +2220,7 @@ const MediaPanel = React.forwardRef( const containerClassName = classNames( css.videoContainer, panelInfo.modal && css.modal, + !panelInfo.modal && css.fullscreen, panelInfo.shouldShrinkTo1px && css.shrinkTo1px, // MediaPanel์ด ์ตœ์ƒ๋‹จ ์•„๋‹ˆ๊ณ , ์ตœ์ƒ๋‹จ์ด DetailPanel(from Player)์ด๋ฉด ๋น„๋””์˜ค ๋ณด์ด๋„๋ก !isOnTop && isTopPanelDetailFromPlayer && css['background-visible'], @@ -2192,12 +2229,23 @@ const MediaPanel = React.forwardRef( !captionEnable && css.hideSubtitle ); + const panelStyleOverride = !panelInfo.modal + ? { + width: '100vw', + height: '100vh', + top: 0, + left: 0, + position: 'fixed', + } + : undefined; + return ( {partnerName} - - {showName} - + {!panelInfo?.modal && ( + + {showName} + + )} {type === 'VOD' && disclaimer && (