forked from Nexus/nexus
send notifications natively
This commit is contained in:
parent
11d83ee067
commit
2beb6dcb9b
14 changed files with 225 additions and 30 deletions
97
lib/controllers/notifications.dart
Normal file
97
lib/controllers/notifications.dart
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
import "dart:io";
|
||||
|
||||
import "package:flutter_local_notifications/flutter_local_notifications.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
|
||||
class NotificationsController
|
||||
extends AsyncNotifier<FlutterLocalNotificationsPlugin> {
|
||||
@override
|
||||
Future<FlutterLocalNotificationsPlugin> build() async {
|
||||
final notifications = FlutterLocalNotificationsPlugin();
|
||||
|
||||
final darwin = DarwinInitializationSettings();
|
||||
|
||||
await notifications.initialize(
|
||||
settings: .new(
|
||||
windows: .new(
|
||||
appName: "Nexus",
|
||||
appUserModelId: "nexus.federated.nexus",
|
||||
guid: "dde78daf-130f-4e46-a80a-e31deeab45d7",
|
||||
),
|
||||
android: .new("ic_launcher"),
|
||||
iOS: darwin,
|
||||
macOS: darwin,
|
||||
linux: .new(defaultActionName: "Open"),
|
||||
),
|
||||
onDidReceiveNotificationResponse: (details) {
|
||||
print(details.data);
|
||||
},
|
||||
);
|
||||
|
||||
return notifications;
|
||||
}
|
||||
|
||||
Future<bool> requestPermissions() async {
|
||||
final controller = await future;
|
||||
|
||||
if (Platform.isIOS) {
|
||||
return await controller
|
||||
.resolvePlatformSpecificImplementation<
|
||||
IOSFlutterLocalNotificationsPlugin
|
||||
>()
|
||||
?.requestPermissions(alert: true, badge: true, sound: true) ??
|
||||
true;
|
||||
} else if (Platform.isMacOS) {
|
||||
return await controller
|
||||
.resolvePlatformSpecificImplementation<
|
||||
MacOSFlutterLocalNotificationsPlugin
|
||||
>()
|
||||
?.requestPermissions(alert: true, badge: true, sound: true) ??
|
||||
true;
|
||||
} else if (Platform.isAndroid) {
|
||||
return await controller
|
||||
.resolvePlatformSpecificImplementation<
|
||||
AndroidFlutterLocalNotificationsPlugin
|
||||
>()
|
||||
?.requestNotificationsPermission() ??
|
||||
true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> send({
|
||||
required int id,
|
||||
required String title,
|
||||
String? body,
|
||||
File? icon,
|
||||
String? payload,
|
||||
}) async {
|
||||
final notificationDetails = NotificationDetails(
|
||||
android: .new(
|
||||
"messages",
|
||||
"Messages",
|
||||
largeIcon: icon == null ? null : FilePathAndroidBitmap(icon.path),
|
||||
),
|
||||
iOS: .new(),
|
||||
macOS: .new(),
|
||||
linux: .new(icon: icon == null ? null : FilePathLinuxIcon(icon.path)),
|
||||
windows: .new(),
|
||||
);
|
||||
|
||||
final controller = await future;
|
||||
await controller.show(
|
||||
id: id,
|
||||
title: title,
|
||||
body: body,
|
||||
notificationDetails: notificationDetails,
|
||||
payload: payload,
|
||||
);
|
||||
}
|
||||
|
||||
static final provider =
|
||||
AsyncNotifierProvider<
|
||||
NotificationsController,
|
||||
FlutterLocalNotificationsPlugin
|
||||
>(NotificationsController.new);
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import "package:m3e_buttons/m3e_buttons.dart";
|
|||
import "package:nexus/controllers/account_data.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
import "package:nexus/controllers/client_state.dart";
|
||||
import "package:nexus/controllers/notifications.dart";
|
||||
import "package:nexus/controllers/settings.dart";
|
||||
import "package:nexus/controllers/unified_push.dart";
|
||||
import "package:nexus/controllers/spec_versions.dart";
|
||||
|
|
@ -132,17 +133,30 @@ class SettingsSectionsController
|
|||
orElse: () => false,
|
||||
)
|
||||
? pusherRegistered.maybeWhen(
|
||||
data: (_) =>
|
||||
(value) => value
|
||||
? ref
|
||||
data: (_) => (value) async {
|
||||
if (value) {
|
||||
if (await ref
|
||||
.watch(
|
||||
NotificationsController
|
||||
.provider
|
||||
.notifier,
|
||||
)
|
||||
.requestPermissions()) {
|
||||
ref
|
||||
.watch(
|
||||
UnifiedPushController
|
||||
.provider
|
||||
.notifier,
|
||||
)
|
||||
.register()
|
||||
.onError(showError)
|
||||
: /*deregeister*/ null,
|
||||
.onError(showError);
|
||||
} else {
|
||||
// TODO: Handle not granted
|
||||
}
|
||||
} else {
|
||||
// TODO: Deregister
|
||||
}
|
||||
},
|
||||
orElse: () => null,
|
||||
)
|
||||
: null,
|
||||
|
|
|
|||
|
|
@ -3,9 +3,12 @@ import "dart:io";
|
|||
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:intl/intl.dart";
|
||||
import "package:nexus/controllers/notifications.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
import "package:nexus/main.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
import "package:nexus/controllers/client_state.dart";
|
||||
import "package:nexus/models/content/message.dart";
|
||||
import "package:nexus/models/requests/register_pusher.dart";
|
||||
import "package:unifiedpush/unifiedpush.dart";
|
||||
import "package:unifiedpush_storage_shared_preferences/storage.dart";
|
||||
|
|
@ -38,10 +41,29 @@ class UnifiedPushController extends AsyncNotifier<bool> {
|
|||
);
|
||||
},
|
||||
onMessage: (message, instance) async {
|
||||
if (message.decrypted == false) {
|
||||
// TODO: Handle more gracefully, show option to re-register pusher
|
||||
throw Exception("Failed to decrypt notification");
|
||||
}
|
||||
final event = await client.handlePush(
|
||||
json.decode(String.fromCharCodes(message.content)),
|
||||
);
|
||||
print(event);
|
||||
|
||||
final room = ref.read(
|
||||
RoomsController.provider.select((rooms) => rooms[event.roomId]),
|
||||
);
|
||||
|
||||
await ref
|
||||
.read(NotificationsController.provider.notifier)
|
||||
.send(
|
||||
id: event.eventId.hashCode & 0x7fffffff,
|
||||
title: room?.metadata?.name ?? "New Message",
|
||||
body: switch (event.content) {
|
||||
MessageContent(:final body) => body,
|
||||
// TODO: Handle more types
|
||||
_ => null,
|
||||
},
|
||||
);
|
||||
},
|
||||
onRegistrationFailed: (error, instance) => throw error,
|
||||
onUnregistered: (instance) => ref.invalidateSelf(),
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import "package:media_kit/media_kit.dart";
|
|||
import "package:nexus/controllers/client.dart";
|
||||
import "package:nexus/controllers/client_state.dart";
|
||||
import "package:nexus/controllers/multi_provider.dart";
|
||||
import "package:nexus/controllers/notifications.dart";
|
||||
import "package:nexus/controllers/settings.dart";
|
||||
import "package:nexus/controllers/shared_prefs.dart";
|
||||
import "package:nexus/controllers/unified_push.dart";
|
||||
|
|
@ -146,6 +147,7 @@ class const App(final bool isInBackground, {super.key})
|
|||
IListConst([
|
||||
SharedPrefsController.provider,
|
||||
ClientController.provider,
|
||||
NotificationsController.provider,
|
||||
UnifiedPushController.provider,
|
||||
]),
|
||||
),
|
||||
|
|
|
|||
Loading…
Reference in a new issue