Skip to content
This repository has been archived by the owner on Jun 23, 2024. It is now read-only.

Commit

Permalink
Change minimum dart version to 3.0
Browse files Browse the repository at this point in the history
Use cache in top playlists
Fixed bug in playlists cache, hopefully last one :)
Hide save playlist from spotify playlists
Android offloading disabled as it causes the sound to mute for some cases
  • Loading branch information
AlvaroRojas committed Jun 7, 2023
1 parent 42a0dfe commit 784ecf6
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 84 deletions.
94 changes: 83 additions & 11 deletions lib/APIs/spotify_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,11 @@ class SpotifyApi {
final List<Map> songsData = [];
if (response.statusCode == 200) {
final result = jsonDecode(response.body);
final playlistCache = Hive.box('cache').get(
'spotifyPlaylists',
defaultValue: [],
) as List;
for (final element in result['items'] as List) {
final playlistCache = Hive.box('cache').get(
'spotifyPlaylists',
defaultValue: [],
) as List;

final cachedPlaylist = playlistCache.isNotEmpty
? playlistCache
.where((x) => x['id'] == element['id'])
Expand Down Expand Up @@ -195,6 +194,79 @@ class SpotifyApi {
}
}

Future<dynamic> getPlaylist(String accessToken, String playlistId) async {
try {
final Uri path = Uri.parse(
'$spotifyApiBaseUrl$spotifyPlaylistTrackEndpoint/$playlistId');

final response = await get(
path,
headers: {
'Authorization': 'Bearer $accessToken',
'Accept': 'application/json'
},
);
Map songsData = {};
if (response.statusCode == 200) {
final result = jsonDecode(response.body);
final playlistCache = Hive.box('cache').get(
'spotifyPlaylists',
defaultValue: [],
) as List;
final element = result;
final cachedPlaylist = playlistCache.isNotEmpty
? playlistCache.where((x) => x['id'] == element['id'])?.firstOrNull
: null;

Map playlistObject = {
'title': element['name'],
'id': element['id'],
'snapshot_id': element['snapshot_id'],
'subtitle': element['description'],
'image': element['images'][0]['url'],
'perma_url': element['external_urls']['spotify'],
'type': element['type'],
'uri': element['uri'],
};

if (cachedPlaylist != null) {
Logger.root.info('Found cached playlist for ${element["id"]}');
playlistObject = Map.from(cachedPlaylist as Map);
if (cachedPlaylist['snapshot_id'] != element['snapshot_id'] ||
(cachedPlaylist['tracks'] as List).length !=
element['tracks']['total']) {
Logger.root.info(
'Cached playlist for ${element["id"]} has changed, update cache',
);
playlistCache.remove(cachedPlaylist);
playlistObject['tracks'] =
await SpotifyApi().getAllTracksOfPlaylist(
accessToken,
element['id'].toString(),
);
playlistCache.add(playlistObject);
Hive.box('cache').put('spotifyPlaylists', playlistCache);
}
} else {
Logger.root.info('New playlist ${element["id"]}, add to cache');
playlistObject['tracks'] = await SpotifyApi().getAllTracksOfPlaylist(
accessToken,
element['id'].toString(),
);
playlistCache.add(playlistObject);
Hive.box('cache').put('spotifyPlaylists', playlistCache);
}
songsData = playlistObject;
} else {
throw Exception('Spotify error: ${jsonDecode(response.body)}');
}
return songsData;
} catch (e) {
Logger.root.severe('Error in getting spotify playlist $playlistId: $e');
return null;
}
}

Future<List> getAllTracksOfPlaylist(
String accessToken,
String playlistId,
Expand Down Expand Up @@ -286,15 +358,15 @@ class SpotifyApi {
'Accept': 'application/json'
},
);

final playlistCache = Hive.box('cache').get(
'spotifyPlaylists',
defaultValue: [],
) as List;
final List<Map> songsData = [];
if (response.statusCode == 200) {
final result = jsonDecode(response.body);
for (final element in result['playlists']['items'] as List) {
final playlistCache = Hive.box('cache').get(
'spotifyPlaylists',
defaultValue: [],
) as List;

final cachedPlaylist = playlistCache.isNotEmpty
? playlistCache
.where((x) => x['id'] == element['id'])
Expand All @@ -310,7 +382,7 @@ class SpotifyApi {
'perma_url': element['external_urls']['spotify'],
'type': element['type'],
'uri': element['uri'],
'section': result['message']
'section': result['message'],
};

if (cachedPlaylist != null) {
Expand Down
11 changes: 6 additions & 5 deletions lib/CustomWidgets/playlist_popupmenu.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ import 'package:soundal/Screens/Player/audioplayer.dart';
class PlaylistPopupMenu extends StatefulWidget {
final List data;
final String title;
const PlaylistPopupMenu({
super.key,
required this.data,
required this.title,
});
final bool showSave;
const PlaylistPopupMenu(
{super.key,
required this.data,
required this.title,
required this.showSave});

@override
_PlaylistPopupMenuState createState() => _PlaylistPopupMenuState();
Expand Down
4 changes: 2 additions & 2 deletions lib/Helpers/format.dart
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ class FormatResponse {
if (cachedDetails.isEmpty) {
cachedDetails =
await SaavnAPI().fetchSongDetails(item['id'].toString());
Hive.box('cache')
await Hive.box('cache')
.put(cachedDetails['id'].toString(), cachedDetails);
}
list[i] = cachedDetails;
Expand Down Expand Up @@ -620,7 +620,7 @@ class FormatResponse {
final res = await Hive.box('spoty2youtube')
.get(tracks[song['order'] as int]['id']);
if (res == null) {
Hive.box('spoty2youtube')
await Hive.box('spoty2youtube')
.put(tracks[song['order'] as int]['id'], song['id']);
}
songList.add(song);
Expand Down
29 changes: 19 additions & 10 deletions lib/Screens/Common/song_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ class _SongsListPageState extends State<SongsListPage> {
fetched = true;
loading = false;
});
break;
case 'album':
//Retrieve spotify album songs then convert them to youtube
Map receivedData = {};
Expand Down Expand Up @@ -167,17 +166,29 @@ class _SongsListPageState extends State<SongsListPage> {
fetched = true;
loading = false;
setState(() {});
break;
case 'playlist':
final List songs = [];
final playlistCached = playlistCache.firstWhere(
var playlistCached = playlistCache.firstWhere(
(element) => element['id'] == widget.listItem['id'],
orElse: () => null,
);

if (playlistCached == null ||
(playlistCached['tracks'] as List).firstOrNull?['is_local'] !=
null) {
if (playlistCached == null) {
await callSpotifyFunction(
function: (String accessToken) async => {
playlistCached = await SpotifyApi().getPlaylist(
accessToken,
widget.listItem['id'].toString(),
)
},
);
}

if ((playlistCached['tracks'] as List).firstOrNull?['is_local'] !=
null) {
Logger.root.info(
'No cached songs for ${widget.listItem['id']}, update cache to add songs',
);
if (widget.listItem['tracks'].runtimeType != List) {
await callSpotifyFunction(
function: (String accessToken) async => {
Expand All @@ -197,7 +208,7 @@ class _SongsListPageState extends State<SongsListPage> {
songs,
);
playlistCached['tracks'] = songList;
Hive.box('settings').put('spotifyPlaylists', playlistCache);
Hive.box('cache').put('spotifyPlaylists', playlistCache);
} else {
songList = playlistCached['tracks'] as List;
}
Expand All @@ -206,7 +217,6 @@ class _SongsListPageState extends State<SongsListPage> {
loading = false;

setState(() {});
break;
case 'mix':
SaavnAPI()
.getSongFromToken(
Expand All @@ -228,7 +238,6 @@ class _SongsListPageState extends State<SongsListPage> {
);
}
});
break;
case 'show':
SaavnAPI()
.getSongFromToken(
Expand All @@ -250,7 +259,6 @@ class _SongsListPageState extends State<SongsListPage> {
);
}
});
break;
default:
setState(() {
fetched = true;
Expand Down Expand Up @@ -306,6 +314,7 @@ class _SongsListPageState extends State<SongsListPage> {
),
PlaylistPopupMenu(
data: songList,
showSave: widget.listItem['snapshot_id'] == null,
title:
widget.listItem['title']?.toString() ?? 'Songs',
),
Expand Down
2 changes: 1 addition & 1 deletion lib/Screens/Home/spotify.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import 'package:soundal/CustomWidgets/song_tile_trailing_menu.dart';
import 'package:soundal/Helpers/countrycodes.dart';
import 'package:soundal/Helpers/extensions.dart';
import 'package:soundal/Helpers/image_resolution_modifier.dart';
import 'package:soundal/Helpers/logging.dart';
import 'package:soundal/Helpers/logger.dart';
import 'package:soundal/Helpers/spotify_helper.dart';
import 'package:soundal/Screens/Common/song_list.dart';
import 'package:soundal/Screens/Library/liked.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/Screens/Search/artists.dart
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class _ArtistSearchPageState extends State<ArtistSearchPage> {
),
if (data['Top Songs'] != null)
PlaylistPopupMenu(
showSave: true,
data: data['Top Songs']!,
title:
widget.data['title']?.toString() ?? 'Songs',
Expand Down
Loading

0 comments on commit 784ecf6

Please sign in to comment.