Skip to content

Commit

Permalink
Merge pull request #187 from hayribakici/refactor_playOrResume
Browse files Browse the repository at this point in the history
Refactor `playOrResume`
  • Loading branch information
rinukkusu authored Feb 7, 2024
2 parents bcb3943 + d925704 commit c8bc7c6
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 25 deletions.
94 changes: 78 additions & 16 deletions lib/src/endpoints/player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ class PlayerEndpoint extends _MeEndpointBase {
/// will be retrieved after setting the volume. Defaults to true.
Future<PlaybackState?> shuffle(bool state,
{String? deviceId, bool retrievePlaybackState = true}) async {
await _api._put('$_path/shuffle?' +
_buildQuery({'state': state, 'deviceId': deviceId}));
await _api._put('$_path/shuffle?${_buildQuery({
'state': state,
'deviceId': deviceId
})}');

return retrievePlaybackState ? playbackState() : null;
}
Expand All @@ -34,8 +36,8 @@ class PlayerEndpoint extends _MeEndpointBase {
/// Returns the current playback state, including progress, track
/// and active device.
Future<PlaybackState> playbackState([Market? market]) async {
var jsonString = await _api
._get('$_path?' + _buildQuery({'market': market?.name}));
var jsonString =
await _api._get('$_path?${_buildQuery({'market': market?.name})}');
final map = json.decode(jsonString);
return PlaybackState.fromJson(map);
}
Expand Down Expand Up @@ -87,6 +89,8 @@ class PlayerEndpoint extends _MeEndpointBase {
/// from the context's current track.
/// [retrievePlaybackState] is optional. If true, the current playback state
/// will be retrieved. Defaults to true.
@Deprecated(
"Use `startWithTracks()` or `startWithContext()` to start a new context and resume() instead")
Future<PlaybackState?> startOrResume(
{String? deviceId,
StartOrResumeOptions? options,
Expand All @@ -95,19 +99,74 @@ class PlayerEndpoint extends _MeEndpointBase {
var json = jsonEncode(body ?? '');

await _api._put(
'$_path/play?' + _buildQuery({'device_id': deviceId}), json);
'$_path/play?${_buildQuery({'device_id': deviceId})}', json);

return retrievePlaybackState ? playbackState() : null;
}

/// Start a new playback context with given [trackUris] and with given optional
/// [deviceId]. If not provided, the user's currently active device
/// is the target. Playback can also start at [positionMs], which is set to `0`
/// by default.
/// [retrievePlaybackState] is optional. If `true`, the current [PlaybackState]
/// will be retrieved. Default's to `true`.
///
/// Note: Before starting a new playback context check the [playbackState]
/// if necessary before [resume]ing, otherwise you overwrite the current
/// context.
Future<PlaybackState?> startWithTracks(List<String> trackUris,
{String? deviceId,
int positionMs = 0,
bool retrievePlaybackState = true}) async {
assert(trackUris.isNotEmpty, 'Cannot start playback with empty track uris');
assert(positionMs >= 0, 'Position must be greater than or equal to 0');

var options = StartOrResumeOptions(uris: trackUris, positionMs: positionMs);
return startOrResume(
deviceId: deviceId,
options: options,
retrievePlaybackState: retrievePlaybackState);
}

/// Start a new playback context (album, playlist) with given a [contextUri].
/// and given optional [deviceId]. If not provided, the user's currently active
/// device is the target. Set [Offset] to start playback at a specific point.
/// [retrievePlaybackState] is optional. If `true`, the current [PlaybackState]
/// will be retrieved. Default's to `true`.
///
/// Note: Before starting a new playback context check the [playbackState]
/// if necessary before [resume]ing, otherwise you overwrite the current
/// context.
Future<PlaybackState?> startWithContext(String contextUri,
{String? deviceId,
Offset? offset,
bool retrievePlaybackState = true}) async {
assert(
contextUri.isNotEmpty, 'Cannot start playback with empty context uri');
var options = StartOrResumeOptions(contextUri: contextUri, offset: offset);
return startOrResume(
deviceId: deviceId,
options: options,
retrievePlaybackState: retrievePlaybackState);
}

/// Resume current playback on the user's active device if not specifically
/// set with [deviceId].
/// [retrievePlaybackState] is optional. If `true`, the current [PlaybackState]
/// will be retrieved. Default's to `true`.
Future<PlaybackState?> resume(
{String? deviceId, bool retrievePlaybackState = true}) async =>
startOrResume(
deviceId: deviceId, retrievePlaybackState: retrievePlaybackState);

/// Pause playback on the user's account.
/// [deviceId] is optional. If not provided, the user's currently active device
/// is the target.
/// [retrievePlaybackState] is optional. If true, the current playback state
/// will be retrieved. Defaults to true.
Future<PlaybackState?> pause(
{String? deviceId, bool retrievePlaybackState = true}) async {
await _api._put('$_path/pause?' + _buildQuery({'device_id': deviceId}));
await _api._put('$_path/pause?${_buildQuery({'device_id': deviceId})}');

return retrievePlaybackState ? playbackState() : null;
}
Expand All @@ -119,7 +178,7 @@ class PlayerEndpoint extends _MeEndpointBase {
/// will be retrieved. Defaults to true.
Future<PlaybackState?> previous(
{String? deviceId, bool retrievePlaybackState = true}) async {
await _api._post('$_path/previous?' + _buildQuery({'device_id': deviceId}));
await _api._post('$_path/previous?${_buildQuery({'device_id': deviceId})}');

return retrievePlaybackState ? playbackState() : null;
}
Expand All @@ -131,7 +190,7 @@ class PlayerEndpoint extends _MeEndpointBase {
/// will be retrieved. Defaults to true.
Future<PlaybackState?> next(
{String? deviceId, bool retrievePlaybackState = true}) async {
await _api._post('$_path/next?' + _buildQuery({'device_id': deviceId}));
await _api._post('$_path/next?${_buildQuery({'device_id': deviceId})}');

return retrievePlaybackState ? playbackState() : null;
}
Expand All @@ -145,8 +204,10 @@ class PlayerEndpoint extends _MeEndpointBase {
Future<PlaybackState?> seek(int positionMs,
{String? deviceId, bool retrievePlaybackState = true}) async {
assert(positionMs >= 0, 'positionMs must be greater or equal to 0');
await _api._put('$_path/seek?' +
_buildQuery({'position_ms': positionMs, 'device_id': deviceId}));
await _api._put('$_path/seek?${_buildQuery({
'position_ms': positionMs,
'device_id': deviceId
})}');

return retrievePlaybackState ? playbackState() : null;
}
Expand All @@ -160,11 +221,10 @@ class PlayerEndpoint extends _MeEndpointBase {
/// will be retrieved. Defaults to true.
Future<PlaybackState?> repeat(RepeatState state,
{String? deviceId, bool retrievePlaybackState = true}) async {
await _api._put('$_path/repeat?' +
_buildQuery({
await _api._put('$_path/repeat?${_buildQuery({
'state': state.toString().split('.').last,
'device_id': deviceId
}));
})}');

return retrievePlaybackState ? playbackState() : null;
}
Expand All @@ -180,13 +240,15 @@ class PlayerEndpoint extends _MeEndpointBase {
{String? deviceId, bool retrievePlaybackState = true}) async {
assert(volumePercent >= 0 && volumePercent <= 100,
'Volume must be between 0 and 100');
await _api._put('$_path/volume?' +
_buildQuery({'volume_percent': volumePercent, 'device_id': deviceId}));
await _api._put('$_path/volume?${_buildQuery({
'volume_percent': volumePercent,
'device_id': deviceId
})}');

return retrievePlaybackState ? playbackState() : null;
}

/// Transfer playback to a new device and determine if
/// Transfer playback to a new device and determine if
/// it should start [play]ing. Default is `true`.
///
/// The `AuthorizationScope.connect.modifyPlaybackState` needs to be set.
Expand Down
4 changes: 2 additions & 2 deletions lib/src/models/_models.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 8 additions & 7 deletions lib/src/models/player.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class PlaybackState extends Object {
PlayerContext? context;

/// Progress into the currently playing track. Can be `null`.
int? progress_ms;
@JsonKey(name: 'progress_ms')
int? progressMs;

/// The currently playing track. Can be `null`.
Track? item;
Expand All @@ -40,7 +41,7 @@ class PlaybackState extends Object {
@JsonKey(name: 'shuffle_state', defaultValue: false)
bool? isShuffling;

/// The repeat state. Can be [RepeatState.off], [RepeatState.track] or
/// The repeat state. Can be [RepeatState.off], [RepeatState.track] or
/// [RepeatState.context]
@JsonKey(name: 'repeat_state', defaultValue: RepeatState.off)
RepeatState? repeatState;
Expand All @@ -55,7 +56,8 @@ class PlayerContext extends Object {
_$PlayerContextFromJson(json);

/// The external_urls of the context, or `null` if not available.
ExternalUrls? external_urls;
@JsonKey(name: 'external_urls')
ExternalUrls? externalUrls;

/// The href of the context, or `null` if not available.
String? href;
Expand Down Expand Up @@ -125,7 +127,7 @@ class StartOrResumeOptions extends Object {

/// Optional. A JSON array of the Spotify track URIs to play.
///
/// Example:
/// Example:
/// ```json
/// [
/// "spotify:track:4iV5W9uYEdYUVa79Axb7Rh",
Expand All @@ -148,9 +150,8 @@ class StartOrResumeOptions extends Object {

Map<String, dynamic> toJson() => _$StartOrResumeOptionsToJson(this);

static Map<String, dynamic> _offsetToJson(Offset? offset) {
return offset?.toJson() ?? {};
}
static Map<String, dynamic> _offsetToJson(Offset? offset) =>
offset?.toJson() ?? {};
}

abstract class Offset {
Expand Down

0 comments on commit c8bc7c6

Please sign in to comment.