From ed4f6b297ad7ef27749a7bc963f0ba5392eccdc0 Mon Sep 17 00:00:00 2001 From: boyan Date: Sun, 16 Feb 2020 16:57:15 +0800 Subject: [PATCH] refactor 2 --- android/gradle.properties | 4 +- lib/component/player/bottom_player_bar.dart | 4 +- lib/component/player/interceptors.dart | 6 +- lib/component/player/player.dart | 43 +++--------- lib/model/music.dart | 72 ++++++--------------- lib/pages/comments/page_comment.dart | 33 ++++------ lib/pages/page_playing_list.dart | 5 +- lib/pages/player/cover.dart | 9 +-- lib/pages/player/page_playing.dart | 2 +- lib/pages/playlist/music_list.dart | 12 ++-- test/widget_test_context.dart | 45 +------------ 11 files changed, 63 insertions(+), 172 deletions(-) diff --git a/android/gradle.properties b/android/gradle.properties index 9d4d6766..2cc51b84 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ android.enableJetifier=true android.useAndroidX=true -org.gradle.jvmargs=-Xmx1536M -#-DsocksProxyHost=127.0.0.1 -DsocksProxyPort=1080 +#org.gradle.jvmargs=-Xmx1536M -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=1080 android.enableR8=true +kotlin.code.style=official \ No newline at end of file diff --git a/lib/component/player/bottom_player_bar.dart b/lib/component/player/bottom_player_bar.dart index 953b9256..912ead67 100644 --- a/lib/component/player/bottom_player_bar.dart +++ b/lib/component/player/bottom_player_bar.dart @@ -77,11 +77,11 @@ class BottomControllerBar extends StatelessWidget { aspectRatio: 1, child: ClipRRect( borderRadius: BorderRadius.all(Radius.circular(3)), - child: music.description.iconUri == null + child: music.imageUrl == null ? Container(color: Colors.grey) : Image( fit: BoxFit.cover, - image: CachedImage(music.description.iconUri.toString()), + image: CachedImage(music.imageUrl), ), ), ), diff --git a/lib/component/player/interceptors.dart b/lib/component/player/interceptors.dart index 1cbf9673..ee19e302 100644 --- a/lib/component/player/interceptors.dart +++ b/lib/component/player/interceptors.dart @@ -16,8 +16,8 @@ class BackgroundInterceptors { return result.asValue.value; } - static Future loadImageInterceptor(MediaDescription description) async { - final ImageStream stream = CachedImage(description.iconUri.toString()).resolve(ImageConfiguration( + static Future loadImageInterceptor(MusicMetadata metadata) async { + final ImageStream stream = CachedImage(metadata.iconUri.toString()).resolve(ImageConfiguration( size: const Size(150, 150), devicePixelRatio: WidgetsBinding.instance.window.devicePixelRatio, )); @@ -31,7 +31,7 @@ class BackgroundInterceptors { .then((image) => image.image.toByteData(format: ImageByteFormat.png)) .then((byte) => byte.buffer.asUint8List()) .timeout(const Duration(seconds: 10)); - debugPrint("load image for : ${description.title} ${result.length}"); + debugPrint("load image for : ${metadata.title} ${result.length}"); return result; } } diff --git a/lib/component/player/player.dart b/lib/component/player/player.dart index a94bd524..37fda645 100644 --- a/lib/component/player/player.dart +++ b/lib/component/player/player.dart @@ -52,9 +52,9 @@ extension QuitPlayerExt on BuildContext { return ScopedModel.of(this, rebuildOnChange: true).player.value; } - PlaybackState get playbackState => playerValue.playbackState; + PlaybackState get playbackState => playerValue.state; - PlayList get playList => playerValue.playList; + PlayQueue get playList => playerValue.queue; } extension MusicPlayerExt on MusicPlayer { @@ -66,51 +66,26 @@ extension MusicPlayerValueExt on MusicPlayerValue { ///might be null Music get current => Music.fromMetadata(metadata); - List get playingList => playList.queue.map((e) => Music.fromMetadata(e)).toList(); + List get playingList => queue.queue.map((e) => Music.fromMetadata(e)).toList(); } extension PlaybackStateExt on PlaybackState { - bool get hasError => state == PlaybackState.STATE_ERROR; + bool get hasError => state == PlayerState.Error; - bool get isPlaying => (state == PlaybackState.STATE_PLAYING) && !hasError; + bool get isPlaying => (state == PlayerState.Playing) && !hasError; ///audio is buffering - bool get isBuffering => state == PlaybackState.STATE_BUFFERING; + bool get isBuffering => state == PlayerState.Buffering; - bool get initialized => state != PlaybackState.STATE_NONE; + bool get initialized => state != PlayerState.None; /// Current real position - int get positionWithOffset => position + (DateTime.now().millisecondsSinceEpoch - lastPositionUpdateTime); + int get positionWithOffset => position + (DateTime.now().millisecondsSinceEpoch - updateTime); } @visibleForTesting class QuietModel extends Model { - MusicPlayer player = MusicPlayer(onServiceConnected: (player) async { - if (player.value.playList.queue.isNotEmpty && player.value.metadata != null) { - return; - } -// try { -// //load former player information from SharedPreference -// var preference = await SharedPreferences.getInstance(); -// final playingMediaId = preference.getString(_PREF_KEY_PLAYING); -// final token = preference.getString(_PREF_KEY_TOKEN); -// final playingList = (json.decode(preference.get(_PREF_KEY_PLAYLIST)) as List) -// ?.cast() -// ?.map((e) => MediaMetadata.fromMap(e)) -// ?.toList(); -// final playMode = PlayMode.values[preference.getInt(_PREF_KEY_PLAY_MODE) ?? 0]; -// player.transportControls -// ..setPlayMode(playMode) -// ..prepareFromMediaId(playingMediaId); -// debugPrint("loaded : $playingMediaId"); -// debugPrint("loaded : $playingList"); -// debugPrint("loaded : $token"); -// debugPrint("loaded : $playMode"); -// } catch (e, stacktrace) { -// debugPrint(e.toString()); -// debugPrint(stacktrace.toString()); -// } - }); + MusicPlayer player = MusicPlayer(); QuietModel() { player.addListener(() { diff --git a/lib/model/music.dart b/lib/model/music.dart index a0a45e28..b4f457b4 100644 --- a/lib/model/music.dart +++ b/lib/model/music.dart @@ -1,11 +1,17 @@ -import 'dart:convert'; - import 'package:music_player/music_player.dart'; import 'model.dart'; class Music { - Music({this.id, this.title, this.url, this.album, this.artist, int mvId}) : this.mvId = mvId ?? 0; + Music({ + this.id, + this.title, + this.url, + this.album, + this.artist, + int mvId, + this.imageUrl, + }) : this.mvId = mvId ?? 0; final int id; @@ -20,21 +26,18 @@ class Music { ///歌曲mv id,当其为0时,表示没有mv final int mvId; - MediaDescription get description => metadata.getDescription(); + final String imageUrl; - MediaMetadata _metadata; + MusicMetadata _metadata; - MediaMetadata get metadata { + MusicMetadata get metadata { if (_metadata != null) return _metadata; - _metadata = MediaMetadata( + _metadata = MusicMetadata( mediaId: id.toString(), title: title, - artist: json.encode(artist.map((e) => e.toMap()).toList()), - album: json.encode(album.toMap()), - albumArtUri: album.coverImageUrl, - mediaUri: url, - displayTitle: title, - displaySubtitle: subTitle, + subtitle: subTitle, + duration: 0, + extras: MusicExt(this).toMap(), ); return _metadata; } @@ -56,11 +59,11 @@ class Music { return 'Music{id: $id, title: $title, url: $url, album: $album, artist: $artist}'; } - factory Music.fromMetadata(MediaMetadata metadata) { + factory Music.fromMetadata(MusicMetadata metadata) { if (metadata == null) { return null; } - return _MediaMetadataMusic(metadata); + return fromMap(metadata.extras); } static Music fromMap(Map map) { @@ -91,46 +94,9 @@ extension MusicExt on Music { } } -extension MusicBuilder on MediaMetadata { +extension MusicBuilder on MusicMetadata { /// convert metadata to [Music] Music toMusic() { return Music.fromMetadata(this); } } - -class _MediaMetadataMusic extends Music { - @override - final MediaMetadata _metadata; - - @override - MediaMetadata get metadata => _metadata; - - _MediaMetadataMusic(this._metadata) - : album = Album.fromMap(json.decode(_metadata.album)), - artist = (json.decode(_metadata.artist) as List).cast().map((e) => Artist.fromMap(e)).toList(); - - @override - int get id => int.tryParse(description.mediaId); - - @override - String get title => description.title; - - @override - String get subTitle => description.subtitle; - - @override - String get url => description.mediaUri.toString(); - - @override - final Album album; - - @override - final List artist; - - //TODO MV ID - @override - int get mvId => 0; - - @override - set _metadata(MediaMetadata __metadata) {} -} diff --git a/lib/pages/comments/page_comment.dart b/lib/pages/comments/page_comment.dart index 0ec6d98e..8a97ce27 100644 --- a/lib/pages/comments/page_comment.dart +++ b/lib/pages/comments/page_comment.dart @@ -79,9 +79,7 @@ class _CommentInputState extends State<_CommentInput> { @override Widget build(BuildContext context) { return Container( - decoration: BoxDecoration( - border: - Border(top: BorderSide(color: Theme.of(context).dividerColor))), + decoration: BoxDecoration(border: Border(top: BorderSide(color: Theme.of(context).dividerColor))), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -91,8 +89,7 @@ class _CommentInputState extends State<_CommentInput> { child: TextField( focusNode: _focusNode, controller: _controller, - decoration: - InputDecoration(hintText: "随乐而起,有感而发", errorText: _error), + decoration: InputDecoration(hintText: "随乐而起,有感而发", errorText: _error), ), )), IconButton( @@ -104,8 +101,7 @@ class _CommentInputState extends State<_CommentInput> { } _error = null; _isPosting = true; - final result = - await _postComment(_controller.text, widget.threadId); + final result = await _postComment(_controller.text, widget.threadId); if (result.isValue) { _controller.text = ""; if (_focusNode.hasFocus) { @@ -126,8 +122,7 @@ class _CommentInputState extends State<_CommentInput> { } class CommentThreadId { - CommentThreadId(this.id, this.type, {this.payload}) - : assert(id != null && type != null); + CommentThreadId(this.id, this.type, {this.payload}) : assert(id != null && type != null); final int id; @@ -187,7 +182,7 @@ class CommentThreadPayload { CommentThreadPayload.music(Music music) : this.obj = music, - coverImage = music.description.iconUri?.toString(), + coverImage = music.imageUrl?.toString(), title = music.title, subtitle = music.subTitle; @@ -220,27 +215,21 @@ enum CommentType { ///like or unlike a comment ///return true when operation succeed -Future _like( - bool like, int commentId, CommentThreadId commentThread) async { +Future _like(bool like, int commentId, CommentThreadId commentThread) async { String op = like ? "like" : "unlike"; var result = await neteaseRepository.doRequest( - "https://music.163.com/weapi/v1/comment/$op", - {"threadId": commentThread.threadId, "commentId": commentId}); + "https://music.163.com/weapi/v1/comment/$op", {"threadId": commentThread.threadId, "commentId": commentId}); return result.isValue; } ///post comment to a comment thread -Future> _postComment( - String content, CommentThreadId commentThread) async { +Future> _postComment(String content, CommentThreadId commentThread) async { return await neteaseRepository.doRequest( - "https://music.163.com/weapi/resource/comments/add", - {"content": content, "threadId": commentThread.threadId}); + "https://music.163.com/weapi/resource/comments/add", {"content": content, "threadId": commentThread.threadId}); } -Future _deleteComment( - CommentThreadId commentThread, int commentId) async { - var result = await neteaseRepository.doRequest( - "https://music.163.com/weapi/resource/comments/delete", +Future _deleteComment(CommentThreadId commentThread, int commentId) async { + var result = await neteaseRepository.doRequest("https://music.163.com/weapi/resource/comments/delete", {"commentId": commentId, "threadId": commentThread.threadId}); debugPrint("_deleteComment :$result"); return result.isValue; diff --git a/lib/pages/page_playing_list.dart b/lib/pages/page_playing_list.dart index 42c928be..4c047928 100644 --- a/lib/pages/page_playing_list.dart +++ b/lib/pages/page_playing_list.dart @@ -112,7 +112,8 @@ class _Header extends StatelessWidget { icon: Icon(Icons.delete_outline), onPressed: () async { Navigator.pop(context); - context.player.setPlayList(PlayList.empty()); + //FIXME +// context.player.setPlayList(PlayList.empty()); }) ], ), @@ -178,7 +179,7 @@ class _MusicTile extends StatelessWidget { IconButton( icon: Icon(Icons.close), onPressed: () { - context.player.removeQueueItem(music.metadata.mediaId); + context.player.removeMusicItem(music.metadata); }) ], ), diff --git a/lib/pages/player/cover.dart b/lib/pages/player/cover.dart index bfd4da08..619d4b16 100644 --- a/lib/pages/player/cover.dart +++ b/lib/pages/player/cover.dart @@ -78,8 +78,9 @@ class _AlbumCoverState extends State with TickerProviderStateMixin { return; } _previousNextDirty = false; - _previous = _player.playList.getPrevious(_current.metadata)?.toMusic(); - _next = _player.playList.getNext(_current.metadata)?.toMusic(); + //TODO fetch previous and next + _previous = null; + _next = null; if (mounted) { setState(() {}); } @@ -337,10 +338,10 @@ class _RotationCoverImageState extends State<_RotationCoverImage> with SingleTic @override Widget build(BuildContext context) { ImageProvider image; - if (widget.music == null || widget.music.description.iconUri == null) { + if (widget.music == null || widget.music.imageUrl == null) { image = AssetImage("assets/playing_page_disc.png"); } else { - image = CachedImage(widget.music.description.iconUri.toString()); + image = CachedImage(widget.music.imageUrl.toString()); } return Transform.rotate( angle: rotation, diff --git a/lib/pages/player/page_playing.dart b/lib/pages/player/page_playing.dart index 44edcd7f..ce72a81c 100644 --- a/lib/pages/player/page_playing.dart +++ b/lib/pages/player/page_playing.dart @@ -341,7 +341,7 @@ class _BlurBackground extends StatelessWidget { fit: StackFit.expand, children: [ Image( - image: CachedImage(music.description.iconUri.toString()), + image: CachedImage(music.imageUrl.toString()), fit: BoxFit.cover, height: 15, width: 15, diff --git a/lib/pages/playlist/music_list.dart b/lib/pages/playlist/music_list.dart index f94b10c8..f365aa4a 100644 --- a/lib/pages/playlist/music_list.dart +++ b/lib/pages/playlist/music_list.dart @@ -50,7 +50,7 @@ class MusicTileConfiguration extends StatelessWidget { width: 40, height: 40, fit: BoxFit.cover, - image: CachedImage(music.description.iconUri?.toString() ?? ""), + image: CachedImage(music.imageUrl?.toString() ?? ""), placeholder: AssetImage("assets/playlist_playlist.9.png"), ), ), @@ -75,12 +75,12 @@ class MusicTileConfiguration extends StatelessWidget { static final void Function(BuildContext context, Music muisc) defaultOnTap = (context, music) { final list = MusicTileConfiguration.of(context); final player = context.player; - final PlayList playList = player.value.playList; + final PlayQueue playList = player.value.queue; if (playList.queueId == list.token && player.playbackState.isPlaying && player.metadata == music.metadata) { //open playing page Navigator.pushNamed(context, ROUTE_PAYING); } else { - context.player.playWithList(PlayList(queue: list.queue, queueId: list.token, queueTitle: list.token), + context.player.playWithQueue(PlayQueue(queue: list.queue, queueId: list.token, queueTitle: list.token), metadata: music.metadata); } }; @@ -89,7 +89,7 @@ class MusicTileConfiguration extends StatelessWidget { final List musics; - final List queue; + final List queue; final void Function(BuildContext context, Music muisc) onMusicTap; @@ -213,11 +213,11 @@ class MusicListHeader extends StatelessWidget implements PreferredSizeWidget { child: InkWell( onTap: () { final list = MusicTileConfiguration.of(context); - if (context.player.playList.queueId == list.token && context.player.playbackState.isPlaying) { + if (context.player.queue.queueId == list.token && context.player.playbackState.isPlaying) { //open playing page Navigator.pushNamed(context, ROUTE_PAYING); } else { - context.player.playWithList(PlayList(queue: list.queue, queueId: list.token, queueTitle: list.token)); + context.player.playWithQueue(PlayQueue(queue: list.queue, queueId: list.token, queueTitle: list.token)); } }, child: SizedBox.fromSize( diff --git a/test/widget_test_context.dart b/test/widget_test_context.dart index d3d5e3d5..d0213a18 100644 --- a/test/widget_test_context.dart +++ b/test/widget_test_context.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:mockito/mockito.dart'; import 'package:music_player/music_player.dart'; -import 'package:music_player/src/player/player_channel.dart'; import 'package:quiet/component/netease/counter.dart'; import 'package:quiet/component/netease/netease.dart'; import 'package:quiet/component/player/player.dart'; @@ -45,47 +44,7 @@ class TestContext extends StatelessWidget { } class _TestQuietModel extends Model implements QuietModel { + //TODO test @override - MusicPlayer player = _FakerPlayer(); -} - -class _FakerPlayer extends ValueNotifier with MediaControllerCallback implements MusicPlayer { - _FakerPlayer() : super(MusicPlayerValue.none()); - - @override - MediaMetadata get metadata => null; - - @override - get onServiceConnected => null; - - @override - PlayList get playList => PlayList.empty(); - - @override - Future playWithList(PlayList playList, {MediaMetadata metadata}) { - return null; - } - - @override - PlaybackInfo get playbackInfo => null; - - @override - PlaybackState get playbackState => PlaybackState.none(); - - @override - noSuchMethod(Invocation invocation) { - //do nothing. - } - - @override - TransportControls get transportControls => const _FakeTransportControl(); -} - -class _FakeTransportControl implements TransportControls { - const _FakeTransportControl(); - - @override - noSuchMethod(Invocation invocation) { - //do nothing. - } + MusicPlayer player = MusicPlayer(); }