From 2cffe6f0a97a7de358e61d8d56c3655273fcb7dd Mon Sep 17 00:00:00 2001 From: optrader Date: Wed, 19 Nov 2025 05:41:53 +0900 Subject: [PATCH] [251119] fix: VideoPlayer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit πŸ• 컀밋 μ‹œκ°„: 2025. 11. 19. 05:41:52 πŸ“Š λ³€κ²½ 톡계: β€’ 총 파일: 4개 β€’ μΆ”κ°€: +28쀄 β€’ μ‚­μ œ: -14쀄 πŸ“ μˆ˜μ •λœ 파일: ~ com.twin.app.shoptime/src/actions/playActions.js ~ com.twin.app.shoptime/src/components/VideoPlayer/TReactPlayer.jsx ~ com.twin.app.shoptime/src/hooks/useVideoPlay/useVideoPlay.js ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less πŸ”§ μ£Όμš” λ³€κ²½ λ‚΄μš©: β€’ 핡심 λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 κ°œμ„  β€’ UI μ»΄ν¬λ„ŒνŠΈ μ•„ν‚€ν…μ²˜ κ°œμ„  β€’ μ†Œκ·œλͺ¨ κΈ°λŠ₯ κ°œμ„  --- .../src/actions/playActions.js | 10 +++++++--- .../src/components/VideoPlayer/TReactPlayer.jsx | 10 ++++++++-- .../src/hooks/useVideoPlay/useVideoPlay.js | 17 ++++++++++++----- .../v2/LiveChannelNext.module.less | 5 +---- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/com.twin.app.shoptime/src/actions/playActions.js b/com.twin.app.shoptime/src/actions/playActions.js index 5bcd54a0..9e902a26 100644 --- a/com.twin.app.shoptime/src/actions/playActions.js +++ b/com.twin.app.shoptime/src/actions/playActions.js @@ -186,20 +186,24 @@ export const startVideoPlayerNew = console.log('[startVideoPlayerNew] *** πŸ“‹ Current PLAYER_PANEL panelInfo:', topPanel.panelInfo); } - // 쀑볡 μ‹€ν–‰ λ°©μ§€: 같은 λ°°λ„ˆ + 같은 modal μƒνƒœ/μ»¨ν…Œμ΄λ„ˆλ©΄ skip + // 쀑볡 μ‹€ν–‰ λ°©μ§€: 같은 λ°°λ„ˆ + 같은 modal μƒνƒœ/μ»¨ν…Œμ΄λ„ˆ + 같은 URL이면 skip const currentPanelInfo = topPanel?.panelInfo || {}; const currentPlayerState = currentPanelInfo.playerState || {}; const isSameBanner = currentPlayerState.currentBannerId === bannerId; const isSameModalType = currentPanelInfo.modal === modal; const isSameContainer = currentPanelInfo.modalContainerId === modalContainerId; + const isSameShowUrl = currentPanelInfo.showUrl === showUrl; + const isSameVideoId = currentPanelInfo.videoId === videoId; - console.log('[startVideoPlayerNew] *** πŸ” Duplicate check - isSameBanner:', isSameBanner, ', isSameModalType:', isSameModalType, ', isSameContainer:', isSameContainer); + console.log('[startVideoPlayerNew] *** πŸ” Duplicate check - isSameBanner:', isSameBanner, ', isSameModalType:', isSameModalType, ', isSameContainer:', isSameContainer, ', isSameShowUrl:', isSameShowUrl, ', isSameVideoId:', isSameVideoId); - if (isSameBanner && isSameModalType && isSameContainer) { + if (isSameBanner && isSameModalType && isSameContainer && isSameShowUrl && isSameVideoId) { console.log('[startVideoPlayerNew] *** ⏭️ SKIPPED - λ™μΌν•œ μš”μ²­', { bannerId, modal, modalContainerId, + showUrl, + videoId, }); return; } diff --git a/com.twin.app.shoptime/src/components/VideoPlayer/TReactPlayer.jsx b/com.twin.app.shoptime/src/components/VideoPlayer/TReactPlayer.jsx index 245632bb..15392dcc 100644 --- a/com.twin.app.shoptime/src/components/VideoPlayer/TReactPlayer.jsx +++ b/com.twin.app.shoptime/src/components/VideoPlayer/TReactPlayer.jsx @@ -27,6 +27,10 @@ export default function TReactPlayer({ }) { const playerRef = useRef(null); + // πŸ”½ [μ΅œμ ν™”] handleEvent의 μ£Όμš” μ˜μ‘΄μ„± μΆ”μΆœ + const playing = rest?.playing; + const config = rest?.config; + const handleEvent = useCallback( (type) => (ev) => { if (type === 'onReady') { @@ -131,7 +135,7 @@ export default function TReactPlayer({ } handle.forward('onUpdate', { type, ev }, rest); }, - [videoRef] + [videoRef, playing, config] // βœ… μ£Όμš” μ˜μ‘΄μ„± μΆ”κ°€ ); const handledMediaEvents = useMemo(() => { @@ -143,16 +147,18 @@ export default function TReactPlayer({ return events; }, [handleEvent, mediaEventsMap]); + // πŸ”½ [μ΅œμ ν™”] URL λ³€κ²½ λ˜λŠ” μ–Έλ§ˆμš΄νŠΈ μ‹œ 이전 λΉ„λ””μ˜€ 정리 (λ©”λͺ¨λ¦¬ λˆ„μˆ˜ λ°©μ§€) useEffect(() => { return () => { const videoNode = playerRef.current?.getInternalPlayer(); if (videoNode && videoNode.pause) { + console.log('[VIDEO-DEBUG] 🧹 λΉ„λ””μ˜€ 정리 (URL λ³€κ²½ λ˜λŠ” μ–Έλ§ˆμš΄νŠΈ)'); videoNode.pause(); videoNode.src = ''; videoNode.srcObject = null; } }; - }, []); + }, [url]); // βœ… URL λ³€κ²½ μ‹œμ—λ„ 정리 둜직 μ‹€ν–‰ return ( { const isPlaying = currentOwnerId && currentOwnerId.endsWith('_player'); const currentBanner = currentOwnerId ? currentOwnerId.replace('_player', '') : null; + // πŸ”½ [μ΅œμ ν™”] λ°°λ„ˆ κ°€μš©μ„± λ©”λͺ¨μ΄μ œμ΄μ…˜ (반볡 계산 λ°©μ§€) + const bannerAvailability = useMemo( + () => ({ + banner0: isBannerAvailable('banner0'), + banner1: isBannerAvailable('banner1'), + }), + [isBannerAvailable] + ); + // πŸ”½ 디버그 정보 (λ‹¨μˆœν™”) const getDebugInfo = useCallback( () => ({ @@ -349,12 +358,9 @@ export const useVideoPlay = (options = {}) => { isPlaying, errorCount, videoState: videoState.getDebugInfo(), - bannerAvailability: { - banner0: isBannerAvailable('banner0'), - banner1: isBannerAvailable('banner1'), - }, + bannerAvailability, }), - [currentOwnerId, currentBanner, isPlaying, errorCount, isBannerAvailable] + [currentOwnerId, currentBanner, isPlaying, errorCount, bannerAvailability] ); return { @@ -371,6 +377,7 @@ export const useVideoPlay = (options = {}) => { isPlaying, currentBanner, bannerVisibility, + bannerAvailability, // βœ… [μ΅œμ ν™”] λ©”λͺ¨μ΄μ œμ΄μ…˜λœ λ°°λ„ˆ κ°€μš©μ„± // πŸ” μœ ν‹Έλ¦¬ν‹° isBannerAvailable, diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less index bb107a75..4773d1ef 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerTabContents/v2/LiveChannelNext.module.less @@ -14,6 +14,7 @@ max-width: 455px; height: 92px; padding: 10px 10px 10px 10px; + margin-bottom: 50px; background: rgba(0, 0, 0, 0.3); border: 1px solid rgba(234, 234, 234, 0.3); border-radius: 100px; @@ -32,10 +33,6 @@ &:focus { background: @PRIMARY_COLOR_RED; border-color: @PRIMARY_COLOR_RED; - - &::after { - .focused(@boxShadow: 22px, @borderRadius: 100px); - } } }