diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 141c6ce1..860252df 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -30,6 +30,14 @@ + + + + + + + diff --git a/android/app/src/main/kotlin/fr/ziedelth/jais/HomeWidgetProvider.kt b/android/app/src/main/kotlin/fr/ziedelth/jais/HomeWidgetProvider.kt new file mode 100644 index 00000000..8933717b --- /dev/null +++ b/android/app/src/main/kotlin/fr/ziedelth/jais/HomeWidgetProvider.kt @@ -0,0 +1,66 @@ +package fr.ziedelth.jais + +import android.appwidget.AppWidgetManager +import android.content.Context +import android.content.SharedPreferences +import android.graphics.BitmapFactory +import android.net.Uri +import android.view.View +import android.widget.RemoteViews + +import es.antonborri.home_widget.HomeWidgetBackgroundIntent +import es.antonborri.home_widget.HomeWidgetLaunchIntent +import es.antonborri.home_widget.HomeWidgetProvider + +class HomeWidgetProvider : HomeWidgetProvider() { + override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray, widgetData: SharedPreferences) { + appWidgetIds.forEach { widgetId -> + val views = RemoteViews(context.packageName, R.layout.home_widget_layout).apply { + // Open App on Widget Click + val pendingIntent = HomeWidgetLaunchIntent.getActivity( + context, + MainActivity::class.java) + setOnClickPendingIntent(R.id.home_widget_container, pendingIntent) + + // Show Images saved with `renderFlutterWidget` + val image1 = widgetData.getString("image0", null) + + if (image1 != null) { + setImageViewBitmap(R.id.widget_img1, BitmapFactory.decodeFile(image1)) + setViewVisibility(R.id.widget_img1, View.VISIBLE) + } else { + setViewVisibility(R.id.widget_img1, View.GONE) + } + + val image2 = widgetData.getString("image1", null) + + if (image2 != null) { + setImageViewBitmap(R.id.widget_img2, BitmapFactory.decodeFile(image2)) + setViewVisibility(R.id.widget_img2, View.VISIBLE) + } else { + setViewVisibility(R.id.widget_img2, View.GONE) + } + + val image3 = widgetData.getString("image2", null) + + if (image3 != null) { + setImageViewBitmap(R.id.widget_img3, BitmapFactory.decodeFile(image3)) + setViewVisibility(R.id.widget_img3, View.VISIBLE) + } else { + setViewVisibility(R.id.widget_img3, View.GONE) + } + + val image4 = widgetData.getString("image3", null) + + if (image4 != null) { + setImageViewBitmap(R.id.widget_img4, BitmapFactory.decodeFile(image4)) + setViewVisibility(R.id.widget_img4, View.VISIBLE) + } else { + setViewVisibility(R.id.widget_img4, View.GONE) + } + } + + appWidgetManager.updateAppWidget(widgetId, views) + } + } +} \ No newline at end of file diff --git a/android/app/src/main/res/drawable/home_widget_background.xml b/android/app/src/main/res/drawable/home_widget_background.xml new file mode 100644 index 00000000..ca954faa --- /dev/null +++ b/android/app/src/main/res/drawable/home_widget_background.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/layout/home_widget_layout.xml b/android/app/src/main/res/layout/home_widget_layout.xml new file mode 100644 index 00000000..bc12f2d5 --- /dev/null +++ b/android/app/src/main/res/layout/home_widget_layout.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/xml/home_widget_provider.xml b/android/app/src/main/res/xml/home_widget_provider.xml new file mode 100644 index 00000000..503011d8 --- /dev/null +++ b/android/app/src/main/res/xml/home_widget_provider.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/lib/controllers/episode_tab_controller.dart b/lib/controllers/episode_tab_controller.dart index 43dff544..2ee204fe 100644 --- a/lib/controllers/episode_tab_controller.dart +++ b/lib/controllers/episode_tab_controller.dart @@ -1,6 +1,12 @@ import 'package:flutter/material.dart'; +import 'package:home_widget/home_widget.dart'; import 'package:jais/controllers/animes/missing_anime_controller.dart'; import 'package:jais/controllers/episodes/episode_controller.dart'; +import 'package:jais/controllers/logger.dart'; +import 'package:jais/models/anime.dart'; +import 'package:jais/utils.dart'; +import 'package:jais/widgets/animes/anime_image.dart'; +import 'package:jais/widgets/animes/missing_anime_widget.dart'; class EpisodeTabController with ChangeNotifier { late MissingAnimeController missingAnimeController; @@ -17,8 +23,57 @@ class EpisodeTabController with ChangeNotifier { episodeController.reset(); notify(); - missingAnimeController.load().whenComplete(() => notify()); - episodeController.load().whenComplete(() => notify()); + missingAnimeController.load().whenComplete(() async { + notify(); + + try { + final List animeImages = []; + + for (int i = 0; i < 4; i++) { + final MissingAnimeWidget? missingAnimeWidget = + missingAnimeController.list.elementAtOrNull(i) + as MissingAnimeWidget?; + + if (missingAnimeWidget == null) { + break; + } + + final Anime anime = missingAnimeWidget.missingAnime.anime; + + animeImages.add(AnimeImage( + anime: anime, + width: Const.missingAnimeImageWith, + height: Const.missingAnimeImageHeight, + radius: 360, + )); + } + + await Future.delayed(const Duration(seconds: 3)); + info('EpisodeTabController', 'updateHomeWidget()'); + + // await HomeWidget.renderFlutterWidget( + // animeImage, + // logicalSize: const Size(Const.missingAnimeImageWith, Const.missingAnimeImageHeight), + // key: 'dashIcon', + // ); + + await Future.wait([ + for (final AnimeImage image in animeImages) + HomeWidget.renderFlutterWidget( + image, + logicalSize: const Size( + Const.missingAnimeImageWith, Const.missingAnimeImageHeight), + key: 'image${animeImages.indexOf(image)}', + ), + ]); + + await HomeWidget.updateWidget(name: 'HomeWidgetProvider'); + } catch (exception, stackTrace) { + error('EpisodeTabController', '$exception', exception, stackTrace); + } + }); + + episodeController.load().whenComplete(notify); } void notify() { diff --git a/lib/main.dart b/lib/main.dart index a3a757b8..91987da4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:home_widget/home_widget.dart'; import 'package:jais/controllers/animes/anime_detail_controller.dart'; import 'package:jais/controllers/animes/anime_diary_controller.dart'; import 'package:jais/controllers/animes/anime_search_controller.dart'; @@ -24,11 +25,22 @@ Future main() async { ); } -class MyApp extends StatelessWidget { +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { static const Color _mainWhiteThemeColor = Color(0xFFa32d26); static const Color _mainDarkThemeColor = Color(0xFFfde5c9); - const MyApp({super.key}); + @override + void initState() { + super.initState(); + HomeWidget.setAppGroupId('jais'); + } @override Widget build(BuildContext context) { diff --git a/pubspec.lock b/pubspec.lock index 40eade60..104aaf03 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -384,6 +384,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + home_widget: + dependency: "direct main" + description: + name: home_widget + sha256: "9a0ed6094823b07025727a39d3dc2d3e02c5281372af22d72e611137e0b3c10d" + url: "https://pub.dev" + source: hosted + version: "0.3.0" html: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a7c7c08b..ae054d42 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,6 +14,7 @@ dependencies: firebase_messaging: ^14.6.5 flutter: sdk: flutter + home_widget: ^0.3.0 http: ^1.1.0 intl: ^0.18.1 json_annotation: ^4.8.1