-
Notifications
You must be signed in to change notification settings - Fork 246
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
notif: Use associated account as initial account; if opened from background #1240
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's a quick review :) in particular I haven't yet tested this manually on the office Android device.
lib/widgets/app.dart
Outdated
final 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting. For a moment, seeing the await
, I thought this comment must be wrong. But in fact I see that context
isn't _handleGenerateInitialRoutes
's context
param, it's the final context
that shadows that param. How about giving this one a different name, like navigatorContext
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also nit: the TODO(linter)
comment is too long; let's put it above this line, and it probably needs to be split onto multiple lines too
lib/widgets/app.dart
Outdated
// TODO(#524) choose initial account as last one used | ||
final initialAccountId = globalStore.accounts.firstOrNull?.id; | ||
|
||
return (String intialRoute) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: spelling of "initial"
test/notifications/display_test.dart
Outdated
@@ -1096,6 +1096,44 @@ void main() { | |||
takeStartingRoutes(); | |||
matchesNavigation(check(pushedRoutes).single, account, message); | |||
}); | |||
|
|||
testWidgets('uses associated account as intial account; if intial route', (tester) async { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: spelling of "initial"
test/notifications/display_test.dart
Outdated
narrow: switch (data.recipient) { | ||
FcmMessageChannelRecipient(:var streamId, :var topic) => | ||
TopicNarrow(streamId, topic), | ||
FcmMessageDmRecipient(:var allRecipientIds) => | ||
DmNarrow(allRecipientIds: allRecipientIds, selfUserId: data.userId), | ||
}).buildUrl(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Indentation looks wrong here (code inside switch
should be indented)
FcmMessageDmRecipient(:var allRecipientIds) => | ||
DmNarrow(allRecipientIds: allRecipientIds, selfUserId: data.userId), | ||
}).buildUrl(); | ||
tester.binding.platformDispatcher.defaultRouteNameTestValue = intentDataUrl.toString(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like it needs a corresponding teardown, with clearDefaultRouteNameTestValue
. (Same with the existing place we set this, actually)
1b7b732
to
54adf40
Compare
Thanks for the review @chrisbobbe! Pushed a revision, PTAL. |
There was a problem hiding this 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, and all looks good in a quick manual test on an Android emulator.
Does this PR change behavior on iOS? We haven't implemented navigation on tapping a notification on iOS yet; that's #1147. I haven't tested on iOS because Apple makes it complicated to test client-side notification changes: https://github.com/zulip/zulip-mobile/blob/main/docs/howto/push-notifications.md#testing-client-side-changes-on-ios
@@ -1070,6 +1070,7 @@ void main() { | |||
|
|||
testWidgets('at app launch', (tester) async { | |||
addTearDown(testBinding.reset); | |||
addTearDown(tester.binding.platformDispatcher.clearDefaultRouteNameTestValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be best in its own commit, since it's about an unrelated test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved this and the formating change in this test to a separate commit.
lib/widgets/app.dart
Outdated
|
||
final globalStore = GlobalStoreWidget.of(context); | ||
// TODO(#524) choose initial account as last one used | ||
final initialAccountId = globalStore.accounts.firstOrNull?.id; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about doing this (checking the contents of globalStore.accounts
) inside the returned InitialRouteListFactory
callback? That's what we do in the open-from-notification case.
Then in particular we don't have to think about what happens if the firstOrNull
account is logged out between a call to _ZulipAppState.build
and the time when Flutter decides to call this InitialRouteListFactory
callback.
—ah, I see: its position outside the callback is the same in main
. How about a prep commit that just puts the query on globalStore.accounts
into the callback, then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems also nice if it's below the open-from-notification code in that callback, so it's easier to see that it's not part of that logic.
…ground Previously, when two accounts (Account-1 and Account-2) were logged in, the app always defaulted to showing the home page of Account-1 on launch. If the app was closed and the user opened a notification from Account-2, the navigation stack would be: HomePage(Account-1) -> MessageListPage(Account-2) This commit fixes that behaviour, now when a notification is opened while the app is closed, the home page will correspond to the account associated with the notification's conversation. This addresses zulip#1210 for background notifications.
54adf40
to
ae30cd3
Compare
Thanks for the review @chrisbobbe. Pushed a new revision, PTAL. |
There was a problem hiding this 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.
@@ -152,6 +152,21 @@ class _ZulipAppState extends State<ZulipApp> with WidgetsBindingObserver { | |||
return super.didPushRouteInformation(routeInformation); | |||
} | |||
|
|||
InitialRouteListFactory _handleGenerateInitialRoutes(BuildContext context) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
app [nfc]: Pull out _handleGenerateInitialRoutes
This commit message is misleading 🙂; the change doesn't follow the common pattern of just moving some code out to a helper function for better organization. Putting the globalStore.accounts
query inside the callback, instead of outside, is significant and worth mentioning; in fact it might not be NFC. The reason I gave in #1240 (comment) was:
Then in particular we don't have to think about what happens if the
firstOrNull
account is logged out between a call to_ZulipAppState.build
and the time when Flutter decides to call thisInitialRouteListFactory
callback.
Does that seem right, or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be even clearer if it were split into two commits: one that changes when globalStore.accounts
is queried, and one for making the helper function (the pure refactor).
final payload = NotificationOpenPayload.parseUrl(url); | ||
|
||
final account = globalStore.accounts.firstWhereOrNull((account) => | ||
account.realmUrl == payload.realmUrl && account.userId == payload.userId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How likely do we think it is that these realm URLs could differ in boring ways that shouldn't matter? Like https://chat.zulip.org/
vs. ``https://chat.zulip.org`. Do we need to just compare .origin
instead, like we do for most (all?) other realm-URL checks?
Previously, when two accounts (Account-1 and Account-2) were logged in, the app always defaulted to showing the home page of Account-1 on launch. If the app was closed and the user opened a notification from Account-2, the navigation stack would be:
HomePage(Account-1) -> MessageListPage(Account-2)
This commit fixes that behaviour, now when a notification is opened while the app is closed, the home page will correspond to the account associated with the notification's conversation.
This addresses #1210 for background notifications.