Browse Source

chore: 更新 Flutter Web 插件以使用 js_interop 和 web 包

迁移 Spotify SDK Web 插件从 dart:html 和 js 包到 dart:js_interop 和 web 包,以适配 Dart 3.7 的 JS 互操作改进。主要更改包括:
- 更新 pubspec.yaml 中的 SDK 约束和依赖项
- 使用 extension types 重写 JS 类型定义
- 用新的互操作方法替换 allowInterop 和 promiseToFuture
- 将 DOM 操作迁移到 web 包 API
- 修复类型转换和事件处理逻辑
weicu
lxm 7 months ago
parent
commit
c29822ad85
  1. 243
      local_plugins/spotify_sdk/lib/spotify_sdk_web.dart
  2. 4
      local_plugins/spotify_sdk/pubspec.yaml

243
local_plugins/spotify_sdk/lib/spotify_sdk_web.dart

@ -5,16 +5,15 @@ import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:core'; import 'dart:core';
import 'dart:developer'; import 'dart:developer';
import 'dart:html'; import 'dart:js_interop';
import 'dart:math' as math; import 'dart:math' as math;
import 'package:crypto/crypto.dart'; import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:js/js.dart';
import 'package:js/js_util.dart';
import 'package:synchronized/synchronized.dart' as synchronized; import 'package:synchronized/synchronized.dart' as synchronized;
import 'package:web/web.dart' as web;
import 'enums/repeat_mode_enum.dart'; import 'enums/repeat_mode_enum.dart';
import 'models/album.dart'; import 'models/album.dart';
@ -52,6 +51,9 @@ class SpotifySdkPlugin {
/// Current Spotify SDK player instance. /// Current Spotify SDK player instance.
Player? _currentPlayer; Player? _currentPlayer;
/// Current device ID (存储在 Dart 侧,因为 extension type 不支持实例字段)
String? _currentDeviceID;
/// Current Spotify auth token. /// Current Spotify auth token.
SpotifyToken? _spotifyToken; SpotifyToken? _spotifyToken;
@ -172,18 +174,19 @@ class SpotifySdkPlugin {
// create player // create player
_currentPlayer = Player(PlayerOptions( _currentPlayer = Player(PlayerOptions(
name: playerName, name: playerName,
getOAuthToken: allowInterop((Function callback, t) { getOAuthToken: ((JSAny? callback, JSAny? t) {
_getSpotifyAuthToken().then((value) { _getSpotifyAuthToken().then((value) {
callback(value); (callback as JSFunction).callAsFunction(null, value.toJS);
}); });
}))); }).toJS));
_registerPlayerEvents(_currentPlayer!); _registerPlayerEvents(_currentPlayer!);
var result = await promiseToFuture(_currentPlayer!.connect()); var result =
(await _currentPlayer!.connect().toDart).toDart;
if (result == true) { if (result == true) {
// wait for the confirmation // wait for the confirmation
num time = 0; num time = 0;
while (_currentPlayer!.deviceID == null) { while (_currentDeviceID == null) {
await Future.delayed(const Duration(milliseconds: 200)); await Future.delayed(const Duration(milliseconds: 200));
time += 200; time += 200;
if (time > 10000) { if (time > 10000) {
@ -242,19 +245,19 @@ class SpotifySdkPlugin {
call.arguments[ParamNames.repeatMode] as RepeatMode?); call.arguments[ParamNames.repeatMode] as RepeatMode?);
break; break;
case MethodNames.resume: case MethodNames.resume:
await promiseToFuture(_currentPlayer?.resume()); await _currentPlayer!.resume().toDart;
break; break;
case MethodNames.pause: case MethodNames.pause:
await promiseToFuture(_currentPlayer?.pause()); await _currentPlayer!.pause().toDart;
break; break;
case MethodNames.skipNext: case MethodNames.skipNext:
await promiseToFuture(_currentPlayer?.nextTrack()); await _currentPlayer!.nextTrack().toDart;
break; break;
case MethodNames.skipPrevious: case MethodNames.skipPrevious:
await promiseToFuture(_currentPlayer?.previousTrack()); await _currentPlayer!.previousTrack().toDart;
break; break;
case MethodNames.getPlayerState: case MethodNames.getPlayerState:
var stateRaw = await promiseToFuture(_currentPlayer?.getCurrentState()) var stateRaw = (await _currentPlayer!.getCurrentState().toDart)
as WebPlaybackState?; as WebPlaybackState?;
if (stateRaw == null) return null; if (stateRaw == null) return null;
return jsonEncode(toPlayerState(stateRaw)!.toJson()); return jsonEncode(toPlayerState(stateRaw)!.toJson());
@ -272,10 +275,13 @@ class SpotifySdkPlugin {
log('Loading Spotify SDK...'); log('Loading Spotify SDK...');
// link spotify ready function // link spotify ready function
_onSpotifyWebPlaybackSDKReady = allowInterop(_onSpotifyInitialized); _onSpotifyWebPlaybackSDKReady = _onSpotifyInitialized.toJS;
// load spotify sdk // load spotify sdk
querySelector('body')!.children.add(ScriptElement()..src = spotifySdkUrl); final script =
web.document.createElement('script') as web.HTMLScriptElement;
script.src = spotifySdkUrl;
web.document.body!.appendChild(script);
// wait for initialization // wait for initialization
while (_sdkLoaded == false) { while (_sdkLoaded == false) {
@ -294,33 +300,37 @@ class SpotifySdkPlugin {
void _registerPlayerEvents(Player player) { void _registerPlayerEvents(Player player) {
// player state // player state
player.addListener('player_state_changed', player.addListener('player_state_changed',
allowInterop((WebPlaybackState? state) { ((JSAny? stateObj) {
if (state == null) return; if (stateObj == null) return;
var state = stateObj as WebPlaybackState;
playerStateEventController playerStateEventController
.add(jsonEncode(toPlayerState(state)!.toJson())); .add(jsonEncode(toPlayerState(state)!.toJson()));
playerContextEventController playerContextEventController
.add(jsonEncode(toPlayerContext(state)!.toJson())); .add(jsonEncode(toPlayerContext(state)!.toJson()));
})); }).toJS);
// ready/not ready // ready/not ready
player.addListener('ready', allowInterop((WebPlaybackPlayer player) { player.addListener('ready', ((JSAny? playerObj) {
var p = playerObj as WebPlaybackPlayer;
log('Spotify SDK ready!'); log('Spotify SDK ready!');
_onSpotifyConnected(player.device_id); _onSpotifyConnected(p.device_id);
})); }).toJS);
player.addListener('not_ready', allowInterop((event) { player.addListener('not_ready', ((JSAny? event) {
_onSpotifyDisconnected( _onSpotifyDisconnected(
errorCode: 'Spotify SDK not ready', errorCode: 'Spotify SDK not ready',
errorDetails: 'Spotify SDK is not ready to take requests'); errorDetails: 'Spotify SDK is not ready to take requests');
})); }).toJS);
// errors // errors
player.addListener('initialization_error', player.addListener('initialization_error',
allowInterop((WebPlaybackError error) { ((JSAny? errorObj) {
var error = errorObj as WebPlaybackError;
_onSpotifyDisconnected( _onSpotifyDisconnected(
errorCode: 'Initialization Error', errorDetails: error.message); errorCode: 'Initialization Error', errorDetails: error.message);
})); }).toJS);
player.addListener('authentication_error', player.addListener('authentication_error',
allowInterop((WebPlaybackError error) { ((JSAny? errorObj) {
var error = errorObj as WebPlaybackError;
// If the error is due to browser security, don't disconnect. // If the error is due to browser security, don't disconnect.
// The user needs to interact with the SDK to trigger media activation. // The user needs to interact with the SDK to trigger media activation.
// https://developer.spotify.com/documentation/web-playback-sdk/quick-start/#mobile-support // https://developer.spotify.com/documentation/web-playback-sdk/quick-start/#mobile-support
@ -330,14 +340,16 @@ class SpotifySdkPlugin {
} }
_onSpotifyDisconnected( _onSpotifyDisconnected(
errorCode: 'Authentication Error', errorDetails: error.message); errorCode: 'Authentication Error', errorDetails: error.message);
})); }).toJS);
player.addListener('account_error', allowInterop((WebPlaybackError error) { player.addListener('account_error', ((JSAny? errorObj) {
var error = errorObj as WebPlaybackError;
_onSpotifyDisconnected( _onSpotifyDisconnected(
errorCode: 'Account Error', errorDetails: error.message); errorCode: 'Account Error', errorDetails: error.message);
})); }).toJS);
player.addListener('playback_error', allowInterop((WebPlaybackError error) { player.addListener('playback_error', ((JSAny? errorObj) {
var error = errorObj as WebPlaybackError;
log('playback_error: ${error.message}'); log('playback_error: ${error.message}');
})); }).toJS);
} }
/// Called when the Spotify SDK is first loaded. /// Called when the Spotify SDK is first loaded.
@ -347,7 +359,7 @@ class SpotifySdkPlugin {
/// Called when the plugin successfully connects to the spotify web sdk. /// Called when the plugin successfully connects to the spotify web sdk.
void _onSpotifyConnected(String deviceId) { void _onSpotifyConnected(String deviceId) {
_currentPlayer!.deviceID = deviceId; _currentDeviceID = deviceId;
// emit connected event // emit connected event
connectionStatusEventController.add(jsonEncode(ConnectionStatus( connectionStatusEventController.add(jsonEncode(ConnectionStatus(
@ -362,6 +374,7 @@ class SpotifySdkPlugin {
void _onSpotifyDisconnected({String? errorCode, String? errorDetails}) { void _onSpotifyDisconnected({String? errorCode, String? errorDetails}) {
_unregisterPlayerEvents(_currentPlayer!); _unregisterPlayerEvents(_currentPlayer!);
_currentPlayer = null; _currentPlayer = null;
_currentDeviceID = null;
if (errorCode != null) { if (errorCode != null) {
// disconnected due to error // disconnected due to error
@ -445,27 +458,32 @@ class SpotifySdkPlugin {
); );
// opening auth window // opening auth window
var authPopup = window.open( var authPopup = web.window.open(
authorizationUri.toString(), authorizationUri.toString(),
'Spotify Authorization', 'Spotify Authorization',
); );
String? message; String? message;
var sub = window.onMessage.listen(allowInterop((event) { final messageHandler = ((JSAny? e) {
message = event.data.toString(); final event = e as web.MessageEvent;
// ensure the message contains auth code if (event.data != null && event.data!.isA<JSString>()) {
if (!message!.startsWith('?code=')) { final str = (event.data as JSString).toDart;
message = null; // ensure the message contains auth code
if (str.startsWith('?code=')) {
message = str;
}
} }
})); }).toJS;
web.window.addEventListener('message', messageHandler);
// loop and wait for auth // loop and wait for auth
while (authPopup.closed == false && message == null) { while (authPopup?.closed == false && message == null) {
// await response from the window // await response from the window
await Future.delayed(const Duration(milliseconds: 250)); await Future.delayed(const Duration(milliseconds: 250));
} }
// error if window closed by user // error if window closed by user
if (message == null) { if (message == null) {
web.window.removeEventListener('message', messageHandler);
throw PlatformException( throw PlatformException(
message: 'User closed authentication window', message: 'User closed authentication window',
code: 'Authentication Error'); code: 'Authentication Error');
@ -476,6 +494,7 @@ class SpotifySdkPlugin {
// check if state is the same // check if state is the same
if (state != parsedMessage.queryParameters['state']) { if (state != parsedMessage.queryParameters['state']) {
web.window.removeEventListener('message', messageHandler);
throw PlatformException( throw PlatformException(
message: 'Invalid state', code: 'Authentication Error'); message: 'Invalid state', code: 'Authentication Error');
} }
@ -483,16 +502,17 @@ class SpotifySdkPlugin {
// check for error // check for error
if (parsedMessage.queryParameters['error'] != null || if (parsedMessage.queryParameters['error'] != null ||
parsedMessage.queryParameters['code'] == null) { parsedMessage.queryParameters['code'] == null) {
web.window.removeEventListener('message', messageHandler);
throw PlatformException( throw PlatformException(
message: "${parsedMessage.queryParameters['error']}", message: "${parsedMessage.queryParameters['error']}",
code: 'Authentication Error'); code: 'Authentication Error');
} }
// close auth window // close auth window
if (authPopup.closed == false) { if (authPopup?.closed == false) {
authPopup.close(); authPopup?.close();
} }
await sub.cancel(); web.window.removeEventListener('message', messageHandler);
// exchange auth code for access and refresh tokens // exchange auth code for access and refresh tokens
dynamic authResponse; dynamic authResponse;
@ -613,7 +633,7 @@ class SpotifySdkPlugin {
/// Starts track playback on the device. /// Starts track playback on the device.
Future _play(String? uri) async { Future _play(String? uri) async {
if (_currentPlayer?.deviceID == null) { if (_currentDeviceID == null) {
throw PlatformException( throw PlatformException(
message: 'Spotify player not connected!', code: 'Playback Error'); message: 'Spotify player not connected!', code: 'Playback Error');
} }
@ -623,7 +643,7 @@ class SpotifySdkPlugin {
data: { data: {
'uris': [uri] 'uris': [uri]
}, },
queryParameters: {'device_id': _currentPlayer!.deviceID}, queryParameters: {'device_id': _currentDeviceID},
options: Options( options: Options(
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -635,14 +655,14 @@ class SpotifySdkPlugin {
/// Adds a given track to the playback queue. /// Adds a given track to the playback queue.
Future _queue(String? uri) async { Future _queue(String? uri) async {
if (_currentPlayer?.deviceID == null) { if (_currentDeviceID == null) {
throw PlatformException( throw PlatformException(
message: 'Spotify player not connected!', code: 'Playback Error'); message: 'Spotify player not connected!', code: 'Playback Error');
} }
await _dio.post( await _dio.post(
'/queue', '/queue',
queryParameters: {'uri': uri, 'device_id': _currentPlayer!.deviceID}, queryParameters: {'uri': uri, 'device_id': _currentDeviceID},
options: Options( options: Options(
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -654,7 +674,7 @@ class SpotifySdkPlugin {
/// Sets whether shuffle should be enabled. /// Sets whether shuffle should be enabled.
Future _setShuffle(bool? shuffleEnabled) async { Future _setShuffle(bool? shuffleEnabled) async {
if (_currentPlayer?.deviceID == null) { if (_currentDeviceID == null) {
throw PlatformException( throw PlatformException(
message: 'Spotify player not connected!', code: 'Set Shuffle Error'); message: 'Spotify player not connected!', code: 'Set Shuffle Error');
} }
@ -663,7 +683,7 @@ class SpotifySdkPlugin {
'/shuffle', '/shuffle',
queryParameters: { queryParameters: {
'state': shuffleEnabled, 'state': shuffleEnabled,
'device_id': _currentPlayer!.deviceID 'device_id': _currentDeviceID
}, },
options: Options( options: Options(
headers: { headers: {
@ -676,7 +696,7 @@ class SpotifySdkPlugin {
/// Sets the repeat mode. /// Sets the repeat mode.
Future _setRepeatMode(RepeatMode? repeatMode) async { Future _setRepeatMode(RepeatMode? repeatMode) async {
if (_currentPlayer?.deviceID == null) { if (_currentDeviceID == null) {
throw PlatformException( throw PlatformException(
message: 'Spotify player not connected!', message: 'Spotify player not connected!',
code: 'Set Repeat Mode Error'); code: 'Set Repeat Mode Error');
@ -686,7 +706,7 @@ class SpotifySdkPlugin {
'/repeat', '/repeat',
queryParameters: { queryParameters: {
'state': repeatMode.toString().substring(11), 'state': repeatMode.toString().substring(11),
'device_id': _currentPlayer!.deviceID 'device_id': _currentDeviceID
}, },
options: Options( options: Options(
headers: { headers: {
@ -699,14 +719,14 @@ class SpotifySdkPlugin {
/// Toggles shuffle on the current player. /// Toggles shuffle on the current player.
Future toggleShuffle({bool? state}) async { Future toggleShuffle({bool? state}) async {
if (_currentPlayer?.deviceID == null) { if (_currentDeviceID == null) {
throw PlatformException( throw PlatformException(
message: 'Spotify player not connected!', code: 'Playback Error'); message: 'Spotify player not connected!', code: 'Playback Error');
} }
await _dio.put( await _dio.put(
'/shuffle', '/shuffle',
queryParameters: {'state': state, 'device_id': _currentPlayer!.deviceID}, queryParameters: {'state': state, 'device_id': _currentDeviceID},
options: Options( options: Options(
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -718,14 +738,14 @@ class SpotifySdkPlugin {
/// Toggles repeat on the current player. /// Toggles repeat on the current player.
Future toggleRepeat({bool? state}) async { Future toggleRepeat({bool? state}) async {
if (_currentPlayer?.deviceID == null) { if (_currentDeviceID == null) {
throw PlatformException( throw PlatformException(
message: 'Spotify player not connected!', code: 'Playback Error'); message: 'Spotify player not connected!', code: 'Playback Error');
} }
await _dio.put( await _dio.put(
'/repeat', '/repeat',
queryParameters: {'state': state, 'device_id': _currentPlayer!.deviceID}, queryParameters: {'state': state, 'device_id': _currentDeviceID},
options: Options( options: Options(
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@ -744,7 +764,8 @@ class SpotifySdkPlugin {
var artists = <Artist>[]; var artists = <Artist>[];
if (trackRaw != null) { if (trackRaw != null) {
for (var artist in trackRaw.artists) { for (var i = 0; i < trackRaw.artists.length; i++) {
var artist = trackRaw.artists[i] as WebPlaybackArtist;
artists.add(Artist(artist.name, artist.uri)); artists.add(Artist(artist.name, artist.uri));
} }
} }
@ -770,7 +791,7 @@ class SpotifySdkPlugin {
artists[0], artists[0],
artists, artists,
-1, -1,
ImageUri(albumRaw.images[0].url), ImageUri((albumRaw.images[0] as WebPlaybackAlbumImage).url),
trackRaw.name, trackRaw.name,
trackRaw.uri, trackRaw.uri,
trackRaw.linked_from.uri, trackRaw.linked_from.uri,
@ -806,87 +827,79 @@ class SpotifySdkPlugin {
/// Allows assigning the function onSpotifyWebPlaybackSDKReady /// Allows assigning the function onSpotifyWebPlaybackSDKReady
/// to be callable from `window.onSpotifyWebPlaybackSDKReady()` /// to be callable from `window.onSpotifyWebPlaybackSDKReady()`
@JS('onSpotifyWebPlaybackSDKReady') @JS('onSpotifyWebPlaybackSDKReady')
external set _onSpotifyWebPlaybackSDKReady(void Function()? f); external set _onSpotifyWebPlaybackSDKReady(JSFunction? f);
/// Allows assigning the function onSpotifyWebPlaybackSDKReady /// Allows checking if onSpotifyWebPlaybackSDKReady has been set
/// to be callable from `window.onSpotifyWebPlaybackSDKReady()`
@JS('onSpotifyWebPlaybackSDKReady') @JS('onSpotifyWebPlaybackSDKReady')
external void Function()? get _onSpotifyWebPlaybackSDKReady; external JSFunction? get _onSpotifyWebPlaybackSDKReady;
/// Spotify Player Object /// Spotify Player Object
@JS('Spotify.Player') @JS('Spotify.Player')
class Player { extension type Player._(JSObject _) implements JSObject {
/// Device id of the player.
String? deviceID;
/// The main constructor for initializing the Web Playback SDK. /// The main constructor for initializing the Web Playback SDK.
/// It should contain an object with the player name, volume and access token. /// It should contain an object with the player name, volume and access token.
external Player(PlayerOptions options); external Player(PlayerOptions options);
/// Connects Web Playback SDK instance to Spotify /// Connects Web Playback SDK instance to Spotify
/// with the credentials provided during initialization. /// with the credentials provided during initialization.
external dynamic connect(); external JSPromise<JSBoolean> connect();
/// Closes the current session that Web Playback SDK has with Spotify. /// Closes the current session that Web Playback SDK has with Spotify.
external void disconnect(); external void disconnect();
/// Create a new event listener in the Web Playback SDK. /// Create a new event listener in the Web Playback SDK.
external void addListener(String type, Function callback); external void addListener(String type, JSFunction callback);
/// Remove an event listener in the Web Playback SDK. /// Remove an event listener in the Web Playback SDK.
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
external void removeListener(String event_name); external void removeListener(String event_name);
/// Collect metadata on local playback. /// Collect metadata on local playback.
external dynamic getCurrentState(); external JSPromise<JSAny?> getCurrentState();
/// Rename the Spotify Player device. /// Rename the Spotify Player device.
/// This is visible across all Spotify Connect devices. /// This is visible across all Spotify Connect devices.
external dynamic setName(String name); external JSPromise setName(String name);
/// Set the local volume for the Web Playback SDK. /// Set the local volume for the Web Playback SDK.
external dynamic setVolume(double volume); external JSPromise setVolume(double volume);
/// Pause the local playback. /// Pause the local playback.
external dynamic pause(); external JSPromise pause();
/// Resume the local playback. /// Resume the local playback.
external dynamic resume(); external JSPromise resume();
/// Resume/pause the local playback. /// Resume/pause the local playback.
external dynamic togglePlay(); external JSPromise togglePlay();
/// Seek to a position in the current track in local playback. /// Seek to a position in the current track in local playback.
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
external dynamic seek(int position_ms); external JSPromise seek(int position_ms);
/// Switch to the previous track in local playback. /// Switch to the previous track in local playback.
external dynamic previousTrack(); external JSPromise previousTrack();
/// Skip to the next track in local playback. /// Skip to the next track in local playback.
external dynamic nextTrack(); external JSPromise nextTrack();
} }
/// Spotify player options object /// Spotify player options object
@JS() extension type PlayerOptions._(JSObject _) implements JSObject {
@anonymous
class PlayerOptions {
// ignore: public_member_api_docs // ignore: public_member_api_docs
external String get name; external String get name;
// ignore: public_member_api_docs // ignore: public_member_api_docs
external Function get getOAuthToken; external JSFunction get getOAuthToken;
// ignore: public_member_api_docs // ignore: public_member_api_docs
external double get volume; external double get volume;
// ignore: public_member_api_docs // ignore: public_member_api_docs
external factory PlayerOptions( external factory PlayerOptions(
{String? name, Function? getOAuthToken, double? volume}); {String? name, JSFunction? getOAuthToken, double? volume});
} }
/// Spotify playback object /// Spotify playback object
@JS() extension type WebPlaybackPlayer._(JSObject _) implements JSObject {
@anonymous
class WebPlaybackPlayer {
// ignore: public_member_api_docs, non_constant_identifier_names // ignore: public_member_api_docs, non_constant_identifier_names
external String get device_id; external String get device_id;
// ignore: public_member_api_docs, non_constant_identifier_names // ignore: public_member_api_docs, non_constant_identifier_names
@ -894,9 +907,7 @@ class WebPlaybackPlayer {
} }
/// Spotify playback state object /// Spotify playback state object
@JS() extension type WebPlaybackState._(JSObject _) implements JSObject {
@anonymous
class WebPlaybackState {
// ignore: public_member_api_docs // ignore: public_member_api_docs
external WebPlayerContext get context; external WebPlayerContext get context;
// ignore: public_member_api_docs // ignore: public_member_api_docs
@ -916,7 +927,7 @@ class WebPlaybackState {
external factory WebPlaybackState( external factory WebPlaybackState(
{WebPlayerContext? context, {WebPlayerContext? context,
WebPlayerDisallows? disallows, WebPlayerDisallows? disallows,
bool? paysed, bool? paused,
int? position, int? position,
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
int? repeat_mode, int? repeat_mode,
@ -926,9 +937,7 @@ class WebPlaybackState {
} }
/// Spotify player context object /// Spotify player context object
@JS() extension type WebPlayerContext._(JSObject _) implements JSObject {
@anonymous
class WebPlayerContext {
// ignore: public_member_api_docs // ignore: public_member_api_docs
external String get uri; external String get uri;
// ignore: public_member_api_docs // ignore: public_member_api_docs
@ -940,9 +949,7 @@ class WebPlayerContext {
} }
/// Spotify player context metadata object /// Spotify player context metadata object
@JS() extension type WebPlayerContextMetadata._(JSObject _) implements JSObject {
@anonymous
class WebPlayerContextMetadata {
// ignore: public_member_api_docs // ignore: public_member_api_docs
external String get title; external String get title;
// ignore: public_member_api_docs // ignore: public_member_api_docs
@ -956,9 +963,7 @@ class WebPlayerContextMetadata {
} }
/// Spotify player disallows object /// Spotify player disallows object
@JS() extension type WebPlayerDisallows._(JSObject _) implements JSObject {
@anonymous
class WebPlayerDisallows {
// ignore: public_member_api_docs // ignore: public_member_api_docs
external bool get pausing; external bool get pausing;
// ignore: public_member_api_docs, non_constant_identifier_names // ignore: public_member_api_docs, non_constant_identifier_names
@ -990,30 +995,26 @@ class WebPlayerDisallows {
} }
/// Spotify player track window object /// Spotify player track window object
@JS() extension type WebPlayerTrackWindow._(JSObject _) implements JSObject {
@anonymous
class WebPlayerTrackWindow {
// ignore: public_member_api_docs, non_constant_identifier_names // ignore: public_member_api_docs, non_constant_identifier_names
external WebPlaybackTrack? get current_track; external WebPlaybackTrack? get current_track;
// ignore: public_member_api_docs, non_constant_identifier_names // ignore: public_member_api_docs, non_constant_identifier_names
external List<WebPlaybackTrack>? get previous_tracks; external JSArray? get previous_tracks;
// ignore: public_member_api_docs, non_constant_identifier_names // ignore: public_member_api_docs, non_constant_identifier_names
external List<WebPlaybackTrack>? get next_tracks; external JSArray? get next_tracks;
// ignore: public_member_api_docs // ignore: public_member_api_docs
external factory WebPlayerTrackWindow( external factory WebPlayerTrackWindow(
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
{WebPlaybackTrack? current_track, {WebPlaybackTrack? current_track,
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
List<WebPlaybackTrack>? previous_tracks, JSArray? previous_tracks,
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
List<WebPlaybackTrack>? next_tracks}); JSArray? next_tracks});
} }
/// Spotify playback track object /// Spotify playback track object
@JS() extension type WebPlaybackTrack._(JSObject _) implements JSObject {
@anonymous
class WebPlaybackTrack {
// ignore: public_member_api_docs // ignore: public_member_api_docs
external String get uri; external String get uri;
// ignore: public_member_api_docs // ignore: public_member_api_docs
@ -1029,7 +1030,7 @@ class WebPlaybackTrack {
// ignore: public_member_api_docs // ignore: public_member_api_docs
external WebPlaybackAlbum get album; external WebPlaybackAlbum get album;
// ignore: public_member_api_docs // ignore: public_member_api_docs
external List<WebPlaybackArtist> get artists; external JSArray get artists;
// ignore: public_member_api_docs // ignore: public_member_api_docs
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
external WebLinkedFrom get linked_from; external WebLinkedFrom get linked_from;
@ -1045,31 +1046,27 @@ class WebPlaybackTrack {
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
bool? is_playable, bool? is_playable,
WebPlaybackAlbum? album, WebPlaybackAlbum? album,
List<WebPlaybackArtist>? artists, JSArray? artists,
// ignore: non_constant_identifier_names // ignore: non_constant_identifier_names
WebLinkedFrom? linked_from}); WebLinkedFrom? linked_from});
} }
/// Spotify playback album object /// Spotify playback album object
@JS() extension type WebPlaybackAlbum._(JSObject _) implements JSObject {
@anonymous
class WebPlaybackAlbum {
// ignore: public_member_api_docs // ignore: public_member_api_docs
external String get uri; external String get uri;
// ignore: public_member_api_docs // ignore: public_member_api_docs
external String get name; external String get name;
// ignore: public_member_api_docs // ignore: public_member_api_docs
external List<WebPlaybackAlbumImage> get images; external JSArray get images;
// ignore: public_member_api_docs // ignore: public_member_api_docs
external factory WebPlaybackAlbum( external factory WebPlaybackAlbum(
{String? uri, String? name, List<WebPlaybackAlbumImage>? images}); {String? uri, String? name, JSArray? images});
} }
/// Spotify playback album object /// Spotify playback album object
@JS() extension type WebLinkedFrom._(JSObject _) implements JSObject {
@anonymous
class WebLinkedFrom {
// ignore: public_member_api_docs // ignore: public_member_api_docs
external String get uri; external String get uri;
// ignore: public_member_api_docs // ignore: public_member_api_docs
@ -1080,9 +1077,7 @@ class WebLinkedFrom {
} }
/// Spotify artist object /// Spotify artist object
@JS() extension type WebPlaybackArtist._(JSObject _) implements JSObject {
@anonymous
class WebPlaybackArtist {
// ignore: public_member_api_docs // ignore: public_member_api_docs
external String get uri; external String get uri;
// ignore: public_member_api_docs // ignore: public_member_api_docs
@ -1093,9 +1088,7 @@ class WebPlaybackArtist {
} }
/// Spotify album image object /// Spotify album image object
@JS() extension type WebPlaybackAlbumImage._(JSObject _) implements JSObject {
@anonymous
class WebPlaybackAlbumImage {
// ignore: public_member_api_docs // ignore: public_member_api_docs
external String get url; external String get url;
@ -1104,9 +1097,7 @@ class WebPlaybackAlbumImage {
} }
/// Spotify playback error object /// Spotify playback error object
@JS() extension type WebPlaybackError._(JSObject _) implements JSObject {
@anonymous
class WebPlaybackError {
// ignore: public_member_api_docs // ignore: public_member_api_docs
external String get message; external String get message;

4
local_plugins/spotify_sdk/pubspec.yaml

@ -5,7 +5,7 @@ homepage: https://github.com/brim-borium/spotify_sdk
issue_tracker: https://github.com/brim-borium/spotify_sdk/issues issue_tracker: https://github.com/brim-borium/spotify_sdk/issues
environment: environment:
sdk: ^3.5.0 sdk: ^3.7.0
flutter: '>=3.3.0' flutter: '>=3.3.0'
dependencies: dependencies:
@ -16,7 +16,7 @@ dependencies:
logger: ^2.4.0 logger: ^2.4.0
dio: ^5.7.0 dio: ^5.7.0
json_annotation: ^4.9.0 json_annotation: ^4.9.0
js: ">=0.6.7 <0.8.0" web: ^1.1.0
crypto: ^3.0.5 crypto: ^3.0.5
synchronized: ^3.3.0+3 synchronized: ^3.3.0+3
http: ^1.2.2 http: ^1.2.2

Loading…
Cancel
Save