diff --git a/page/README.md b/page/README.md index eff285b..e3e8ef1 100644 --- a/page/README.md +++ b/page/README.md @@ -124,6 +124,8 @@ site: "bot-site" 구독 → serverId 일치하는 것만 EventSource(SSE)로 브 | 관행 | 예전 | 현재 | |------|------|------| +| 곡 검색 결과 표시 | 그리드 카드 | 리스트 행(번호·썸네일·제목/아티스트·재생시간). 그리드는 앨범/재생목록처럼 커버가 주인공일 때 쓰는 형태이고, 개별 곡은 두 서비스 모두 행 형식이다 | +| 대기열 접기/펴기 | 넓은 화면에서 항상 고정 | 재생바 우측 대기열 버튼으로 접고 펼 수 있음(스포티파이와 같은 위치) | | 좁은 화면 대응 | 3열 고정이라 모바일에서 본문이 눌려 사용 불가 | 단일 컬럼 + 대기열 슬라이드 패널 | | 대기열 상단에 "지금 재생 중" | 없음(다음 곡만) | 현재 곡을 강조해 표시 | | 대기열 곡 클릭 → 그 곡부터 재생 | 없음 | 지원(앞 곡들은 빠짐 — 스포티파이 대기열과 동일) | diff --git a/page/src/app/page.tsx b/page/src/app/page.tsx index e548e0e..637adb3 100644 --- a/page/src/app/page.tsx +++ b/page/src/app/page.tsx @@ -18,8 +18,12 @@ export default function MusicPlayerLayout() { const [viewMode, setViewMode] = useState("SERVER_LIST"); const [selectedServer, setSelectedServer] = useState(null); const [searchQuery, setSearchQuery] = useState(""); - // 모바일에서 대기열은 상시 컬럼이 아니라 오른쪽에서 밀려나오는 패널로 띄운다. + // 대기열 표시 상태는 화면 크기별로 기본값이 달라서 두 개로 나눠 둔다. + // (창 크기를 읽어 한 상태로 합치면 SSR·하이드레이션이 어긋난다) + // · 좁은 화면: 기본 접힘 → 버튼으로 슬라이드 패널을 연다 + // · 넓은 화면: 기본 펼침 → 재생바의 대기열 버튼으로 접을 수 있다 const [isQueueOpen, setIsQueueOpen] = useState(false); + const [isQueueDocked, setIsQueueDocked] = useState(true); // 재생바가 이미 폴링하는 현재 곡을 대기열 패널과 공유한다(같은 API 를 두 번 부르지 않기 위함). const [nowPlaying, setNowPlaying] = useState(null); const handleNowPlayingChange = useCallback((t: Track | null) => setNowPlaying(t), []); @@ -95,8 +99,9 @@ export default function MusicPlayerLayout() {
setIsQueueOpen((v) => !v)} isQueueOpen={isQueueOpen} + onToggleDock={() => setIsQueueDocked((v) => !v)} + isQueueDocked={isQueueDocked} onNowPlayingChange={handleNowPlayingChange} /> )} diff --git a/page/src/components/player/MainContent.tsx b/page/src/components/player/MainContent.tsx index 3b056a5..43db7e7 100644 --- a/page/src/components/player/MainContent.tsx +++ b/page/src/components/player/MainContent.tsx @@ -197,34 +197,49 @@ export default function MainContent({ const hasAnyResults = searchResults.spotify.length > 0 || searchResults.youtubeMusic.length > 0 || searchResults.youtubeVideo.length > 0; - // 카드 전체가 눌리는 버튼이다. 예전에는 hover 시에만 나타나는 작은 아이콘만 눌러야 해서 - // 터치 기기(hover 없음)에서는 재생 방법을 찾기 어려웠다. - const renderTrackCard = (track: SearchTrack) => ( + /** + * 곡 하나는 '리스트 행'으로 보여준다. + * 그리드 카드는 앨범/재생목록처럼 커버가 주인공일 때 쓰는 형태고, + * 개별 곡 검색 결과는 스포티파이·유튜브뮤직 모두 행(제목·아티스트·재생시간) 형식이라 + * 사용자에게 익숙한 쪽으로 맞춘다. 행 전체가 버튼이라 터치로도 바로 누를 수 있다. + */ + const renderTrackRow = (track: SearchTrack, index: number) => ( ); @@ -360,8 +375,8 @@ export default function MainContent({

Spotify 결과

-
- {searchResults.spotify.map(renderTrackCard)} +
+ {searchResults.spotify.map(renderTrackRow)}
)} @@ -372,8 +387,8 @@ export default function MainContent({

YouTube Music

-
- {searchResults.youtubeMusic.map(renderTrackCard)} +
+ {searchResults.youtubeMusic.map(renderTrackRow)}
)} @@ -384,8 +399,8 @@ export default function MainContent({

YouTube 영상

-
- {searchResults.youtubeVideo.map(renderTrackCard)} +
+ {searchResults.youtubeVideo.map(renderTrackRow)}
)} diff --git a/page/src/components/player/PlayerBar.tsx b/page/src/components/player/PlayerBar.tsx index 2f3014a..1061527 100644 --- a/page/src/components/player/PlayerBar.tsx +++ b/page/src/components/player/PlayerBar.tsx @@ -8,11 +8,14 @@ interface PlayerBarProps { selectedServer: DiscordServer | null; onToggleQueue?: () => void; isQueueOpen?: boolean; + /** 넓은 화면에서 우측 대기열 컬럼을 접었다 펴는 토글 */ + onToggleDock?: () => void; + isQueueDocked?: boolean; /** 대기열 패널에도 "지금 재생 중"을 보여주기 위해 현재 곡을 위로 올려준다(중복 폴링 방지). */ onNowPlayingChange?: (track: Track | null) => void; } -export default function PlayerBar({ selectedServer, onToggleQueue, isQueueOpen, onNowPlayingChange }: PlayerBarProps) { +export default function PlayerBar({ selectedServer, onToggleQueue, isQueueOpen, onToggleDock, isQueueDocked, onNowPlayingChange }: PlayerBarProps) { const { data: session } = useSession(); // 재생 상태 관리 @@ -423,7 +426,7 @@ export default function PlayerBar({ selectedServer, onToggleQueue, isQueueOpen, - {/* 모바일 전용: 대기열 토글 */} + {/* 좁은 화면에서 대기열 열기(넓은 화면에는 우측 하단에 같은 버튼을 따로 둔다) */} {onToggleQueue && (
- {/* 3. 볼륨 (좁은 화면에서는 숨긴다 — 기기 자체 볼륨으로 조절 가능) */} + {/* 3. 우측 보조 조작: 대기열 + 볼륨 (스포티파이도 이 자리에 대기열 버튼을 둔다) */}
+ {onToggleDock && ( + + )}