From 537abae7716f72e0cbe869cf45f8cf90488c014e Mon Sep 17 00:00:00 2001 From: Vishnu Mohandas Date: Fri, 21 May 2021 04:53:29 +0530 Subject: [PATCH] Show a notification on Android when storage limit is exceeded --- .../main/res/drawable/notification_icon.png | Bin 0 -> 901 bytes lib/main.dart | 2 + lib/services/notification_service.dart | 44 ++++++++++++++++++ lib/services/sync_service.dart | 16 +++++++ pubspec.lock | 21 +++++++++ pubspec.yaml | 1 + 6 files changed, 84 insertions(+) create mode 100644 android/app/src/main/res/drawable/notification_icon.png create mode 100644 lib/services/notification_service.dart diff --git a/android/app/src/main/res/drawable/notification_icon.png b/android/app/src/main/res/drawable/notification_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..05f1fc8c36bd41db3046ad7af2d89474a26de6e4 GIT binary patch literal 901 zcmV;01A6?4P)@mB7MGRGxi@ez4v#3< z57;%qm^b2+5n~?5wk~t)JzRhT4MiH_1#Dd9_zS8-xX#<=`AonqBZ~i63o&lMzYTHj zYa^GLgRK}e6lSr-Sl6jP7lyd9tynVy4>z2YhdYS3*sutD+m6?3*wS$253s4DxF;Io zUfM;>Uc%iC+rcv(#=Ttqwzs>hxV?i9Yl?7c3bE_H1)p{uyB9QXKPRRT|HX#*+q;fm z9B!&feyGJepAmDYJB)WuBYshMpl$)CIET7N+k2)phhp$(P4WY5o6_gEnmOz%U7yZj zUrq9z8;*Xi{e0>AbPg|dU+PsmP`W;y)9~3 z-1gZkT1_*I&xx`iE@TSh+6LCXl9#5Z`h?XhPLZu{TnbGEm%_hcw2Tk_7uyOo?r_FOm^dzuxxnRdNcQ`jW{e!&) ztS_C@%u+o?-HmtfCBDN+{B*|Wr0OgjSic literal 0 HcmV?d00001 diff --git a/lib/main.dart b/lib/main.dart index 48345a6be..a3c7e61b1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,6 +12,7 @@ import 'package:photos/db/upload_locks_db.dart'; import 'package:photos/services/billing_service.dart'; import 'package:photos/services/collections_service.dart'; import 'package:photos/services/memories_service.dart'; +import 'package:photos/services/notification_service.dart'; import 'package:photos/services/sync_service.dart'; import 'package:photos/ui/app_lock.dart'; import 'package:photos/ui/home_widget.dart'; @@ -118,6 +119,7 @@ Future _init(bool isBackground) async { _logger.info("Initializing..."); InAppPurchaseConnection.enablePendingPurchases(); CryptoUtil.init(); + await NotificationService.instance.init(); await Network.instance.init(); await Configuration.instance.init(); await BillingService.instance.init(); diff --git a/lib/services/notification_service.dart b/lib/services/notification_service.dart new file mode 100644 index 000000000..9303922f4 --- /dev/null +++ b/lib/services/notification_service.dart @@ -0,0 +1,44 @@ +import 'dart:io'; + +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; + +class NotificationService { + static final NotificationService instance = + NotificationService._privateConstructor(); + + NotificationService._privateConstructor(); + final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = + FlutterLocalNotificationsPlugin(); + + Future init() async { + const AndroidInitializationSettings initializationSettingsAndroid = + AndroidInitializationSettings('notification_icon'); + final InitializationSettings initializationSettings = + InitializationSettings( + android: initializationSettingsAndroid, + ); + await _flutterLocalNotificationsPlugin.initialize(initializationSettings, + onSelectNotification: selectNotification); + } + + Future selectNotification(String payload) async {} + + Future showNotification(String title, String message) async { + if (!Platform.isAndroid) { + return; + } + const AndroidNotificationDetails androidPlatformChannelSpecifics = + AndroidNotificationDetails( + 'io.ente.photos', + 'ente', + 'ente alerts', + importance: Importance.max, + priority: Priority.high, + showWhen: false, + ); + const NotificationDetails platformChannelSpecifics = + NotificationDetails(android: androidPlatformChannelSpecifics); + await _flutterLocalNotificationsPlugin.show( + 0, title, message, platformChannelSpecifics); + } +} diff --git a/lib/services/sync_service.dart b/lib/services/sync_service.dart index fc3f33c04..07edb1149 100644 --- a/lib/services/sync_service.dart +++ b/lib/services/sync_service.dart @@ -4,6 +4,7 @@ import 'package:computer/computer.dart'; import 'package:connectivity/connectivity.dart'; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; +import 'package:photos/core/constants.dart'; import 'package:photos/core/errors.dart'; import 'package:photos/core/event_bus.dart'; import 'package:photos/core/network.dart'; @@ -15,6 +16,7 @@ import 'package:photos/events/subscription_purchased_event.dart'; import 'package:photos/events/trigger_logout_event.dart'; import 'package:photos/models/file_type.dart'; import 'package:photos/services/collections_service.dart'; +import 'package:photos/services/notification_service.dart'; import 'package:photos/utils/diff_fetcher.dart'; import 'package:photo_manager/photo_manager.dart'; import 'package:photos/utils/file_sync_util.dart'; @@ -44,6 +46,8 @@ class SyncService { static const kDbUpdationTimeKey = "db_updation_time"; static const kHasCompletedFirstImportKey = "has_completed_firstImport"; static const kHasGrantedPermissionsKey = "has_granted_permissions"; + static const kLastStorageLimitExceededNotificationPushTime = + "last_storage_limit_exceeded_notification_push_time"; static const kLastBackgroundUploadDetectedTime = "last_background_upload_detected_time"; static const kDiffLimit = 2500; @@ -114,6 +118,7 @@ class SyncService { Bus.instance.fire(SyncStatusUpdate(SyncStatus.error, error: NoActiveSubscriptionError())); } on StorageLimitExceededError { + _showStorageLimitExceededNotification(); Bus.instance.fire(SyncStatusUpdate(SyncStatus.error, error: StorageLimitExceededError())); } on UnauthorizedError { @@ -449,4 +454,15 @@ class SyncService { "fileIDs": fileIDs, }); } + + void _showStorageLimitExceededNotification() async { + final lastNotificationShownTime = + _prefs.getInt(kLastStorageLimitExceededNotificationPushTime) ?? 0; + final now = DateTime.now().microsecondsSinceEpoch; + if ((now - lastNotificationShownTime) > MICRO_SECONDS_IN_DAY) { + await _prefs.setInt(kLastStorageLimitExceededNotificationPushTime, now); + NotificationService.instance.showNotification( + "storage limit exceeded", "sorry, we had to pause your backups"); + } + } } diff --git a/pubspec.lock b/pubspec.lock index 473a2aa2b..f837b562e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -265,6 +265,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.9.0" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.0+4" + flutter_local_notifications_platform_interface: + dependency: transitive + description: + name: flutter_local_notifications_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" flutter_native_splash: dependency: "direct dev" description: @@ -770,6 +784,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.19" + timezone: + dependency: transitive + description: + name: timezone + url: "https://pub.dartlang.org" + source: hosted + version: "0.7.0" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index ba387639b..d82871b0b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -79,6 +79,7 @@ dependencies: move_to_background: ^1.0.2 loading_animations: ^2.1.0 dots_indicator: ^2.0.0 + flutter_local_notifications: ^5.0.0+4 dev_dependencies: flutter_test: