diff --git a/lib/blocs/explore/cubit/explore_cubits.dart b/lib/blocs/explore/cubit/explore_cubits.dart index 2a97fb0..0c035ff 100644 --- a/lib/blocs/explore/cubit/explore_cubits.dart +++ b/lib/blocs/explore/cubit/explore_cubits.dart @@ -1,13 +1,19 @@ // ignore_for_file: public_member_api_docs, sort_constructors_first +import 'dart:async'; import 'dart:developer'; - +import 'dart:isolate'; +import 'package:Bloomee/services/db/GlobalDB.dart'; import 'package:bloc/bloc.dart'; - import 'package:Bloomee/model/MediaPlaylistModel.dart'; import 'package:Bloomee/model/chart_model.dart'; import 'package:Bloomee/plugins/chart_defines.dart'; import 'package:Bloomee/repository/Youtube/yt_charts_home.dart'; +import 'package:Bloomee/screens/screen/chart/show_charts.dart'; import 'package:Bloomee/services/db/bloomee_db_service.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:isar/isar.dart'; +import 'package:path_provider/path_provider.dart'; part 'explore_states.dart'; @@ -58,24 +64,85 @@ class RecentlyCubit extends Cubit { class ChartCubit extends Cubit { ChartInfo chartInfo; + StreamSubscription? strm; + FetchChartCubit fetchChartCubit; ChartCubit( this.chartInfo, + this.fetchChartCubit, ) : super(ChartInitial()) { getChartFromDB(); - getChart(); + initListener(); } - - void getChart() async { - final chart = await chartInfo.chartFunction(chartInfo.url); - emit(state.copyWith( - chart: chart, coverImg: chart.chartItems?.first.imageUrl)); + void initListener() { + strm = fetchChartCubit.stream.listen((state) { + if (state.isFetched) { + log("Chart Fetched from Isolate - ${chartInfo.title}", + name: "Isolate Fetched"); + getChartFromDB(); + } + }); } - void getChartFromDB() async { + Future getChartFromDB() async { final chart = await BloomeeDBService.getChart(chartInfo.title); if (chart != null) { emit(state.copyWith( chart: chart, coverImg: chart.chartItems?.first.imageUrl)); } } + + @override + Future close() { + fetchChartCubit.close(); + strm?.cancel(); + return super.close(); + } +} + +class FetchChartCubit extends Cubit { + FetchChartCubit() : super(FetchChartInitial()) { + fetchCharts(); + } + + Future fetchCharts() async { + String _path = (await getApplicationDocumentsDirectory()).path; + BackgroundIsolateBinaryMessenger.ensureInitialized( + ServicesBinding.rootIsolateToken!); + + final chartList = await Isolate.run>(() async { + log(_path, name: "Isolate Path"); + List _chartList = List.empty(growable: true); + ChartModel chart; + final db = await Isar.open( + [ + ChartsCacheDBSchema, + ], + directory: _path, + ); + for (var i in chartInfoList) { + final chartCacheDB = db.chartsCacheDBs + .where() + .filter() + .chartNameEqualTo(i.title) + .findFirstSync(); + if ((chartCacheDB?.lastUpdated.difference(DateTime.now()).inHours ?? + 0) > + 12) { + chart = await i.chartFunction(i.url); + if ((chart.chartItems?.isNotEmpty) ?? false) { + db.writeTxnSync(() => + db.chartsCacheDBs.putSync(chartModelToChartCacheDB(chart))); + } + log("Chart Fetched - ${chart.chartName}", name: "Isolate"); + _chartList.add(chart); + } + } + db.close(); + return _chartList; + }); + + if (chartList.isNotEmpty) { + emit(state.copyWith(isFetched: true)); + } + } } diff --git a/lib/blocs/explore/cubit/explore_states.dart b/lib/blocs/explore/cubit/explore_states.dart index ca754c6..5cf8c95 100644 --- a/lib/blocs/explore/cubit/explore_states.dart +++ b/lib/blocs/explore/cubit/explore_states.dart @@ -68,3 +68,22 @@ class ChartInitial extends ChartState { ), coverImg: ""); } + +class FetchChartState { + bool isFetched; + FetchChartState({ + required this.isFetched, + }); + + FetchChartState copyWith({ + bool? isFetched, + }) { + return FetchChartState( + isFetched: isFetched ?? this.isFetched, + ); + } +} + +class FetchChartInitial extends FetchChartState { + FetchChartInitial() : super(isFetched: false); +} diff --git a/lib/main.dart b/lib/main.dart index 2d497d6..950871a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -178,7 +178,7 @@ class _MyAppState extends State { ), BlocProvider( create: (context) => FetchSearchResultsCubit(), - ) + ), ], child: MultiRepositoryProvider( providers: [ diff --git a/lib/plugins/billboard_charts.dart b/lib/plugins/billboard_charts.dart index 6796444..abd5039 100644 --- a/lib/plugins/billboard_charts.dart +++ b/lib/plugins/billboard_charts.dart @@ -2,7 +2,7 @@ import 'dart:developer'; import 'package:Bloomee/model/chart_model.dart'; import 'package:Bloomee/plugins/chart_defines.dart'; -import 'package:Bloomee/services/db/bloomee_db_service.dart'; +// import 'package:Bloomee/services/db/bloomee_db_service.dart'; import 'package:http/http.dart' as http; import 'package:html/parser.dart' show parse; import 'package:html/dom.dart'; @@ -173,26 +173,26 @@ Future getBillboardChart(ChartURL url) async { chartItems: chartItems, url: url.url, lastUpdated: DateTime.now()); - BloomeeDBService.putChart(chart); + // BloomeeDBService.putChart(chart); log('Billboard Charts: ${chart.chartItems!.length} tracks', name: "Billboard"); return chart; } else { - final chart = await BloomeeDBService.getChart(url.title); - if (chart != null) { - log('Billboard Charts: ${chart.chartItems!.length} tracks loaded from cache', - name: "Billboard"); - return chart; - } + // final chart = await BloomeeDBService.getChart(url.title); + // if (chart != null) { + // log('Billboard Charts: ${chart.chartItems!.length} tracks loaded from cache', + // name: "Billboard"); + // return chart; + // } throw Exception("Failed to load page"); } } catch (e) { - final chart = await BloomeeDBService.getChart(url.title); - if (chart != null) { - log('Billboard Charts: ${chart.chartItems!.length} tracks loaded from cache', - name: "Billboard"); - return chart; - } + // final chart = await BloomeeDBService.getChart(url.title); + // if (chart != null) { + // log('Billboard Charts: ${chart.chartItems!.length} tracks loaded from cache', + // name: "Billboard"); + // return chart; + // } throw Exception("Error: $e"); } } diff --git a/lib/plugins/last_dot_fm_charts.dart b/lib/plugins/last_dot_fm_charts.dart index 20ea071..514348b 100644 --- a/lib/plugins/last_dot_fm_charts.dart +++ b/lib/plugins/last_dot_fm_charts.dart @@ -2,7 +2,7 @@ import 'dart:developer'; import 'package:Bloomee/model/chart_model.dart'; import 'package:Bloomee/plugins/chart_defines.dart'; -import 'package:Bloomee/services/db/bloomee_db_service.dart'; +// import 'package:Bloomee/services/db/bloomee_db_service.dart'; import 'package:http/http.dart' as http; import 'package:html/parser.dart' as parser; @@ -63,28 +63,28 @@ Future getLastFmCharts(ChartURL url) async { chartItems: chartItems, url: url.url, lastUpdated: DateTime.now()); - BloomeeDBService.putChart(lastfmModel); + // BloomeeDBService.putChart(lastfmModel); log('Last.fm Charts: ${lastfmModel.chartItems!.length} tracks', name: "LastFM"); return lastfmModel; } else { - final chart = await BloomeeDBService.getChart(url.title); - if (chart != null) { - log('LastFM Charts: ${chart.chartItems!.length} tracks loaded from cache', - name: "LastFM"); - return chart; - } + // final chart = await BloomeeDBService.getChart(url.title); + // if (chart != null) { + // log('LastFM Charts: ${chart.chartItems!.length} tracks loaded from cache', + // name: "LastFM"); + // return chart; + // } throw Exception( 'Failed to load page with status code: ${response.statusCode}'); } } on Exception catch (e) { - final chart = await BloomeeDBService.getChart(url.title); - if (chart != null) { - log('LastFM Charts: ${chart.chartItems!.length} tracks loaded from cache', - name: "LastFM"); - return chart; - } + // final chart = await BloomeeDBService.getChart(url.title); + // if (chart != null) { + // log('LastFM Charts: ${chart.chartItems!.length} tracks loaded from cache', + // name: "LastFM"); + // return chart; + // } throw Exception('Failed to parse page: $e'); } finally { client.close(); diff --git a/lib/plugins/melon_charts.dart b/lib/plugins/melon_charts.dart index dfed46f..f57337f 100644 --- a/lib/plugins/melon_charts.dart +++ b/lib/plugins/melon_charts.dart @@ -2,7 +2,7 @@ import 'dart:developer'; import 'package:Bloomee/model/chart_model.dart'; import 'package:Bloomee/plugins/chart_defines.dart'; -import 'package:Bloomee/services/db/bloomee_db_service.dart'; +// import 'package:Bloomee/services/db/bloomee_db_service.dart'; import 'package:http/http.dart' as http; import 'package:html/parser.dart' as parser; @@ -103,27 +103,27 @@ Future getMelonChart(ChartURL url) async { chartItems: chartItems, url: url.url, lastUpdated: DateTime.now()); - BloomeeDBService.putChart(melonChart); + // BloomeeDBService.putChart(melonChart); log('Melon Charts: ${melonChart.chartItems!.length} tracks', name: "Melon"); return melonChart; } else { - final chart = await BloomeeDBService.getChart(url.title); - if (chart != null) { - log('Melon Charts: ${chart.chartItems!.length} tracks loaded from cache', - name: "Melon"); - return chart; - } + // final chart = await BloomeeDBService.getChart(url.title); + // if (chart != null) { + // log('Melon Charts: ${chart.chartItems!.length} tracks loaded from cache', + // name: "Melon"); + // return chart; + // } throw Exception( 'Parsing failed with status code: ${response.statusCode}'); } } catch (e) { - final chart = await BloomeeDBService.getChart(url.title); - if (chart != null) { - log('Melon Charts: ${chart.chartItems!.length} tracks loaded from cache', - name: "Melon"); - return chart; - } + // final chart = await BloomeeDBService.getChart(url.title); + // if (chart != null) { + // log('Melon Charts: ${chart.chartItems!.length} tracks loaded from cache', + // name: "Melon"); + // return chart; + // } throw Exception('Failed to parse page'); } } diff --git a/lib/plugins/spotify_top50_chart.dart b/lib/plugins/spotify_top50_chart.dart index 3620d6f..21e8f88 100644 --- a/lib/plugins/spotify_top50_chart.dart +++ b/lib/plugins/spotify_top50_chart.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'dart:developer'; import 'package:Bloomee/model/chart_model.dart'; import 'package:Bloomee/plugins/chart_defines.dart'; -import 'package:Bloomee/services/db/bloomee_db_service.dart'; +// import 'package:Bloomee/services/db/bloomee_db_service.dart'; import 'package:http/http.dart' as http; const List spotifyIMGs = [ @@ -42,26 +42,26 @@ Future getSpotifyTop50Chart(ChartURL url) async { url: url.url, lastUpdated: DateTime.now(), ); - BloomeeDBService.putChart(chart); + // BloomeeDBService.putChart(chart); log('Spotify Charts: ${chart.chartItems!.length} tracks', name: "Spotify"); return chart; } else { - final chart = await BloomeeDBService.getChart(url.title); - if (chart != null) { - log('Spotify Charts: ${chart.chartItems!.length} tracks loaded from cache', - name: "Spotify"); - return chart; - } + // final chart = await BloomeeDBService.getChart(url.title); + // if (chart != null) { + // log('Spotify Charts: ${chart.chartItems!.length} tracks loaded from cache', + // name: "Spotify"); + // return chart; + // } throw Exception('Failed to load chart'); } } catch (e) { - final chart = await BloomeeDBService.getChart(url.title); - if (chart != null) { - log('Spotify Charts: ${chart.chartItems!.length} tracks loaded from cache', - name: "Spotify"); - return chart; - } + // final chart = await BloomeeDBService.getChart(url.title); + // if (chart != null) { + // log('Spotify Charts: ${chart.chartItems!.length} tracks loaded from cache', + // name: "Spotify"); + // return chart; + // } throw Exception('Something went wrong while parsing the page'); } } diff --git a/lib/screens/screen/explore_screen.dart b/lib/screens/screen/explore_screen.dart index 3135fca..719d145 100644 --- a/lib/screens/screen/explore_screen.dart +++ b/lib/screens/screen/explore_screen.dart @@ -69,48 +69,51 @@ class _ExploreScreenState extends State { child: BlocBuilder( builder: (context, state) { return AnimatedSwitcher( - duration: const Duration(milliseconds: 1000), - child: state is RecentlyCubitInitial - ? const Center( - child: SizedBox( - height: 60, - width: 60, - child: CircularProgressIndicator( - color: Default_Theme.accentColor2, - )), - ) - : TabSongListWidget( - list: state.mediaPlaylist.mediaItems - .map((e) { - return Padding( - padding: const EdgeInsets.only( - bottom: 8.0, - right: 10, - left: 15, - ), - child: SingleSongCardWidget( - titleText: e.title, - subText: e.artist ?? "", - artUri: e.artUri.toString(), - showLiked: false, - onClicked: () { - context - .read() - .bloomeePlayer - .loadPlaylist( - MediaPlaylist( - mediaItems: [e], - albumName: "Recently", - ), - doPlay: true, - ); - }, - ), - ); - }).toList(), - category: "Recently", - columnSize: 3, - )); + duration: const Duration(milliseconds: 1000), + child: state is RecentlyCubitInitial + ? const Center( + child: SizedBox( + height: 60, + width: 60, + child: CircularProgressIndicator( + color: Default_Theme.accentColor2, + )), + ) + : ((state.mediaPlaylist.mediaItems.isNotEmpty) + ? TabSongListWidget( + list: state.mediaPlaylist.mediaItems + .map((e) { + return Padding( + padding: const EdgeInsets.only( + bottom: 8.0, + right: 10, + left: 15, + ), + child: SingleSongCardWidget( + titleText: e.title, + subText: e.artist ?? "", + artUri: e.artUri.toString(), + showLiked: false, + onClicked: () { + context + .read() + .bloomeePlayer + .loadPlaylist( + MediaPlaylist( + mediaItems: [e], + albumName: "Recently", + ), + doPlay: true, + ); + }, + ), + ); + }).toList(), + category: "Recently", + columnSize: 3, + ) + : const SizedBox()), + ); }, ), ), diff --git a/lib/screens/widgets/carousal_widget.dart b/lib/screens/widgets/carousal_widget.dart index 67d5667..7f74204 100644 --- a/lib/screens/widgets/carousal_widget.dart +++ b/lib/screens/widgets/carousal_widget.dart @@ -22,12 +22,13 @@ class CaraouselWidget extends StatefulWidget { class _CaraouselWidgetState extends State { bool _visibility = true; + final FetchChartCubit fetchChartCubit = FetchChartCubit(); List chartCubitList = List.empty(growable: true); @override void initState() { for (var i in chartInfoList) { - chartCubitList.add(ChartCubit(i)); + chartCubitList.add(ChartCubit(i, fetchChartCubit)); } super.initState(); } diff --git a/lib/services/db/bloomee_db_service.dart b/lib/services/db/bloomee_db_service.dart index 83d4e96..e7244f5 100644 --- a/lib/services/db/bloomee_db_service.dart +++ b/lib/services/db/bloomee_db_service.dart @@ -189,14 +189,17 @@ class BloomeeDBService { if (Isar.instanceNames.isEmpty) { String _path = (await getApplicationDocumentsDirectory()).path; log(_path, name: "DB"); - return await Isar.open([ - MediaPlaylistDBSchema, - MediaItemDBSchema, - AppSettingsBoolDBSchema, - AppSettingsStrDBSchema, - RecentlyPlayedDBSchema, - ChartsCacheDBSchema, - ], directory: _path); + return await Isar.open( + [ + MediaPlaylistDBSchema, + MediaItemDBSchema, + AppSettingsBoolDBSchema, + AppSettingsStrDBSchema, + RecentlyPlayedDBSchema, + ChartsCacheDBSchema, + ], + directory: _path, + ); } return Future.value(Isar.getInstance()); }