feat: enable caching of queue

This commit is contained in:
Kingkor Roy Tirtho 2023-05-27 23:04:54 +06:00
parent e529c79c4f
commit ec11af53a1
6 changed files with 39 additions and 21 deletions

View File

@ -8,7 +8,6 @@ import 'package:spotube/extensions/album_simple.dart';
import 'package:spotube/extensions/artist_simple.dart'; import 'package:spotube/extensions/artist_simple.dart';
import 'package:spotube/models/matched_track.dart'; import 'package:spotube/models/matched_track.dart';
import 'package:spotube/provider/user_preferences_provider.dart'; import 'package:spotube/provider/user_preferences_provider.dart';
import 'package:spotube/services/supabase.dart';
import 'package:spotube/services/youtube.dart'; import 'package:spotube/services/youtube.dart';
import 'package:spotube/utils/platform.dart'; import 'package:spotube/utils/platform.dart';
import 'package:spotube/utils/service_utils.dart'; import 'package:spotube/utils/service_utils.dart';

View File

@ -11,9 +11,9 @@ class ProxyPlaylist {
ProxyPlaylist(this.tracks, [this.active]); ProxyPlaylist(this.tracks, [this.active]);
factory ProxyPlaylist.fromJson(Map<String, dynamic> json) { factory ProxyPlaylist.fromJson(Map<String, dynamic> json) {
return ProxyPlaylist( return ProxyPlaylist(
(json['tracks'] as List<Map<String, dynamic>>) List.castFrom<dynamic, Map<String, dynamic>>(
.map(_makeAppropriateTrack) json['tracks'] ?? <Map<String, dynamic>>[],
.toSet(), ).map(_makeAppropriateTrack).toSet(),
json['active'] as int, json['active'] as int,
); );
} }

View File

@ -1,3 +1,6 @@
import 'dart:async';
import 'dart:convert';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:palette_generator/palette_generator.dart'; import 'package:palette_generator/palette_generator.dart';
@ -13,6 +16,7 @@ import 'package:spotube/provider/proxy_playlist/proxy_playlist.dart';
import 'package:spotube/provider/user_preferences_provider.dart'; import 'package:spotube/provider/user_preferences_provider.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';
import 'package:spotube/services/audio_services/audio_services.dart'; import 'package:spotube/services/audio_services/audio_services.dart';
import 'package:spotube/utils/persisted_state_notifier.dart';
import 'package:spotube/utils/type_conversion_utils.dart'; import 'package:spotube/utils/type_conversion_utils.dart';
/// Things to implement: /// Things to implement:
@ -24,7 +28,7 @@ import 'package:spotube/utils/type_conversion_utils.dart';
/// * [x] Add track at the beginning /// * [x] Add track at the beginning
/// * [x] Remove track /// * [x] Remove track
/// * [ ] Reorder track /// * [ ] Reorder track
/// * [ ] Caching and loading of cache of tracks /// * [x] Caching and loading of cache of tracks
/// * [x] Shuffling /// * [x] Shuffling
/// * [x] loop => playlist, track, none /// * [x] loop => playlist, track, none
/// * [ ] Alternative Track Source /// * [ ] Alternative Track Source
@ -35,7 +39,7 @@ import 'package:spotube/utils/type_conversion_utils.dart';
/// * It'll not store any sort of player state e.g playing, paused, shuffled etc /// * It'll not store any sort of player state e.g playing, paused, shuffled etc
/// * For that, use [SpotubeAudioPlayer] /// * For that, use [SpotubeAudioPlayer]
class ProxyPlaylistNotifier extends StateNotifier<ProxyPlaylist> class ProxyPlaylistNotifier extends PersistedStateNotifier<ProxyPlaylist>
with NextFetcher { with NextFetcher {
final Ref ref; final Ref ref;
late final AudioServices notificationService; late final AudioServices notificationService;
@ -52,7 +56,7 @@ class ProxyPlaylistNotifier extends StateNotifier<ProxyPlaylist>
static AlwaysAliveRefreshable<ProxyPlaylistNotifier> get notifier => static AlwaysAliveRefreshable<ProxyPlaylistNotifier> get notifier =>
provider.notifier; provider.notifier;
ProxyPlaylistNotifier(this.ref) : super(ProxyPlaylist({})) { ProxyPlaylistNotifier(this.ref) : super(ProxyPlaylist({}), "playlist") {
() async { () async {
notificationService = await AudioServices.create(ref, this); notificationService = await AudioServices.create(ref, this);
@ -80,9 +84,6 @@ class ProxyPlaylistNotifier extends StateNotifier<ProxyPlaylist>
audioPlayer.shuffledStream.listen((event) { audioPlayer.shuffledStream.listen((event) {
final newlyOrderedTracks = mapSourcesToTracks(audioPlayer.sources); final newlyOrderedTracks = mapSourcesToTracks(audioPlayer.sources);
print(
'newlyOrderedTracks: ${newlyOrderedTracks.map((e) => e.name).toList()}');
final newActiveIndex = newlyOrderedTracks.indexWhere( final newActiveIndex = newlyOrderedTracks.indexWhere(
(element) => element.id == state.activeTrack?.id, (element) => element.id == state.activeTrack?.id,
); );
@ -207,13 +208,13 @@ class ProxyPlaylistNotifier extends StateNotifier<ProxyPlaylist>
} }
Future<void> load( Future<void> load(
List<Track> tracks, { Iterable<Track> tracks, {
int initialIndex = 0, int initialIndex = 0,
bool autoPlay = false, bool autoPlay = false,
}) async { }) async {
tracks = blacklist.filter(tracks).toList() as List<Track>; tracks = blacklist.filter(tracks).toList() as List<Track>;
final addableTrack = final addableTrack = await SpotubeTrack.fetchFromTrack(
await SpotubeTrack.fetchFromTrack(tracks[initialIndex], preferences); tracks.elementAt(initialIndex), preferences);
state = state.copyWith( state = state.copyWith(
tracks: mergeTracks([addableTrack], tracks), tracks: mergeTracks([addableTrack], tracks),
@ -227,7 +228,7 @@ class ProxyPlaylistNotifier extends StateNotifier<ProxyPlaylist>
); );
await storeTrack( await storeTrack(
tracks[initialIndex], tracks.elementAt(initialIndex),
addableTrack, addableTrack,
); );
} }
@ -385,4 +386,24 @@ class ProxyPlaylistNotifier extends StateNotifier<ProxyPlaylist>
ref.read(paletteProvider.notifier).state = null; ref.read(paletteProvider.notifier).state = null;
} }
} }
@override
onInit() {
return load(
state.tracks,
initialIndex: state.active ?? 0,
autoPlay: false,
);
}
@override
FutureOr<ProxyPlaylist> fromJson(Map<String, dynamic> json) {
return ProxyPlaylist.fromJson(json);
}
@override
Map<String, dynamic> toJson() {
final json = state.toJson();
return json;
}
} }

View File

@ -109,7 +109,7 @@ abstract class PersistedStateNotifier<T> extends StateNotifier<T> {
} }
void save() async { void save() async {
box.put(cacheKey, toJson()); await box.put(cacheKey, toJson());
} }
FutureOr<T> fromJson(Map<String, dynamic> json); FutureOr<T> fromJson(Map<String, dynamic> json);

View File

@ -1306,11 +1306,9 @@ packages:
piped_client: piped_client:
dependency: "direct main" dependency: "direct main"
description: description:
path: "." path: "../piped_client"
ref: "2036a78d3414a0fc7fe3b081f1029dd086352fcd" relative: true
resolved-ref: "2036a78d3414a0fc7fe3b081f1029dd086352fcd" source: path
url: "https://github.com/KRTirtho/piped_client"
source: git
version: "0.1.0" version: "0.1.0"
platform: platform:
dependency: transitive dependency: transitive

View File

@ -101,7 +101,7 @@ dependencies:
piped_client: piped_client:
git: git:
url: https://github.com/KRTirtho/piped_client url: https://github.com/KRTirtho/piped_client
ref: 2036a78d3414a0fc7fe3b081f1029dd086352fcd ref: eaade37d0938d31dbfa35bb5152caca4e284bda6
supabase_flutter: ^1.9.1 supabase_flutter: ^1.9.1
dev_dependencies: dev_dependencies: