Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace flutter_local_notifications with pigeon bindings #856

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

rajveermalviya
Copy link
Collaborator

@rajveermalviya rajveermalviya commented Aug 1, 2024

Fixes: #351

@gnprice
Copy link
Member

gnprice commented Aug 2, 2024

Exciting!

LMK if there are questions you have for me at this stage, or particular spots in the code you'd like an early high-level review of.

@rajveermalviya
Copy link
Collaborator Author

@gnprice, I have a question about whether this implementation is desirable. Currently it creates a pending intent using the ACTION_VIEW action with a URL payload for each notification. When the user opens the notification, the intent functions as a deeplink and is handled by the existing URL handling in Flutter. Then this url is parsed and handled here for incoming intents while the app is open and while the app is closed.

Also, when the intent is created we set explicity set the reciever component so that ensures that this instance of zulip://notificiation_open url intent is only handled by our app.

This way this implementation avoids creating a custom intent handler and reuses Flutter existing URL route handler.

@rajveermalviya
Copy link
Collaborator Author

Moved the discussion to chat thread here — https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/flutter.3A.20Drop.20.60flutter_local_notifications.60.20.23F856/near/1910352

Copy link
Collaborator

@Khader-1 Khader-1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @rajveermalviya! LGTM.

@Khader-1 Khader-1 added mentor review GSoC mentor review needed. and removed buddy review GSoC buddy review needed. labels Aug 23, 2024
Copy link
Collaborator

@kenclary kenclary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@gnprice gnprice added the maintainer review PR ready for review by Zulip maintainers label Sep 5, 2024
Copy link
Collaborator

@chrisbobbe chrisbobbe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Comments below, all small. Also, I haven't done any manual testing of this; did you?

@@ -87,7 +87,7 @@ private class AndroidNotificationHost(val context: Context)
// FlutterLocalNotificationsPlugin, which handles receiving the Intent.
// TODO take care of receiving the notification-opened Intent ourselves
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notif [nfc]: Replace intentPayload with AndroidIntent.extras

At this commit, the reference to "This […] extra name" seems like it's dangling; it's not clear from the code next to the comment that it means the string "payload". Can you make that fact clearer? It may also help to comment on the spot in the code where the string "payload" appears.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I see that this special name "payload" remains after removing flutter_local_notifications. Is that because we're happy/neutral to keep it around, or is it a sign that there's still helpful cleanup of flutter_local_notifications to do?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated with main commit (notif: Handle opening of notification via URI intents) removing dangling references for payload.

HomePage.buildRoute(accountId: accountId),
InboxPage.buildRoute(accountId: accountId),
notificationRoute,
] else if (initialAccountId != null) ...[
HomePage.buildRoute(accountId: initialAccountId),
InboxPage.buildRoute(accountId: initialAccountId),
],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notif: Introduce URL based notif open implementation

This looks like maybe a behavior change, right? Before, when you opened the app from a notification, the home page and inbox page would be for the first account in the list (the "initial account" in initialAccountId), even if that was different from the notification's account. Now, those pages are chosen to match the notification.

I agree the new behavior seems better. Let's mention the change, though, and any other user-visible behavior changes, in the commit message.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this behaviour (for now) to keep the diff smaller, this would probably be better done in a separate PR.

@chrisbobbe
Copy link
Collaborator

It looks like there's been some further discussion on these changes: https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/narrow.20links.20with.20userid.3F/near/1941174

Please post here when that's resolved and this is ready for another review. 🙂

@chrisbobbe chrisbobbe removed the mentor review GSoC mentor review needed. label Oct 9, 2024
…M messages

Prep commit for upcoming implementation where for foreground
notifications it'd depend on GlobalStore inherited widget and thus would
require the use of `testWidget` instead of `test` function.
…ntent

Prep work for upcoming support of receiving notification-opened Intents
without relying on `package:flutter_local_notifications`.
@rajveermalviya
Copy link
Collaborator Author

