Improve custom playlist support.

This commit is contained in:
Stonegate 2021-01-02 16:21:05 +08:00
parent f36ae4f486
commit 656e5ccdea
2 changed files with 82 additions and 41 deletions

View File

@ -120,7 +120,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
double _seekSliderValue = 0.0; double _seekSliderValue = 0.0;
/// Record plyaer position. /// Record plyaer position.
int _lastPostion = 0; int _lastPosition = 0;
/// Set true if sleep timer mode is end of episode. /// Set true if sleep timer mode is end of episode.
bool _stopOnComplete = false; bool _stopOnComplete = false;
@ -199,7 +199,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
EpisodeBrief get episode => _episode; EpisodeBrief get episode => _episode;
/// Playlist provider. /// Playlist provider.
int get lastPositin => _lastPostion; int get lastPosition => _lastPosition;
List<Playlist> get playlists => _playlists; List<Playlist> get playlists => _playlists;
Playlist get queue => _playlists.first; Playlist get queue => _playlists.first;
bool get playing => _playing; bool get playing => _playing;
@ -269,20 +269,32 @@ class AudioPlayerNotifier extends ChangeNotifier {
await _getAutoPlay(); await _getAutoPlay();
var state = await _playerStateStorage.getPlayerState(); var state = await _playerStateStorage.getPlayerState();
if (state[0] != '') { var idList = [for (var p in _playlists) p.id];
_playlist = _playlists.firstWhere((p) => p.id == state[0], if (idList.contains(state[1])) {
orElse: () => _playlists.first); _playlist = _playlists.firstWhere(
(p) => p.id == state[0],
);
await _playlist.getPlaylist();
if (state[1] != '') {
var episode = await _dbHelper.getRssItemWithUrl(state[1]);
if ((!_playlist.isQueue && _playlist.contains(episode)) ||
(_playlist.isQueue && _queue.episodes.first == episode)) {
_episode = episode;
_lastPosition = int.parse(state[2] ?? '0');
} else {
_episode = _playlist.episodes.first;
_lastPosition = 0;
}
} else {
_episode = _playlist.episodes.first;
_lastPosition = 0;
}
} else { } else {
_playlist = _playlists.first; _playlist = _playlists.first;
_episode = _playlist.episodes.first;
_lastPosition = 0;
} }
await _playlist.getPlaylist(); notifyListeners();
if (state[1] != '') {
_episode = await _dbHelper.getRssItemWithUrl(state[1]);
} else {
_episode =
_playlist.episodes.isNotEmpty ? _playlist.episodes.first : null;
}
_lastPostion = int.parse(state[2] ?? '0');
/// Save plays history if app is closed accidentally. /// Save plays history if app is closed accidentally.
/// if (_lastPostion > 0 && _queue.episodes.isNotEmpty) { /// if (_lastPostion > 0 && _queue.episodes.isNotEmpty) {
@ -308,7 +320,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
_playerRunning = true; _playerRunning = true;
notifyListeners(); notifyListeners();
_startAudioService(_playlist, _startAudioService(_playlist,
position: _lastPostion ?? 0, position: _lastPosition ?? 0,
index: _playlist.episodes.indexOf(_episode)); index: _playlist.episodes.indexOf(_episode));
} }
} }
@ -348,7 +360,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
await _dbHelper.saveHistory(history); await _dbHelper.saveHistory(history);
_queue.addToPlayListAt(episodeNew, 0); _queue.addToPlayListAt(episodeNew, 0);
await updatePlaylist(_queue); await updatePlaylist(_queue);
if (_playlist.name != 'Queue') { if (!_playlist.isQueue) {
AudioService.customAction('setIsQueue', true); AudioService.customAction('setIsQueue', true);
AudioService.customAction('changeQueue', [ AudioService.customAction('changeQueue', [
for (var e in _queue.episodes) jsonEncode(e.toMediaItem().toJson()) for (var e in _queue.episodes) jsonEncode(e.toMediaItem().toJson())
@ -479,7 +491,6 @@ class AudioPlayerNotifier extends ChangeNotifier {
} }
notifyListeners(); notifyListeners();
} else { } else {
// _queue.playlist.removeAt(0);
AudioService.skipToNext(); AudioService.skipToNext();
} }
}); });
@ -511,16 +522,17 @@ class AudioPlayerNotifier extends ChangeNotifier {
AudioService.customEventStream.distinct().listen((event) async { AudioService.customEventStream.distinct().listen((event) async {
if (event is String) { if (event is String) {
if (_playlist.name == 'Queue' && if (_playlist.isQueue &&
_queue.episodes.isNotEmpty && _queue.isNotEmpty &&
_queue.episodes.first.title == event) { _queue.episodes.first.title == event) {
_queue.delFromPlaylist(_episode); _queue.delFromPlaylist(_episode);
updatePlaylist(_queue, updateEpisodes: false);
} }
_lastPostion = 0; _lastPosition = 0;
notifyListeners(); notifyListeners();
// await _positionStorage.saveInt(_lastPostion); // await _positionStorage.saveInt(_lastPostion);
await _playerStateStorage.savePlayerState( await _playerStateStorage.savePlayerState(
_playlist.id, _episode.enclosureUrl, _lastPostion); _playlist.id, _episode.enclosureUrl, _lastPosition);
var history; var history;
if (_markListened) { if (_markListened) {
history = PlayHistory(_episode.title, _episode.enclosureUrl, history = PlayHistory(_episode.title, _episode.enclosureUrl,
@ -534,9 +546,9 @@ class AudioPlayerNotifier extends ChangeNotifier {
if (event is Map && event['playerRunning'] == false && _playerRunning) { if (event is Map && event['playerRunning'] == false && _playerRunning) {
_playerRunning = false; _playerRunning = false;
notifyListeners(); notifyListeners();
if (_lastPostion > 0) { if (_lastPosition > 0) {
final history = PlayHistory(_episode.title, _episode.enclosureUrl, final history = PlayHistory(_episode.title, _episode.enclosureUrl,
_lastPostion ~/ 1000, _seekSliderValue); _lastPosition ~/ 1000, _seekSliderValue);
await _dbHelper.saveHistory(history); await _dbHelper.saveHistory(history);
} }
//_episode = null; //_episode = null;
@ -569,10 +581,10 @@ class AudioPlayerNotifier extends ChangeNotifier {
if (_backgroundAudioPosition > 0 && if (_backgroundAudioPosition > 0 &&
_backgroundAudioPosition < _backgroundAudioDuration) { _backgroundAudioPosition < _backgroundAudioDuration) {
_lastPostion = _backgroundAudioPosition; _lastPosition = _backgroundAudioPosition;
// _positionStorage.saveInt(_lastPostion); // _positionStorage.saveInt(_lastPostion);
_playerStateStorage.savePlayerState( _playerStateStorage.savePlayerState(
_playlist.id, _episode.enclosureUrl, _lastPostion); _playlist.id, _episode.enclosureUrl, _lastPosition);
} }
notifyListeners(); notifyListeners();
} }
@ -582,16 +594,17 @@ class AudioPlayerNotifier extends ChangeNotifier {
}); });
} }
/// Playlists management. /// Queue management.
Future<void> addToPlaylist(EpisodeBrief episode) async { Future<void> addToPlaylist(EpisodeBrief episode) async {
var episodeNew = await _dbHelper.getRssItemWithUrl(episode.enclosureUrl); var episodeNew = await _dbHelper.getRssItemWithUrl(episode.enclosureUrl);
if (episodeNew.isNew == 1) { if (episodeNew.isNew == 1) {
await _dbHelper.removeEpisodeNewMark(episodeNew.enclosureUrl); await _dbHelper.removeEpisodeNewMark(episodeNew.enclosureUrl);
} }
if (!_queue.episodes.contains(episodeNew)) { if (!_queue.episodes.contains(episodeNew)) {
if (playerRunning && _playlist.name == 'Queue') { if (playerRunning && _playlist.isQueue) {
await AudioService.addQueueItem(episodeNew.toMediaItem()); await AudioService.addQueueItem(episodeNew.toMediaItem());
} }
if (_playlist.isQueue && _queue.isEmpty) _episode = episodeNew;
_queue.addToPlayList(episodeNew); _queue.addToPlayList(episodeNew);
await updatePlaylist(_queue, updateEpisodes: false); await updatePlaylist(_queue, updateEpisodes: false);
} }
@ -602,7 +615,7 @@ class AudioPlayerNotifier extends ChangeNotifier {
if (episodeNew.isNew == 1) { if (episodeNew.isNew == 1) {
await _dbHelper.removeEpisodeNewMark(episodeNew.enclosureUrl); await _dbHelper.removeEpisodeNewMark(episodeNew.enclosureUrl);
} }
if (playerRunning && _playlist.name == 'Queue') { if (_playerRunning && _playlist.isQueue) {
await AudioService.addQueueItemAt(episodeNew.toMediaItem(), index); await AudioService.addQueueItemAt(episodeNew.toMediaItem(), index);
} }
_queue.addToPlayListAt(episodeNew, index); _queue.addToPlayListAt(episodeNew, index);
@ -629,20 +642,25 @@ class AudioPlayerNotifier extends ChangeNotifier {
} }
Future<void> updateMediaItem(EpisodeBrief episode) async { Future<void> updateMediaItem(EpisodeBrief episode) async {
if (episode.enclosureUrl == episode.mediaId && _episode != episode) { if (episode.enclosureUrl == episode.mediaId &&
_episode != episode &&
_playlist.contains(episode)) {
var episodeNew = await _dbHelper.getRssItemWithUrl(episode.enclosureUrl); var episodeNew = await _dbHelper.getRssItemWithUrl(episode.enclosureUrl);
_playlist.updateEpisode(episodeNew); _playlist.updateEpisode(episodeNew);
if (_playerRunning) {
await AudioService.updateMediaItem(episodeNew.toMediaItem());
}
} }
} }
Future<int> delFromPlaylist(EpisodeBrief episode) async { Future<int> delFromPlaylist(EpisodeBrief episode) async {
var episodeNew = await _dbHelper.getRssItemWithUrl(episode.enclosureUrl); var episodeNew = await _dbHelper.getRssItemWithUrl(episode.enclosureUrl);
if (playerRunning && _playlist.name == 'Queue') { if (playerRunning && _playlist.isQueue) {
await AudioService.removeQueueItem(episodeNew.toMediaItem()); await AudioService.removeQueueItem(episodeNew.toMediaItem());
} }
var index = _queue.delFromPlaylist(episodeNew); var index = _queue.delFromPlaylist(episodeNew);
if (index == 0) { if (index == 0) {
_lastPostion = 0; _lastPosition = 0;
await _positionStorage.saveInt(0); await _positionStorage.saveInt(0);
} }
updatePlaylist(_queue, updateEpisodes: false); updatePlaylist(_queue, updateEpisodes: false);
@ -650,6 +668,9 @@ class AudioPlayerNotifier extends ChangeNotifier {
} }
Future reorderPlaylist(int oldIndex, int newIndex) async { Future reorderPlaylist(int oldIndex, int newIndex) async {
if (newIndex > oldIndex) {
newIndex -= 1;
}
var episode = _queue.episodes[oldIndex]; var episode = _queue.episodes[oldIndex];
if (playerRunning && _playlist.name == 'Queue') { if (playerRunning && _playlist.name == 'Queue') {
await AudioService.removeQueueItem(episode.toMediaItem()); await AudioService.removeQueueItem(episode.toMediaItem());
@ -658,27 +679,30 @@ class AudioPlayerNotifier extends ChangeNotifier {
_queue.addToPlayListAt(episode, newIndex); _queue.addToPlayListAt(episode, newIndex);
updatePlaylist(_queue, updateEpisodes: false); updatePlaylist(_queue, updateEpisodes: false);
if (newIndex == 0) { if (newIndex == 0) {
_lastPostion = 0; _lastPosition = 0;
await _positionStorage.saveInt(0); await _positionStorage.saveInt(0);
} }
} }
Future<bool> moveToTop(EpisodeBrief episode) async { Future<bool> moveToTop(EpisodeBrief episode) async {
await delFromPlaylist(episode); await delFromPlaylist(episode);
if (playerRunning && _playlist.name == 'Queue') { final episodeNew = await _dbHelper.getRssItemWithUrl(episode.enclosureUrl);
final episodeNew = if (_playerRunning && _playlist.isQueue) {
await _dbHelper.getRssItemWithUrl(episode.enclosureUrl);
await AudioService.addQueueItemAt(episodeNew.toMediaItem(), 1); await AudioService.addQueueItemAt(episodeNew.toMediaItem(), 1);
_queue.addToPlayListAt(episode, 1, existed: false); _queue.addToPlayListAt(episode, 1, existed: false);
} else { } else {
_queue.addToPlayListAt(episode, 0, existed: false); _queue.addToPlayListAt(episode, 0, existed: false);
_lastPostion = 0; if (_playlist.isQueue) {
_positionStorage.saveInt(_lastPostion); _lastPosition = 0;
_positionStorage.saveInt(_lastPosition);
_episode = episodeNew;
}
} }
updatePlaylist(_queue, updateEpisodes: false); updatePlaylist(_queue, updateEpisodes: false);
return true; return true;
} }
/// Custom playlist management.
void addPlaylist(Playlist playlist) { void addPlaylist(Playlist playlist) {
_playlists = [..._playlists, playlist]; _playlists = [..._playlists, playlist];
notifyListeners(); notifyListeners();
@ -734,7 +758,14 @@ class AudioPlayerNotifier extends ChangeNotifier {
} }
void clearPlaylist(Playlist playlist) { void clearPlaylist(Playlist playlist) {
playlist.clear(); if (_playerRunning && _playlist.isQueue && playlist.isQueue) {
for (var e in playlist.episodes) {
if (e != _episode) {
delFromPlaylist(e);
}
}
} else
playlist.clear();
updatePlaylist(playlist, updateEpisodes: false); updatePlaylist(playlist, updateEpisodes: false);
} }
@ -742,11 +773,15 @@ class AudioPlayerNotifier extends ChangeNotifier {
{bool updateEpisodes = true}) async { {bool updateEpisodes = true}) async {
if (updateEpisodes) await playlist.getPlaylist(); if (updateEpisodes) await playlist.getPlaylist();
_playlists = [for (var p in _playlists) p.id == playlist.id ? playlist : p]; _playlists = [for (var p in _playlists) p.id == playlist.id ? playlist : p];
if (_playlist.id == playlist.id && !_playerRunning) { if (_playlist.id == playlist.id) {
_playlist = _playlists.firstWhere((e) => e.id == _playlist.id); if (playlist.isQueue) {
_playlist = _queue;
} else if (!_playerRunning) {
_playlist = _playlists.firstWhere((e) => e.id == _playlist.id);
}
notifyListeners(); notifyListeners();
} }
_savePlaylists(); await _savePlaylists();
} }
bool playlistExisted(String name) { bool playlistExisted(String name) {

View File

@ -34,10 +34,16 @@ class Playlist extends Equatable {
/// Eposides in playlist. /// Eposides in playlist.
final List<EpisodeBrief> episodes; final List<EpisodeBrief> episodes;
bool get isEmpty => episodeList.isEmpty; bool get isEmpty => episodes.isEmpty && episodeList.isEmpty;
bool get isNotEmpty => episodes.isNotEmpty && episodeList.isNotEmpty;
int get length => episodes.length; int get length => episodes.length;
bool get isQueue => name == 'Queue';
bool contains(EpisodeBrief episode) => episodes.contains(episode);
Playlist(this.name, Playlist(this.name,
{String id, List<String> episodeList, List<EpisodeBrief> episodes}) {String id, List<String> episodeList, List<EpisodeBrief> episodes})
: id = id ?? Uuid().v4(), : id = id ?? Uuid().v4(),