From 0e53e769d116f960b5dc75127d06042a597b8e29 Mon Sep 17 00:00:00 2001 From: The one with the braid Date: Mon, 12 Aug 2024 13:01:28 +0200 Subject: [PATCH] refactor: migrate project to Flutter best practice * BREAKING: remove async gaps from `BuildContext` * See README for migration * BREAKING: remove built-in provider storage * See README for migration * Fix missing await statement for asynchronous tasks Signed-off-by: The one with the braid --- unifiedpush/CHANGELOG.md | 7 ++ unifiedpush/README.md | 124 ++++++++++++++++++++++++++++++- unifiedpush/lib/dialogs.dart | 42 ----------- unifiedpush/lib/unifiedpush.dart | 71 +++++------------- unifiedpush/pubspec.yaml | 3 +- 5 files changed, 148 insertions(+), 99 deletions(-) delete mode 100644 unifiedpush/lib/dialogs.dart diff --git a/unifiedpush/CHANGELOG.md b/unifiedpush/CHANGELOG.md index cf08acc..7d72a55 100644 --- a/unifiedpush/CHANGELOG.md +++ b/unifiedpush/CHANGELOG.md @@ -1,3 +1,10 @@ +## 6.0.0 +* BREAKING: remove async gaps from `BuildContext` + * See README for migration +* BREAKING: remove built-in provider storage + * See README for migration +* Fix missing await statement for asynchronous tasks + ## 5.0.1 * Upgrade max sdk diff --git a/unifiedpush/README.md b/unifiedpush/README.md index 8102341..af81cfb 100644 --- a/unifiedpush/README.md +++ b/unifiedpush/README.md @@ -1,6 +1,7 @@ # UnifiedPush flutter-connector -UnifiedPush is specifications and tools that let the user choose how push notifications are delivered. All in a free and open source way. +UnifiedPush is specifications and tools that let the user choose how push notifications are delivered. All in a free and +open source way. ## Getting Started @@ -9,3 +10,124 @@ Check out the documentation here: 1. 2. To have Firebase as a fallback, 3. An [example app](../example) can be found here. + +## Migrating from UnifiedPush 5.x.x + +With version 6.0.0, UnifiedPush removes + +- `UnifiedPush.registerAppWithDialog` +- `UnifiedPush.removeNoDistributorDialogACK` + +The reason is simple as: + +The previous approach was using async gaps in the use of a `BuildContext`. With the new approach, we hand over the +possibility for devs to properly handle async gaps of the registration dialog on their own. Additionally, this enables a +custom registration dialog, localization and better integration into the embedding app. An additional advantage is a +more minimal dependency chain since storage of the UnifiedPush state is now the apps responsibility. + +
+ + Implementation 5.x.x + +```dart +Future _myPushHandler() async { + await UnifiedPush.registerAppWithDialog(); +} + +Future _myPushRemoveNoHandler() async { + await UnifiedPush.removeNoDistributorDialogACK(); +} +``` + +
+ +
+ + Migrated to 6.0.0 + +```dart + +static const noDistribAck = "noDistributorAck"; + +Future _myPushHandler() async { + final distributor = await UnifiedPush.getDistributor(); + final prefs = await SharedPreferences.getInstance(); + String? picked; + + if (distributor == null) { + final distributors = await getDistributors(features = features); + if (distributors.isEmpty) { + if (!(prefs.getBool(noDistribAck) ?? false)) { + return showDialog( + context: context, + builder: noDistributorDialog(onDismissed: () { + prefs.setBool(noDistribAck, true); + })); + } + } else if (distributors.length == 1) { + picked = distributors.single; + } else { + picked = await showDialog( + context: context, + builder: pickDistributorDialog(distributors), + ); + } + + if (picked != null) { + await saveDistributor(picked); + } + } + + await registerApp(instance = instance, features = features); +} + +Future _myPushRemoveNoHandler() async { + final prefs = await SharedPreferences.getInstance(); + prefs.remove(noDistribAck); +} + + +noDistributorDialog({required Null Function() onDismissed}) { + return (BuildContext context) { + return AlertDialog( + title: const Text('Push Notifications'), + content: const SingleChildScrollView( + child: SelectableText( + "You need to install a distributor for push notifications to work.\nYou can find more information at: https://unifiedpush.org/users/intro/")), + actions: [ + TextButton( + child: const Text('Dismiss'), + onPressed: () { + onDismissed(); + Navigator.of(context).pop(); + }, + ), + TextButton( + child: const Text('Close'), + onPressed: Navigator.of(context).pop, + ), + ], + ); + }; +} + +pickDistributorDialog(distributors) { + return (BuildContext context) { + return SimpleDialog( + title: const Text('Select push distributor'), + children: distributors + .map( + (d) => SimpleDialogOption( + onPressed: () { + Navigator.pop(context, d); + }, + child: Text(d), + ), + ) + .toList()); + }; +} + +``` + +
\ No newline at end of file diff --git a/unifiedpush/lib/dialogs.dart b/unifiedpush/lib/dialogs.dart deleted file mode 100644 index bba0e4f..0000000 --- a/unifiedpush/lib/dialogs.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:flutter/material.dart'; - -noDistributorDialog({required Null Function() onDismissed}) { - return (BuildContext context) { - return AlertDialog( - title: const Text('Push Notifications'), - content: const SingleChildScrollView( - child: SelectableText( - "You need to install a distributor for push notifications to work.\nYou can find more information at: https://unifiedpush.org/users/intro/")), - actions: [ - TextButton( - child: const Text('Dismiss'), - onPressed: () { - onDismissed(); - Navigator.of(context).pop(); - }, - ), - TextButton( - child: const Text('Close'), - onPressed: Navigator.of(context).pop, - ), - ], - ); - }; -} - -pickDistributorDialog(distributors) { - return (BuildContext context) { - return SimpleDialog( - title: const Text('Select push distributor'), - children: distributors - .map( - (d) => SimpleDialogOption( - onPressed: () { - Navigator.pop(context, d); - }, - child: Text(d), - ), - ) - .toList()); - }; -} diff --git a/unifiedpush/lib/unifiedpush.dart b/unifiedpush/lib/unifiedpush.dart index fdb51f3..2ef7afd 100644 --- a/unifiedpush/lib/unifiedpush.dart +++ b/unifiedpush/lib/unifiedpush.dart @@ -1,11 +1,9 @@ import 'dart:async'; import 'dart:typed_data'; -import 'package:flutter/material.dart'; -import 'package:shared_preferences/shared_preferences.dart'; + import 'package:unifiedpush_platform_interface/unifiedpush_platform_interface.dart'; import 'constants.dart'; -import 'dialogs.dart'; class UnifiedPush { static Future initialize({ @@ -15,63 +13,28 @@ class UnifiedPush { void Function(Uint8List message, String instance)? onMessage, }) async { await UnifiedPushPlatform.instance.initializeCallback( - onNewEndpoint: (String e, String i) async => onNewEndpoint?.call(e, i), - onRegistrationFailed: (String i) async => onRegistrationFailed?.call(i), - onUnregistered: (String i) async => onUnregistered?.call(i), - onMessage: (Uint8List m, String i) async => onMessage?.call(m, i)); - } - - static const noDistribAck = "noDistributorAck"; - - static Future registerAppWithDialog(BuildContext context, - [String instance = defaultInstance, List? features]) async { - var distributor = await getDistributor(); - final prefs = await SharedPreferences.getInstance(); - String? picked; - - if (distributor == null) { - final distributors = await getDistributors(features = features); - if (distributors.isEmpty) { - if (!(prefs.getBool(noDistribAck) ?? false)) { - return showDialog( - context: context, - builder: noDistributorDialog(onDismissed: () { - prefs.setBool(noDistribAck, true); - })); - } - } else if (distributors.length == 1) { - picked = distributors.single; - } else { - picked = await showDialog( - context: context, - builder: pickDistributorDialog(distributors), - ); - } - - if (picked != null) { - await saveDistributor(picked); - } - } - - await registerApp(instance = instance, features = features); - } - - static Future removeNoDistributorDialogACK() async { - final prefs = await SharedPreferences.getInstance(); - prefs.remove(noDistribAck); + onNewEndpoint: (String e, String i) async => onNewEndpoint?.call(e, i), + onRegistrationFailed: (String i) async => onRegistrationFailed?.call(i), + onUnregistered: (String i) async => onUnregistered?.call(i), + onMessage: (Uint8List m, String i) async => onMessage?.call(m, i), + ); } - static Future registerApp( - [String instance = defaultInstance, List? features]) async { - UnifiedPushPlatform.instance.registerApp(instance, features ?? []); + static Future registerApp([ + String instance = defaultInstance, + List features = const [], + ]) async { + await UnifiedPushPlatform.instance.registerApp(instance, features); } static Future unregister([String instance = defaultInstance]) async { - UnifiedPushPlatform.instance.unregister(instance); + await UnifiedPushPlatform.instance.unregister(instance); } - static Future> getDistributors([List? features]) async { - return await UnifiedPushPlatform.instance.getDistributors(features ?? []); + static Future> getDistributors([ + List features = const [], + ]) async { + return await UnifiedPushPlatform.instance.getDistributors(features); } static Future getDistributor() async { @@ -79,6 +42,6 @@ class UnifiedPush { } static Future saveDistributor(String distributor) async { - UnifiedPushPlatform.instance.saveDistributor(distributor); + await UnifiedPushPlatform.instance.saveDistributor(distributor); } } diff --git a/unifiedpush/pubspec.yaml b/unifiedpush/pubspec.yaml index 3681771..e369b9d 100644 --- a/unifiedpush/pubspec.yaml +++ b/unifiedpush/pubspec.yaml @@ -1,6 +1,6 @@ name: unifiedpush description: Push notifications with the provider chosen by the user. -version: 5.0.1 +version: 6.0.0 homepage: "https://unifiedpush.org/developers/flutter" documentation: "https://unifiedpush.org/developers/flutter" repository: https://codeberg.org/UnifiedPush/flutter-connector @@ -13,7 +13,6 @@ environment: dependencies: flutter: sdk: flutter - shared_preferences: ^2.0.11 unifiedpush_platform_interface: ^2.0.0 unifiedpush_android: ^2.0.0