From f6073d78c1441799cf057fbcc23175274b3d2a91 Mon Sep 17 00:00:00 2001 From: optrader Date: Wed, 17 Dec 2025 14:17:24 +0900 Subject: [PATCH] [251217] fix: LiveChannelContents Navigation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ๐Ÿ• ์ปค๋ฐ‹ ์‹œ๊ฐ„: 2025. 12. 17. 14:17:24 ๐Ÿ“Š ๋ณ€๊ฒฝ ํ†ต๊ณ„: โ€ข ์ด ํŒŒ์ผ: 1๊ฐœ โ€ข ์ถ”๊ฐ€: +100์ค„ โ€ข ์‚ญ์ œ: -9์ค„ ๐Ÿ“ ์ˆ˜์ •๋œ ํŒŒ์ผ: ~ com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx ๐Ÿ”ง ์ฃผ์š” ๋ณ€๊ฒฝ ๋‚ด์šฉ: โ€ข ์†Œ๊ทœ๋ชจ ๊ธฐ๋Šฅ ๊ฐœ์„  --- .../src/views/PlayerPanel/PlayerPanel.jsx | 109 ++++++++++++++++-- 1 file changed, 100 insertions(+), 9 deletions(-) diff --git a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx index 8d80a0a1..7de705f2 100644 --- a/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx +++ b/com.twin.app.shoptime/src/views/PlayerPanel/PlayerPanel.jsx @@ -1248,12 +1248,12 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props return () => { // ํŒจ๋„์ด 2๊ฐœ ์กด์žฌํ• ๋•Œ๋งŒ popPanel ์ง„ํ–‰ // ํ˜„์žฌ ์Šคํƒ์˜ top์ด PlayerPanel์ผ ๋•Œ๋งŒ pop ์ˆ˜ํ–‰ (๋‹ค๋ฅธ ํŒจ๋„์ด ์˜ฌ๋ผ์˜จ ์ƒํƒœ์—์„œ ์˜ค์ž‘๋™ ๋ฐฉ์ง€) - console.log('[PP-TRACE] cleanup start', { - modal: panelInfo.modal, - isOnTop, - topPanel: panels[panels.length - 1]?.name, - stack: panels.map((p) => p.name), - }); + // console.log('[PP-TRACE] cleanup start', { + // modal: panelInfo.modal, + // isOnTop, + // topPanel: panels[panels.length - 1]?.name, + // stack: panels.map((p) => p.name), + // }); // ๐Ÿ”ฝ [251221] PlayerPanel unmount ์‹œ DeepLink ํ”Œ๋ž˜๊ทธ ๋ฆฌ์…‹ dispatch( @@ -1272,7 +1272,7 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props topPanelName === panel_names.PLAYER_PANEL && panels.length === 1 // ๋‹ค๋ฅธ ํŒจ๋„ ์กด์žฌ ์‹œ pop ๊ธˆ์ง€ (DetailPanel ์ œ๊ฑฐ ๋ฐฉ์ง€) ) { - console.log('[PP-TRACE] popPanel - useEffect cleanup (top is PlayerPanel)'); + // console.log('[PP-TRACE] popPanel - useEffect cleanup (top is PlayerPanel)'); dispatch(PanelActions.popPanel()); } else { Spotlight.focus('tbody'); @@ -2536,14 +2536,105 @@ const PlayerPanel = ({ isTabActivated, panelInfo, isOnTop, spotlightId, ...props ); const onKeyDown = (ev) => { - if (ev.keyCode === 34) { + // tabIndex === 1 (LiveChannelContents ํ‘œ์‹œ)์ด๊ณ  ๋น„๋””์˜ค ๋ฐฐ๋„ˆ์— ํฌ์ปค์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ + const currentFocused = Spotlight.getCurrent(); + const spotlightId = currentFocused?.getAttribute('data-spotlight-id'); + const isVideoItemFocused = spotlightId?.startsWith('tabChannel-video'); + + // LiveChannelContents์˜ ๋น„๋””์˜ค ๋ฐฐ๋„ˆ์— ํฌ์ปค์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ: PageUp/PageDown์„ ์ขŒ์šฐ ์ด๋™์œผ๋กœ ๋ณ€ํ™˜ + if (tabIndexV2 === 1 && isVideoItemFocused) { + // DOM์—์„œ ์‹ค์ œ๋กœ ๋ Œ๋”๋ง๋œ ๋ชจ๋“  ๋น„๋””์˜ค ๋ฐฐ๋„ˆ ์ฐพ๊ธฐ (๊ฐ€์ƒํ™” ๋Œ€์‘) + const allVideoBanners = Array.from( + document.querySelectorAll('[data-spotlight-id^="tabChannel-video-"]') + ); + + if (allVideoBanners.length > 0) { + // ํ˜„์žฌ ํฌ์ปค์Šค๋œ ๋ฐฐ๋„ˆ์˜ ์ธ๋ฑ์Šค ์ฐพ๊ธฐ + const currentBannerIndex = allVideoBanners.findIndex( + (el) => el === currentFocused + ); + + if (currentBannerIndex !== -1) { + if (ev.keyCode === 34) { // PageDown -> ์˜ค๋ฅธ์ชฝ ๋ฐฐ๋„ˆ๋กœ ํฌ์ปค์Šค ์ด๋™ + ev.stopPropagation(); + ev.preventDefault(); + + // DOM์— ๋ Œ๋”๋ง๋œ ๋‹ค์Œ ๋ฐฐ๋„ˆ๋กœ ์ด๋™ (๋งˆ์ง€๋ง‰์ด๋ฉด ๋ฌด์‹œ ๋˜๋Š” ์ฒซ ๋ฒˆ์งธ๋กœ) + if (currentBannerIndex < allVideoBanners.length - 1) { + // ๋‹ค์Œ ๋ฐฐ๋„ˆ๊ฐ€ DOM์— ์žˆ์œผ๋ฉด ์ด๋™ + const nextBanner = allVideoBanners[currentBannerIndex + 1]; + const nextSpotlightId = nextBanner.getAttribute('data-spotlight-id'); + + dlog('[PlayerPanel] ๐ŸŽฏ PageDown (๋น„๋””์˜ค ๋ฐฐ๋„ˆ) -> ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™', { + current: spotlightId, + next: nextSpotlightId, + currentBannerIndex, + totalVisibleBanners: allVideoBanners.length, + }); + + Spotlight.focus(nextSpotlightId); + } else { + // ๋งˆ์ง€๋ง‰ ๋ฐฐ๋„ˆ๋ฉด ์ฒซ ๋ฒˆ์งธ๋กœ ์ด๋™ ์‹œ๋„ (DOM์— ์žˆ์œผ๋ฉด) + const firstBanner = allVideoBanners[0]; + const firstSpotlightId = firstBanner.getAttribute('data-spotlight-id'); + + dlog('[PlayerPanel] ๐ŸŽฏ PageDown (๋งˆ์ง€๋ง‰ ๋ฐฐ๋„ˆ) -> ์ฒซ ๋ฒˆ์งธ ๋ฐฐ๋„ˆ๋กœ ์ด๋™ ์‹œ๋„', { + current: spotlightId, + next: firstSpotlightId, + isWrapAround: true, + }); + + Spotlight.focus(firstSpotlightId); + } + return; + } else if (ev.keyCode === 33) { // PageUp -> ์™ผ์ชฝ ๋ฐฐ๋„ˆ๋กœ ํฌ์ปค์Šค ์ด๋™ + ev.stopPropagation(); + ev.preventDefault(); + + // DOM์— ๋ Œ๋”๋ง๋œ ์ด์ „ ๋ฐฐ๋„ˆ๋กœ ์ด๋™ (์ฒซ ๋ฒˆ์งธ๋ฉด ๋ฌด์‹œ ๋˜๋Š” ๋งˆ์ง€๋ง‰์œผ๋กœ) + if (currentBannerIndex > 0) { + // ์ด์ „ ๋ฐฐ๋„ˆ๊ฐ€ DOM์— ์žˆ์œผ๋ฉด ์ด๋™ + const prevBanner = allVideoBanners[currentBannerIndex - 1]; + const prevSpotlightId = prevBanner.getAttribute('data-spotlight-id'); + + dlog('[PlayerPanel] ๐ŸŽฏ PageUp (๋น„๋””์˜ค ๋ฐฐ๋„ˆ) -> ์™ผ์ชฝ์œผ๋กœ ์ด๋™', { + current: spotlightId, + prev: prevSpotlightId, + currentBannerIndex, + totalVisibleBanners: allVideoBanners.length, + }); + + Spotlight.focus(prevSpotlightId); + } else { + // ์ฒซ ๋ฒˆ์งธ ๋ฐฐ๋„ˆ๋ฉด ๋งˆ์ง€๋ง‰์œผ๋กœ ์ด๋™ ์‹œ๋„ (DOM์— ์žˆ์œผ๋ฉด) + const lastBanner = allVideoBanners[allVideoBanners.length - 1]; + const lastSpotlightId = lastBanner.getAttribute('data-spotlight-id'); + + dlog('[PlayerPanel] ๐ŸŽฏ PageUp (์ฒซ ๋ฒˆ์งธ ๋ฐฐ๋„ˆ) -> ๋งˆ์ง€๋ง‰ ๋ฐฐ๋„ˆ๋กœ ์ด๋™ ์‹œ๋„', { + current: spotlightId, + prev: lastSpotlightId, + isWrapAround: true, + }); + + Spotlight.focus(lastSpotlightId); + } + return; + } + } + } + } + + // ๊ธฐ์กด ๋กœ์ง: LiveChannelButton ๋˜๋Š” ๋‹ค๋ฅธ ๊ฒฝ์šฐ์—๋Š” ์ƒ/ํ•˜ ์ด๋™ + if (ev.keyCode === 34) { // PageDown handleIndicatorDownClick(); ev.stopPropagation(); ev.preventDefault(); - } else if (ev.keyCode === 33) { + dlog('[PlayerPanel] ๐Ÿ“บ PageDown (๋ฒ„ํŠผ ๋˜๋Š” ๋‹ค๋ฅธ ๊ฒฝ์šฐ) -> ๋‹ค์Œ ๋น„๋””์˜ค'); + } else if (ev.keyCode === 33) { // PageUp handleIndicatorUpClick(); ev.stopPropagation(); ev.preventDefault(); + dlog('[PlayerPanel] ๐Ÿ“บ PageUp (๋ฒ„ํŠผ ๋˜๋Š” ๋‹ค๋ฅธ ๊ฒฝ์šฐ) -> ์ด์ „ ๋น„๋””์˜ค'); } };