Skip to content

Commit 89a8e8d

Browse files
authored
Merge pull request #40 from CalPinSW/add-play-album-buttons
Add ability to start album in context of playlist from playlist explo…
2 parents 01f1b4e + ad126a2 commit 89a8e8d

File tree

6 files changed

+53
-14
lines changed

6 files changed

+53
-14
lines changed

backend/src/dataclasses/playback_request.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@ class StartPlaybackRequestUriOffset(BaseModel):
1010
uri: str
1111

1212

13+
class StartPlaybackRequestAlbumIdOffset(BaseModel):
14+
album_id: str
15+
16+
1317
class StartPlaybackRequest(BaseModel):
1418
context_uri: Optional[str] = None
1519
uris: Optional[List[str]] = None
1620
offset: Optional[
17-
StartPlaybackRequestPositionOffset | StartPlaybackRequestUriOffset
21+
StartPlaybackRequestPositionOffset
22+
| StartPlaybackRequestUriOffset
23+
| StartPlaybackRequestAlbumIdOffset
1824
] = None
1925
position_ms: Optional[int] = None

backend/src/spotify.py

+23-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import json
22
import requests
33
import os
4-
from typing import List
4+
from typing import List, Optional
55
from flask import Response, make_response, redirect
66
from src.dataclasses.album import Album
77
from src.dataclasses.playback_info import PlaybackInfo, PlaylistProgression
8-
from src.dataclasses.playback_request import StartPlaybackRequest
8+
from src.dataclasses.playback_request import (
9+
StartPlaybackRequest,
10+
StartPlaybackRequestUriOffset,
11+
)
912
from src.dataclasses.playback_state import PlaybackState
1013
from src.dataclasses.playlist import Playlist
1114
from src.dataclasses.playlist_info import CurrentUserPlaylists, SimplifiedPlaylist
@@ -468,11 +471,28 @@ def pause_playback(self, access_token) -> Response:
468471
)
469472

470473
def start_playback(
471-
self, access_token, start_playback_request_body: StartPlaybackRequest = None
474+
self,
475+
access_token,
476+
start_playback_request_body: Optional[StartPlaybackRequest] = None,
472477
) -> Response:
473478
if not start_playback_request_body:
474479
data = None
475480
else:
481+
if start_playback_request_body.offset.album_id:
482+
track_offset = StartPlaybackRequestUriOffset.model_validate(
483+
{
484+
"uri": (
485+
self.get_album(
486+
access_token=access_token,
487+
id=start_playback_request_body.offset.album_id,
488+
)
489+
.tracks.items[0]
490+
.uri
491+
)
492+
}
493+
)
494+
495+
start_playback_request_body.offset = track_offset
476496
data = start_playback_request_body.model_dump_json(exclude_none=True)
477497

