Skip to content

Commit

Permalink
refactor: migrate project to Flutter best practice
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
TheOneWithTheBraid committed Aug 22, 2024
1 parent f81e4b5 commit 0e53e76
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 99 deletions.
7 changes: 7 additions & 0 deletions unifiedpush/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
124 changes: 123 additions & 1 deletion unifiedpush/README.md
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -9,3 +10,124 @@ Check out the documentation here:
1. <https://unifiedpush.org/developers/flutter/>
2. To have Firebase as a fallback, <https://unifiedpush.org/developers/embedded_fcm/>
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.

<details>

<summary> Implementation 5.x.x </summary>

```dart
Future<void> _myPushHandler() async {
await UnifiedPush.registerAppWithDialog();
}
Future<void> _myPushRemoveNoHandler() async {
await UnifiedPush.removeNoDistributorDialogACK();
}
```

</details>

<details>

<summary> Migrated to 6.0.0 </summary>

```dart
static const noDistribAck = "noDistributorAck";
Future<void> _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<String>(
context: context,
builder: pickDistributorDialog(distributors),
);
}
if (picked != null) {
await saveDistributor(picked);
}
}
await registerApp(instance = instance, features = features);
}
Future<void> _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<Widget>(
(d) => SimpleDialogOption(
onPressed: () {
Navigator.pop(context, d);
},
child: Text(d),
),
)
.toList());
};
}
```

</details>
42 changes: 0 additions & 42 deletions unifiedpush/lib/dialogs.dart

This file was deleted.

71 changes: 17 additions & 54 deletions unifiedpush/lib/unifiedpush.dart
Original file line number Diff line number Diff line change
@@ -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<void> initialize({
Expand All @@ -15,70 +13,35 @@ 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<void> registerAppWithDialog(BuildContext context,
[String instance = defaultInstance, List<String>? 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<String>(
context: context,
builder: pickDistributorDialog(distributors),
);
}

if (picked != null) {
await saveDistributor(picked);
}
}

await registerApp(instance = instance, features = features);
}

static Future<void> 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<void> registerApp(
[String instance = defaultInstance, List<String>? features]) async {
UnifiedPushPlatform.instance.registerApp(instance, features ?? []);
static Future<void> registerApp([
String instance = defaultInstance,
List<String> features = const [],
]) async {
await UnifiedPushPlatform.instance.registerApp(instance, features);
}

static Future<void> unregister([String instance = defaultInstance]) async {
UnifiedPushPlatform.instance.unregister(instance);
await UnifiedPushPlatform.instance.unregister(instance);
}

static Future<List<String>> getDistributors([List<String>? features]) async {
return await UnifiedPushPlatform.instance.getDistributors(features ?? []);
static Future<List<String>> getDistributors([
List<String> features = const [],
]) async {
return await UnifiedPushPlatform.instance.getDistributors(features);
}

static Future<String?> getDistributor() async {
return await UnifiedPushPlatform.instance.getDistributor();
}

static Future<void> saveDistributor(String distributor) async {
UnifiedPushPlatform.instance.saveDistributor(distributor);
await UnifiedPushPlatform.instance.saveDistributor(distributor);
}
}
3 changes: 1 addition & 2 deletions unifiedpush/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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

Expand Down

0 comments on commit 0e53e76

Please sign in to comment.