Skip to content

Commit

Permalink
wip and handle when in background, too
Browse files Browse the repository at this point in the history
  • Loading branch information
gnprice committed Oct 19, 2023
1 parent 80a25dc commit fa73e5a
Showing 1 changed file with 64 additions and 38 deletions.
102 changes: 64 additions & 38 deletions lib/notifications.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:convert';

import 'package:collection/collection.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
Expand Down Expand Up @@ -47,13 +48,10 @@ class NotificationService {
// TODO(#324) defer notif setup if user not logged into any accounts
// (in order to avoid calling for permissions)

ZulipBinding.instance.firebaseMessagingOnMessage.listen(_onRemoteMessage);
ZulipBinding.instance.notifications.initialize(
const InitializationSettings(
android: AndroidInitializationSettings('zulip_notification'),
),
onDidReceiveNotificationResponse: _onNotificationOpened,
);
ZulipBinding.instance.firebaseMessagingOnMessage.listen(_onForegroundMessage);
FirebaseMessaging.onBackgroundMessage(_onBackgroundMessage);

NotificationDisplayManager._init();

// Get the FCM registration token, now and upon changes. See FCM API docs:
// https://firebase.google.com/docs/cloud-messaging/android/client#sample-register
Expand All @@ -80,43 +78,62 @@ class NotificationService {
// need to save the value.
token.value = value;
}
}

void _onRemoteMessage(FirebaseRemoteMessage message) {
assert(debugLog("notif message: ${message.data}"));
final data = FcmMessage.fromJson(message.data);
switch (data) {
case MessageFcmMessage(): NotificationDisplayManager._onMessageFcmMessage(data, message.data);
case RemoveFcmMessage(): break; // TODO handle
case UnexpectedFcmMessage(): break; // TODO(log)
}
}
void _onForegroundMessage(FirebaseRemoteMessage message) {
assert(debugLog("notif message: ${message.data}"));
_onRemoteMessage(message);
}

void _onNotificationOpened(NotificationResponse response) async {
final data = MessageFcmMessage.fromJson(jsonDecode(response.payload!));
assert(debugLog('opened notif: message ${data.zulipMessageId}, content ${data.content}'));
final navigator = navigatorKey.currentState;
if (navigator == null) return; // TODO(log) handle

final globalStore = GlobalStoreWidget.of(navigator.context);
final account = globalStore.accounts.firstWhereOrNull((account) =>
account.realmUrl == data.realmUri && account.userId == data.userId);
if (account == null) return; // TODO(log)

final narrow = switch (data.recipient) {
FcmMessageStreamRecipient(:var streamId, :var topic) =>
TopicNarrow(streamId, topic),
FcmMessageDmRecipient(:var allRecipientIds) =>
DmNarrow(allRecipientIds: allRecipientIds, selfUserId: account.userId),
};
Future<void> _onBackgroundMessage(FirebaseRemoteMessage message) async {
// This callback will run in a separate isolate from the rest of the app.
// See docs:
// https://firebase.flutter.dev/docs/messaging/usage/#background-messages
assert(() {
debugLogEnabled = true;
return true;
}());
LiveZulipBinding.ensureInitialized();
NotificationDisplayManager._init();

assert(debugLog("notif message in background: ${message.data}"));
_onRemoteMessage(message);
}

assert(debugLog(' account: $account, narrow: $narrow'));
// TODO(nav): Better interact with existing nav stack on notif open
navigator.push(MaterialPageRoute(builder: (context) =>
PerAccountStoreWidget(accountId: account.id,
child: MessageListPage(narrow: narrow))));
void _onRemoteMessage(FirebaseRemoteMessage message) {
final data = FcmMessage.fromJson(message.data);
switch (data) {
case MessageFcmMessage(): NotificationDisplayManager._onMessageFcmMessage(data, message.data);
case RemoveFcmMessage(): break; // TODO handle
case UnexpectedFcmMessage(): break; // TODO(log)
}
}

void _onNotificationOpened(NotificationResponse response) async {
final data = MessageFcmMessage.fromJson(jsonDecode(response.payload!));
assert(debugLog('opened notif: message ${data.zulipMessageId}, content ${data.content}'));
final navigator = navigatorKey.currentState;
if (navigator == null) return; // TODO(log) handle

final globalStore = GlobalStoreWidget.of(navigator.context);
final account = globalStore.accounts.firstWhereOrNull((account) =>
account.realmUrl == data.realmUri && account.userId == data.userId);
if (account == null) return; // TODO(log)

final narrow = switch (data.recipient) {
FcmMessageStreamRecipient(:var streamId, :var topic) =>
TopicNarrow(streamId, topic),
FcmMessageDmRecipient(:var allRecipientIds) =>
DmNarrow(allRecipientIds: allRecipientIds, selfUserId: account.userId),
};

assert(debugLog(' account: $account, narrow: $narrow'));
// TODO(nav): Better interact with existing nav stack on notif open
navigator.push(MaterialPageRoute(builder: (context) =>
PerAccountStoreWidget(accountId: account.id,
child: MessageListPage(narrow: narrow))));
}

/// Service for configuring our Android "notification channel".
class NotificationChannelManager {
static const _kChannelId = 'messages-1';
Expand Down Expand Up @@ -146,6 +163,15 @@ class NotificationDisplayManager {
// We rely on the tag instead.
static const _kNotificationId = 0;

static void _init() {
ZulipBinding.instance.notifications.initialize(
const InitializationSettings(
android: AndroidInitializationSettings('zulip_notification'),
),
onDidReceiveNotificationResponse: _onNotificationOpened,
);
}

static void _onMessageFcmMessage(MessageFcmMessage data, Map<String, dynamic> dataJson) {
NotificationChannelManager._ensureChannel();
assert(debugLog('notif message content: ${data.content}'));
Expand Down

0 comments on commit fa73e5a

Please sign in to comment.