-
Notifications
You must be signed in to change notification settings - Fork 2
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
Refactor/#244 기존 SongDetailPage 컴포넌트에 새로운 플로우와 시안을 적용한다. #261
Changes from 36 commits
9dae4e4
4d269dc
d008412
797e175
afa7c92
a40efc6
c968fbd
99f3403
8896774
8b96c7d
a2fb71e
477faa6
378c172
b1c4868
e2706fe
9aa0718
e5b9c39
ad186bc
58f05df
f7f67cb
7475e9c
91717d6
8d9f812
361cb1e
9fd9485
476d38a
4886a6f
dee7353
af60a62
5fad8e4
007f133
0657970
ada932f
9aac9fb
4ced5f8
7dfcf04
e8a3e38
5d60a20
2488d6b
ee88e78
307d4c1
7c5960e
98be716
9d1c617
c3d016e
84caa6c
145c1d1
a09260b
c3d437f
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 | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,122 @@ | ||||||
import { useEffect, useRef, useState } from 'react'; | ||||||
import { styled } from 'styled-components'; | ||||||
import CommentList from '@/features/comments/components/CommentList'; | ||||||
import useVideoPlayerContext from '@/features/youtube/hooks/useVideoPlayerContext'; | ||||||
import Spacing from '@/shared/components/Spacing'; | ||||||
import ToggleSwitch from '@/shared/components/ToggleSwitch/ToggleSwitch'; | ||||||
import KillingPartTrackList from './KillingPartTrackList'; | ||||||
import type { KillingPart, SongDetail } from '@/shared/types/song'; | ||||||
|
||||||
interface KillingPartInterfaceProps { | ||||||
killingParts: SongDetail['killingParts']; | ||||||
songId: number; | ||||||
} | ||||||
|
||||||
const DEFAULT_PART_ID = -1; | ||||||
|
||||||
const KillingPartInterface = ({ killingParts, songId }: KillingPartInterfaceProps) => { | ||||||
const [nowPlayingTrack, setNowPlayingTrack] = useState<KillingPart['id']>(DEFAULT_PART_ID); | ||||||
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. 이제 변동 가능한 rank 대신 고정값인 id로 관리합니다! 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. 💬 rank는 왜 변동가능하고 id는 왜 고정인가요? 둘 다 똑같은 KillingPart의 정보 아닌가요? 역으로 생각하면 서버에서 내려주는 killingParts에는 rank가 순서대로 고정적으로 담겨있고, 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. 제 설명이 다소 애매하고 부족했네요. {killingPart && <CommentList songId={id} partId={killingParts[killingRank! - 1].id} />} 리팩터링 전에는 page컴포넌트가 KillingRank 상태를 가지고 있었고, rank로 killingPart를 찾고, 또 이 과정에서 "part의 id는 순위가 변동된다고 변하지 않고, rank는 순위에 변동에 따라 바뀌니깐
이 문장 하나로는 택도 없었네요 ㅠ
코난의 의문이 확실히 이해됩니다! 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.
그렇군요 👍👍 |
||||||
const [isRepeat, setIsRepeat] = useState(false); | ||||||
const { videoPlayer, playerState, seekTo, pause } = useVideoPlayerContext(); | ||||||
|
||||||
const timerRef = useRef<number | null>(null); | ||||||
|
||||||
const toggleRepetition = () => { | ||||||
setIsRepeat(!isRepeat); | ||||||
}; | ||||||
|
||||||
useEffect(() => { | ||||||
if (document.activeElement === videoPlayer.current?.getIframe()) { | ||||||
setNowPlayingTrack(DEFAULT_PART_ID); | ||||||
} | ||||||
}, [videoPlayer, playerState]); | ||||||
|
||||||
useEffect(() => { | ||||||
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. 반복 재생 이펙트 이동 및 로직 개선 |
||||||
const part = killingParts.find((part) => part.id === nowPlayingTrack); | ||||||
if (!part) return; | ||||||
|
||||||
seekTo(part.start); | ||||||
|
||||||
const interval = (part.end - part.start) * 1000; | ||||||
|
||||||
if (isRepeat) { | ||||||
timerRef.current = window.setInterval(() => seekTo(part.start), interval); | ||||||
} else { | ||||||
timerRef.current = window.setTimeout(() => { | ||||||
pause(); | ||||||
setNowPlayingTrack(DEFAULT_PART_ID); | ||||||
}, interval); | ||||||
} | ||||||
|
||||||
return () => { | ||||||
if (!timerRef.current) return; | ||||||
window.clearInterval(timerRef.current); | ||||||
}; | ||||||
}, [isRepeat, nowPlayingTrack, seekTo, pause, killingParts]); | ||||||
|
||||||
return ( | ||||||
<> | ||||||
<FlexContainer> | ||||||
<TitleWrapper aria-label="Top 3 킬링파트 듣기"> | ||||||
<ItalicTitle aria-hidden="true">Top 3</ItalicTitle> | ||||||
<NormalTitle aria-hidden="true"> Killing part</NormalTitle> | ||||||
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.
Suggested change
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. 다른 스타일의 텍스트 사이에 띄어쓰기가 필요해서 넣었습니다! 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. 아하! 띄어쓰기로 간격을 주지말고 TitleWrapper를 flex로 변경하고 간격을 주면 어떨까요?? <TitleWrapper aria-label="Top 3 킬링파트 듣기">
<ItalicTitle aria-hidden="true">Top 3</ItalicTitle>
<Spacing direction="horizontal" size={10} />
<NormalTitle aria-hidden="true">Killing part</NormalTitle>
</TitleWrapper> |
||||||
</TitleWrapper> | ||||||
<SwitchWrapper> | ||||||
<SwitchLabel htmlFor="repetition">구간 반복</SwitchLabel> | ||||||
<ToggleSwitch | ||||||
id="repetition" | ||||||
on={toggleRepetition} | ||||||
off={toggleRepetition} | ||||||
defaultToggle={isRepeat} | ||||||
/> | ||||||
</SwitchWrapper> | ||||||
</FlexContainer> | ||||||
<Spacing direction="vertical" size={16} /> | ||||||
<KillingPartTrackList | ||||||
killingParts={killingParts} | ||||||
nowPlayingTrack={nowPlayingTrack} | ||||||
setNowPlayingTrack={setNowPlayingTrack} | ||||||
/> | ||||||
{nowPlayingTrack !== DEFAULT_PART_ID && ( | ||||||
<CommentList songId={songId} partId={nowPlayingTrack} /> | ||||||
)} | ||||||
</> | ||||||
); | ||||||
}; | ||||||
|
||||||
export default KillingPartInterface; | ||||||
|
||||||
const SwitchWrapper = styled.div` | ||||||
display: flex; | ||||||
column-gap: 8px; | ||||||
`; | ||||||
|
||||||
const SwitchLabel = styled.label` | ||||||
font-size: 12px; | ||||||
color: ${({ theme: { color } }) => color.white}; | ||||||
`; | ||||||
|
||||||
const TitleWrapper = styled.div` | ||||||
font-size: 22px; | ||||||
font-weight: 700; | ||||||
color: ${({ theme: { color } }) => color.white}; | ||||||
|
||||||
@media (max-width: ${({ theme }) => theme.breakPoints.md}) { | ||||||
font-size: 18px; | ||||||
} | ||||||
`; | ||||||
|
||||||
const ItalicTitle = styled.span` | ||||||
font-style: italic; | ||||||
color: ${({ theme: { color } }) => color.primary}; | ||||||
`; | ||||||
|
||||||
const NormalTitle = styled.span` | ||||||
color: ${({ theme: { color } }) => color.white}; | ||||||
`; | ||||||
|
||||||
const FlexContainer = styled.div` | ||||||
display: flex; | ||||||
align-items: center; | ||||||
justify-content: space-between; | ||||||
`; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,5 +1,6 @@ | ||||||
import { useState } from 'react'; | ||||||
import { VideoPlayerProvider } from '@/features/youtube/components/VideoPlayerProvider'; | ||||||
import TimerProvider from '@/shared/components/Timer/TimerProvider'; | ||||||
import ToastProvider from '@/shared/components/Toast/ToastProvider'; | ||||||
import KillingPartTrack from './KillingPartTrack'; | ||||||
import type { KillingPart } from '@/shared/types/song'; | ||||||
|
@@ -13,7 +14,9 @@ const meta = { | |||||
return ( | ||||||
<ToastProvider> | ||||||
<VideoPlayerProvider> | ||||||
<Story /> | ||||||
<TimerProvider time={killingPart.end - killingPart.start}> | ||||||
<Story /> | ||||||
</TimerProvider> | ||||||
</VideoPlayerProvider> | ||||||
</ToastProvider> | ||||||
); | ||||||
|
@@ -36,21 +39,15 @@ const killingPart: KillingPart = { | |||||
}; | ||||||
|
||||||
const KillingPartTrackWithHook = () => { | ||||||
const [nowPlayingTrack, setNowPlayingTrack] = useState(-1); | ||||||
const [nowPlayingTrack, setNowPlayingTrack] = useState<KillingPart['id']>(-1); | ||||||
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. 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. 저번에도 비슷한 질문을 해주신것 같은데요! 해당 코드가 항상 killingPart의 id 만을 받아야 하는 상태인것을 아는 상황이라면 number로 두어도 이해가 되겠지만, 위와 같은 이유로 저는 객체 타입의 하위 타입? 이라면 조금더 좁혀서 명시해 주고 있습니다! |
||||||
|
||||||
const changePlayingTrack: React.ChangeEventHandler<HTMLInputElement> = ({ currentTarget }) => { | ||||||
const newTrack = Number(currentTarget.value); | ||||||
|
||||||
setNowPlayingTrack(newTrack); | ||||||
}; | ||||||
|
||||||
const isPlaying = killingPart.rank === nowPlayingTrack; | ||||||
const isNowPlayingTrack = killingPart.rank === nowPlayingTrack; | ||||||
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.
Suggested change
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. 이런일이! 수정하겠습니다! |
||||||
|
||||||
return ( | ||||||
<KillingPartTrack | ||||||
killingPart={killingPart} | ||||||
isPlaying={isPlaying} | ||||||
changePlayingTrack={changePlayingTrack} | ||||||
isNowPlayingTrack={isNowPlayingTrack} | ||||||
setNowPlayingTrack={setNowPlayingTrack} | ||||||
/> | ||||||
); | ||||||
}; | ||||||
|
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.
💬 커밋 메세지로 확인 안되어서 그런데 이건 왜 고치신건가요?
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.
커밋을 잘 나누지 못했네요...
만약 comments 배열 자체가 없거나, comments 배열은 있는데 코멘트가 없어도
랜더링은 진행되어서
댓글 0개
는 보여주는게 좋겠다 생각했어요!