Apologies for the delay in the revision. Thanks for the previous review @chrisbobbe, pushed a new revision, PTAL.

@chrisbobbe

This comment was marked as resolved.

@rajveermalviya

This comment was marked as resolved.

@chrisbobbe

This comment was marked as resolved.

Copy link
Collaborator

@chrisbobbe chrisbobbe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Small comments below from a very light review; Greg knows this system better than I do, and I'll go ahead and mark for his review to save some time. 🙂

@@ -87,6 +87,36 @@ data class NotificationChannel (
}
}

/**
* Corresponds to `android.content.Intent`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notif [nfc]: Replace PendingIntent.intentPayload with PendingIntent.intent

Hmm, tools/check pigeon fails for me at this commit; do you reproduce?

Running pigeon...
Error: there were changes to pigeons:
 M android/app/src/main/kotlin/com/zulip/flutter/Notifications.g.kt
 M lib/host/android_notifications.g.dart

FAILED: pigeon

But the commit after it passes. So maybe some generated code was committed in that later commit but should have been committed here.

expectedTitle: expectedTitle,
expectedTagComponent: expectedTagComponent);
testBinding.androidNotificationHost.clearActiveNotifications();
void testNotification(String description, Future<void> Function(Future<void> Function(FcmMessage data) receiveFcmMessage) body, {http.Client Function()? httpClientFactory}) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notif test: Use testNotification to test foreground and background FCM messages

It looks like this commit is adding a new helper named testNotification. Could you reword the summary line to be clearer about that? At first this looked like it might be about adding callers of an existing testNotification function.

@chrisbobbe chrisbobbe added integration review Added by maintainers when PR may be ready for integration and removed maintainer review PR ready for review by Zulip maintainers labels Oct 18, 2024
Comment on lines +122 to +132
final GlobalStore globalStore;
if (isBackground) {
_backgroundIsolateGlobalStore ??= await ZulipBinding.instance.loadGlobalStore();
globalStore = _backgroundIsolateGlobalStore!;
} else {
NavigatorState navigator = await ZulipApp.navigator;
final context = navigator.context;
assert(context.mounted);
if (!context.mounted) return; // TODO(linter): this is impossible as there's no actual async gap, but the use_build_context_synchronously lint doesn't see that
globalStore = GlobalStoreWidget.of(context);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, it feels like the wrong structure for this NotificationDisplayManager class to be maintaining its own GlobalStore instance (in _backgroundIsolateGlobalStore).

Having this method, and its caller chain, need to know about whether it's running in a background isolate or in the foreground seems messy too.

I've just sent #1005 to solve this a different way. Then this becomes:

Suggested change
final GlobalStore globalStore;
if (isBackground) {
_backgroundIsolateGlobalStore ??= await ZulipBinding.instance.loadGlobalStore();
globalStore = _backgroundIsolateGlobalStore!;
} else {
NavigatorState navigator = await ZulipApp.navigator;
final context = navigator.context;
assert(context.mounted);
if (!context.mounted) return; // TODO(linter): this is impossible as there's no actual async gap, but the use_build_context_synchronously lint doesn't see that
globalStore = GlobalStoreWidget.of(context);
}
final globalStore = await ZulipBinding.instance.getGlobalStore();

required MessageFcmMessage data,
}) async {
final account = globalStore.accounts.firstWhereOrNull((account) =>
account.realmUrl.origin == data.realmUri.origin && account.userId == data.userId);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

notif: Match realmUri using only the origin part of the uri

Can you elaborate on the motivation for this change? What's the situation where it makes a difference, and why is the new behavior better than the old behavior in that situation?

Copy link
Member

@gnprice gnprice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @rajveermalviya for taking care of this, and thanks @chrisbobbe for the previous reviews!

For tonight I've just skimmed this; a couple of comments above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integration review Added by maintainers when PR may be ready for integration
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Replace flutter_local_notifications with a thin API binding using Pigeon
5 participants