-
Notifications
You must be signed in to change notification settings - Fork 2
[feat] 둘러보기 UX 개선사항 반영 #108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ import { useNavigate } from 'react-router-dom' | |
|
|
||
| import styled from 'styled-components' | ||
|
|
||
| import { usePlaylist } from '@/app/providers/PlayerProvider' | ||
| import { Cancel } from '@/assets/icons' | ||
| import type { PlaylistDetailResponse } from '@/entities/playlist' | ||
| import { getGenreLabel } from '@/shared/lib' | ||
|
|
@@ -17,6 +18,13 @@ interface PlaylistInfoProps { | |
|
|
||
| const PlaylistInfo = ({ playlistData, isLoading, isError }: PlaylistInfoProps) => { | ||
| const navigate = useNavigate() | ||
| const { setPlaylist, currentPlaylist } = usePlaylist() | ||
|
|
||
| const handleClickTrack = (trackIndex: number) => { | ||
| if (!currentPlaylist) return | ||
| navigate(-1) | ||
| setPlaylist(currentPlaylist, trackIndex, 0) | ||
| } | ||
|
Comment on lines
+23
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 선택한 트랙 재생 시 원본 플레이리스트 소스 확인 필요 (현재 로직은 currentPlaylist만 사용) 상세 화면에서 클릭한 트랙의 인덱스로 재생하려면, currentPlaylist가 상세의 playlistData와 동일하지 않은 경우에도 해당 상세 플레이리스트를 소스로 설정해야 합니다. 현 로직은 currentPlaylist가 없으면 아무 작업도 하지 않고, 다른 플레이리스트가 활성화된 상태에서는 잘못된 인덱스로 점프할 수 있습니다. 권장: currentPlaylist?.playlistId !== playlistData.playlistId인 경우 playlistData를 Player가 요구하는 타입으로 변환하여 setPlaylist에 전달하세요. 또한 setPlaylist 이후 navigate(-1) 호출 순서를 권장합니다. 예시(개념적): const handleClickTrack = (trackIndex: number) => {
if (!playlistData) return
const source =
currentPlaylist?.playlistId === playlistData.playlistId
? currentPlaylist
: transformDetailToPlaylistInfo(playlistData) // 변환 함수 필요
setPlaylist(source, trackIndex, 0)
navigate(-1)
}🤖 Prompt for AI Agents |
||
|
|
||
| if (isError || !playlistData) { | ||
| return ( | ||
|
|
@@ -50,7 +58,12 @@ const PlaylistInfo = ({ playlistData, isLoading, isError }: PlaylistInfoProps) = | |
| <TrackInfo> | ||
| {playlistData.songs && | ||
| playlistData.songs.map((track, index) => ( | ||
| <Link key={index} data={track} variant="large" /> | ||
| <Link | ||
| key={track.id} | ||
| data={track} | ||
| variant="large" | ||
| onClick={() => handleClickTrack(index)} | ||
| /> | ||
maylh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ))} | ||
| </TrackInfo> | ||
| </Content> | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,7 +1,7 @@ | ||||||||||||||||||||||||||
| import { useRef, useEffect } from 'react' | ||||||||||||||||||||||||||
| import YouTube from 'react-youtube' | ||||||||||||||||||||||||||
| import type { YouTubeProps, YouTubeEvent, YouTubePlayer } from 'react-youtube' // | ||||||||||||||||||||||||||
| import type { YouTubeProps, YouTubeEvent, YouTubePlayer } from 'react-youtube' | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| import { useDevice } from '@/shared/lib/useDevice' | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| interface YoutubePlayerProps { | ||||||||||||||||||||||||||
| videoId: string | ||||||||||||||||||||||||||
|
|
@@ -10,23 +10,38 @@ interface YoutubePlayerProps { | |||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| function YoutubePlayer({ videoId, onReady, onStateChange }: YoutubePlayerProps) { | ||||||||||||||||||||||||||
| const deviceType = useDevice() | ||||||||||||||||||||||||||
| const isMobile = deviceType === 'mobile' | ||||||||||||||||||||||||||
| const playerRef = useRef<YouTubePlayer | null>(null) | ||||||||||||||||||||||||||
| const isFirstLoad = useRef(true) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const playerOpts: YouTubeProps['opts'] = { | ||||||||||||||||||||||||||
| playerVars: { | ||||||||||||||||||||||||||
| autoplay: 1, | ||||||||||||||||||||||||||
| mute: isMobile ? 1 : 0, | ||||||||||||||||||||||||||
| mute: 0, | ||||||||||||||||||||||||||
| playsinline: 1, // 모바일 인라인 재생 | ||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||
| if (!isFirstLoad.current && playerRef.current && videoId) { | ||||||||||||||||||||||||||
| // 첫 로딩 제외하고 loadVideoById 호출 | ||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||
| playerRef.current.loadVideoById(videoId) | ||||||||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||||||||
| console.error('loadVideoById 실패', e) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| isFirstLoad.current = false | ||||||||||||||||||||||||||
| }, [videoId]) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
Comment on lines
+24
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. videoId 변경 시 이중 load 위험 (react-youtube가 이미 처리함) react-youtube는 videoId prop 변경 시 내부적으로 loadVideoById를 호출합니다. 현재 useEffect에서 동일 호출을 반복해 깜빡임/상태 경합이 생길 수 있습니다. 이 효과를 제거하는 것을 권장합니다. 적용 diff: - useEffect(() => {
- if (!isFirstLoad.current && playerRef.current && videoId) {
- // 첫 로딩 제외하고 loadVideoById 호출
- try {
- playerRef.current.loadVideoById(videoId)
- } catch (e) {
- console.error('loadVideoById 실패', e)
- }
- }
- isFirstLoad.current = false
- }, [videoId])
+ // react-youtube가 videoId 변경을 내부적으로 처리하므로 별도의 load 호출은 불필요합니다.추가로 isFirstLoad ref는 불필요해집니다(정리 권장). 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||
| <div style={{ width: 0, height: 0, overflow: 'hidden', position: 'absolute' }}> | ||||||||||||||||||||||||||
| <YouTube | ||||||||||||||||||||||||||
| videoId={videoId} | ||||||||||||||||||||||||||
| opts={playerOpts} | ||||||||||||||||||||||||||
| onReady={onReady} | ||||||||||||||||||||||||||
| onReady={(e) => { | ||||||||||||||||||||||||||
| playerRef.current = e.target | ||||||||||||||||||||||||||
| onReady(e) | ||||||||||||||||||||||||||
| }} | ||||||||||||||||||||||||||
| onStateChange={onStateChange} | ||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
플레이리스트 상세 페이지에서 특정 트랙을 클릭했을 때의 재생 로직에 치명적인 오류가 있습니다.
현재 코드는
usePlaylist에서 가져온currentPlaylist를 사용하여setPlaylist를 호출하고 있습니다. 이 경우, 사용자가 보고 있는 플레이리스트(playlistData)가 아닌 현재 재생 중인 플레이리스트의 트랙이 변경됩니다. 만약 아무것도 재생 중이지 않다면currentPlaylist가null이므로 아무 동작도 하지 않게 됩니다.사용자가 보고 있는
playlistData를 기준으로 플레이리스트를 설정하도록 수정해야 합니다.playlistData의 타입(PlaylistDetailResponse)과setPlaylist가 요구하는 타입(PlaylistInfo)이 다르므로, 필요한 형태로 객체를 변환하여 전달해야 합니다.