478498
response = requests.put(

frontend/src/api/index.ts

+6-8
Original file line numberDiff line numberDiff line change
@@ -109,18 +109,16 @@ export const pausePlayback = async (): Promise<Response> => {
109109
return jsonRequest(`spotify/pause_playback`, RequestMethod.PUT);
110110
};
111111

112-
export const startPlayback = async (
112+
interface StartPlaybackRequest {
113113
context_uri?: string,
114114
uris?: string[],
115-
offset?: {position: number} | {uri: string},
115+
offset?: {position: number} | {uri: string} | {album_id: string},
116116
position_ms?: number
117+
}
118+
119+
export const startPlayback = async (requestBody?: StartPlaybackRequest
117120
): Promise<Response> => {
118-
return jsonRequest(`spotify/start_playback`, RequestMethod.PUT, {
119-
context_uri,
120-
uris,
121-
offset,
122-
position_ms
123-
});
121+
return jsonRequest(`spotify/start_playback`, RequestMethod.PUT, requestBody);
124122
};
125123

126124
export const pauseOrStartPlayback = async (): Promise<Response> => {

frontend/src/playlistExplorer/AlbumList/AlbumContainer.tsx

+12-2
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,20 @@ import PlaylistIcon from "../../components/PlaylistIcon";
44
import { RotatingBorderBox } from "../../components/RotatingBorderBox";
55
import Modal from "../../components/Modal";
66
import { Playlist } from "../../interfaces/Playlist";
7-
import { addAlbumToPlaylist } from "../../api";
7+
import { addAlbumToPlaylist, startPlayback } from "../../api";
88
import { useModal } from "../../hooks/useModal";
99
import Button from "../../components/Button";
1010

1111
interface AlbumContainerProps {
1212
album: Album;
13+
contextPlaylist: Playlist
1314
associatedPlaylists: Playlist[];
1415
active?: boolean;
1516
}
1617

1718
export const AlbumContainer: FC<AlbumContainerProps> = ({
1819
album,
20+
contextPlaylist,
1921
associatedPlaylists,
2022
active,
2123
}) => {
@@ -31,6 +33,7 @@ export const AlbumContainer: FC<AlbumContainerProps> = ({
3133
<>
3234
<Modal isModalOpen={isModalOpen} closeModal={closeModal}>
3335
<AlbumActionsModalContent
36+
contextPlaylist={contextPlaylist}
3437
associatedPlaylists={associatedPlaylists}
3538
album={album}
3639
closeModal={closeModal}
@@ -80,11 +83,13 @@ export const AlbumContainer: FC<AlbumContainerProps> = ({
8083

8184
interface AlbumActionsModalContentProps {
8285
album: Album;
86+
contextPlaylist: Playlist
8387
associatedPlaylists: Playlist[];
8488
closeModal: () => void;
8589
}
8690
const AlbumActionsModalContent: FC<AlbumActionsModalContentProps> = ({
8791
album,
92+
contextPlaylist,
8893
associatedPlaylists,
8994
closeModal,
9095
}) => {
@@ -98,7 +103,7 @@ const AlbumActionsModalContent: FC<AlbumActionsModalContentProps> = ({
98103
<h2 className="my-auto text-m">Actions:</h2>
99104
<button onClick={closeModal}>X</button>
100105
</div>
101-
<div className="my-2 space-y-2">
106+
<div className="flex flex-col my-2 space-y-2">
102107
{associatedPlaylists.map((associatedPlaylist) => (
103108
<Button
104109
onClick={() => addAlbumToAssociatedPlaylist(associatedPlaylist)}
@@ -107,6 +112,11 @@ const AlbumActionsModalContent: FC<AlbumActionsModalContentProps> = ({
107112
Add to {associatedPlaylist.name}
108113
</Button>
109114
))}
115+
<Button
116+
onClick={() => (startPlayback({context_uri: contextPlaylist.uri, offset: {album_id: album.id} }))}
117+
>
118+
Play Album
119+
</Button>
110120
</div>
111121
</div>
112122
);

frontend/src/playlistExplorer/AlbumList/AlbumList.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import { Playlist } from "../../interfaces/Playlist";
66

77
interface AlbumListProps {
88
albumList: Album[];
9+
contextPlaylist: Playlist;
910
associatedPlaylists: Playlist[];
1011
activeAlbumId?: string;
1112
}
1213
export const AlbumList: FC<AlbumListProps> = ({
1314
albumList,
15+
contextPlaylist,
1416
associatedPlaylists,
1517
activeAlbumId,
1618
}) => {
@@ -21,6 +23,7 @@ export const AlbumList: FC<AlbumListProps> = ({
2123
<AlbumContainer
2224
album={album}
2325
key={album.id}
26+
contextPlaylist={contextPlaylist}
2427
associatedPlaylists={associatedPlaylists}
2528
active={album.id == activeAlbumId}
2629
/>

frontend/src/playlistExplorer/PlaylistExplorer.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export const PlaylistExplorer: FC = () => {
5151
}, []);
5252

5353
const { playbackInfo } = usePlaybackContext();
54+
5455
return (
5556
<div className="flex flex-col h-full space-y-1 ">
5657
<div className="mx-2">
@@ -124,6 +125,7 @@ export const PlaylistExplorer: FC = () => {
124125
<AlbumList
125126
albumList={playlistAlbums}
126127
activeAlbumId={playbackInfo?.album_id}
128+
contextPlaylist={playlist}
127129
associatedPlaylists={associatedPlaylists}
128130
/>
129131
)}

0 commit comments

Comments
 (0)