diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index 6ac97a3..9e76d61 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -85,6 +85,7 @@ android {
ndkVersion = flutter.ndkVersion
compileOptions {
+ isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
@@ -111,3 +112,7 @@ android {
flutter {
source = "../.."
}
+
+dependencies {
+ coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
+}
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 450264d..b6707dc 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -53,4 +53,10 @@
+
+
diff --git a/lib/const.dart b/lib/const.dart
index 535361b..28f9f03 100644
--- a/lib/const.dart
+++ b/lib/const.dart
@@ -1,6 +1,7 @@
import 'package:amberflutter/amberflutter.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:ndk/ndk.dart';
import 'package:ndk_amber/ndk_amber.dart';
import 'package:ndk_objectbox/ndk_objectbox.dart';
@@ -38,6 +39,7 @@ const searchRelays = ["wss://relay.nostr.band", "wss://search.nos.today"];
final loginData = LoginData();
final RouteObserver> routeObserver =
RouteObserver>();
+final localNotifications = FlutterLocalNotificationsPlugin();
Future initLogin() async {
// reload / cache login data
diff --git a/lib/main.dart b/lib/main.dart
index 21afeda..666dff5 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,8 +1,11 @@
+import 'dart:developer' as developer;
+
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:zap_stream_flutter/app.dart';
import 'package:zap_stream_flutter/const.dart';
import 'package:zap_stream_flutter/i18n/strings.g.dart';
+import 'package:zap_stream_flutter/notifications.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
@@ -10,5 +13,9 @@ Future main() async {
await Firebase.initializeApp();
await initLogin();
+ setupNotifications().catchError((e) {
+ developer.log("Failed to setup notifications: $e");
+ });
+
runZapStream();
}
diff --git a/lib/notifications.dart b/lib/notifications.dart
new file mode 100644
index 0000000..50d5968
--- /dev/null
+++ b/lib/notifications.dart
@@ -0,0 +1,103 @@
+import 'dart:developer' as developer;
+import 'dart:io';
+
+import 'package:firebase_messaging/firebase_messaging.dart';
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+import 'package:ndk/ndk.dart';
+import 'package:zap_stream_flutter/const.dart';
+import 'package:http/http.dart' as http;
+
+class Notepush {
+ final String base;
+ final EventSigner signer;
+
+ Notepush(this.base, {required this.signer});
+
+ Future register(String token) async {
+ final pubkey = signer.getPublicKey();
+ final url =
+ "$base/user-info/$pubkey/${Uri.encodeComponent(token)}?backend=fcm";
+ developer.log(url);
+ final auth = await _makeAuth("PUT", url);
+ final rsp = await http.put(
+ Uri.parse(url),
+ headers: {
+ "authorization": "Nostr $auth",
+ "accept": "application/json",
+ "content-type": "application/json",
+ },
+ );
+ developer.log(rsp.body);
+ return rsp.body;
+ }
+
+ Future _makeAuth(String method, String url) async {
+ final pubkey = signer.getPublicKey();
+ final authEvent = Nip01Event(
+ pubKey: pubkey,
+ kind: 27235,
+ tags: [
+ ["u", url],
+ ["method", "PUT"],
+ ],
+ content: "",
+ );
+ await signer.sign(authEvent);
+ return authEvent.toBase64();
+ }
+}
+
+Future setupNotifications() async {
+ final signer = ndk.accounts.getLoggedAccount()?.signer;
+ if (signer != null) {
+ final pusher = Notepush("http://10.0.2.2:8000", signer: signer);
+ final fbase = FirebaseMessaging.instance;
+ FirebaseMessaging.onMessage.listen((msg) {
+ developer.log(msg.notification?.body ?? "");
+ final notification = msg.notification;
+ if (notification != null && notification.android != null) {
+ /*FlutterLocalNotificationsPlugin().show(
+ notification.hashCode,
+ notification.title,
+ notification.body,
+ NotificationDetails(
+ android: AndroidNotificationDetails(
+ notification.android!.channelId ?? "fcm",
+ "fcm",
+ ),
+ ),
+ );*/
+ // TODO: foreground notification
+ }
+ });
+ await fbase.setAutoInitEnabled(true);
+ await fbase.setForegroundNotificationPresentationOptions(
+ alert: true,
+ badge: true,
+ sound: true,
+ );
+ await fbase.requestPermission(provisional: true);
+
+ await localNotifications.initialize(
+ InitializationSettings(
+ android: AndroidInitializationSettings("@mipmap/ic_launcher"),
+ ),
+ );
+ fbase.onTokenRefresh.listen((token) async {
+ developer.log("NEW TOKEN: $token");
+ await pusher.register(token);
+ });
+
+ if (Platform.isIOS) {
+ final apnsToken = await FirebaseMessaging.instance.getAPNSToken();
+ if (apnsToken == null) {
+ throw "APNS token not availble";
+ }
+ }
+ final fcmToken = await FirebaseMessaging.instance.getToken();
+ if (fcmToken == null) {
+ throw "Push token is null";
+ }
+ await pusher.register(fcmToken);
+ }
+}
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 6841ae6..8a74080 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -9,6 +9,7 @@ import emoji_picker_flutter
import file_selector_macos
import firebase_core
import firebase_messaging
+import flutter_local_notifications
import flutter_secure_storage_macos
import objectbox_flutter_libs
import package_info_plus
@@ -25,6 +26,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
+ FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
ObjectboxFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "ObjectboxFlutterLibsPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
diff --git a/pubspec.lock b/pubspec.lock
index ceaab27..0e32520 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -374,6 +374,38 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.0.0"
+ flutter_local_notifications:
+ dependency: "direct main"
+ description:
+ name: flutter_local_notifications
+ sha256: b94a50aabbe56ef254f95f3be75640f99120429f0a153b2dc30143cffc9bfdf3
+ url: "https://pub.dev"
+ source: hosted
+ version: "19.2.1"
+ flutter_local_notifications_linux:
+ dependency: transitive
+ description:
+ name: flutter_local_notifications_linux
+ sha256: e3c277b2daab8e36ac5a6820536668d07e83851aeeb79c446e525a70710770a5
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.0.0"
+ flutter_local_notifications_platform_interface:
+ dependency: transitive
+ description:
+ name: flutter_local_notifications_platform_interface
+ sha256: "2569b973fc9d1f63a37410a9f7c1c552081226c597190cb359ef5d5762d1631c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "9.0.0"
+ flutter_local_notifications_windows:
+ dependency: transitive
+ description:
+ name: flutter_local_notifications_windows
+ sha256: f8fc0652a601f83419d623c85723a3e82ad81f92b33eaa9bcc21ea1b94773e6e
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.0"
flutter_localizations:
dependency: "direct main"
description: flutter
@@ -494,7 +526,7 @@ packages:
source: hosted
version: "0.15.6"
http:
- dependency: transitive
+ dependency: "direct main"
description:
name: http
sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b"
@@ -1095,6 +1127,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.7.4"
+ timezone:
+ dependency: transitive
+ description:
+ name: timezone
+ sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.10.1"
typed_data:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 4276648..1a61d13 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -41,6 +41,8 @@ dependencies:
sdk: flutter
firebase_core: ^3.13.1
firebase_messaging: ^15.2.6
+ http: ^1.4.0
+ flutter_local_notifications: ^19.2.1
dependency_overrides:
ndk:
diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake
index 79a04d4..e1a7c66 100644
--- a/windows/flutter/generated_plugins.cmake
+++ b/windows/flutter/generated_plugins.cmake
@@ -13,6 +13,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
+ flutter_local_notifications_windows
rust_lib_ndk
)