Repository navigation
feat(notifications): notification status page in Settings - #1874
Merged
Merged
Conversation
bmc08gt
force-pushed
the
feat/notification-status
branch
from
October 28, 2026 20:42
d655512 to
fbd985c
Compare
AuthManager.updateFcmToken and NotificationService.onNewToken dropped the AddToken result, so nothing could say whether push registration worked. Both now go through PushRegistrar, which saves the outcome (ok, invalidPushToken, transport, unknown), source and time per account, and logout clears it. FirebasePushTokenProvider.deleteToken now awaits the task so a following getToken can't return the deleted token.
Channels were created on first post, so a category that never fired had no channel the user could turn off and nothing for the status page to check. FlipcashApp now creates all six channels and both groups at startup; the lazy create stays as a backstop. Adds TestNotificationPoster for the status page's local test: posted on channel_chat after 3 s from its own scope, with a fixed id and a tap target of app.flipcash.com/settings/notifications.
The status page's checks as a pure function: a settings snapshot and the registration result in, ordered rows and a summary out, with no Android types. A blocked channel is a Fail or a Warning by what the user misses; a transport failure is a Warning only if the server last said ok. The report builder prints each check with its raw value and only the last six characters of the token.
The page drew nothing until the device read landed, then snapped the expanded groups into the folded row once registration finished. Rows now have stable keys and a Checking placeholder per row, status changes crossfade in place, rows that come or go and the all-pass fold animate, and the page scrolls under both bars with a progressive blur as Settings does.
Spec Behaviour 7 now puts Check again in the top bar only, with no pull-to-refresh, so the summary-card button and PullToRefreshBox go. CircularIconButton gains an enabled flag so the action can be inert while a run is in progress. The status page Card painted a rounded background without clipping, so the folded row's ripple filled square corners. It now clips before any clickable.
Buttons and group headers are title case; the page no longer uppercases its headers. A sent test shows "Test notification sent" in the floating toast host instead of the green note under the button. Each row reserves two lines of detail, and at a font scale of 1.5 or more the footer buttons scroll with the page instead of staying pinned.
…text At large font scales the actions scroll inside the hazeSource, so the glass would sample its own ancestor.
iOS leads this toast with checkmark.circle.fill in the text colour. Pass the existing ic_check_circle, drawn to match that symbol, through the toast's icon.
Login and refresh called the registrar with no timeout, so a hung AddToken recorded nothing. The 10 s limit is now the registrar's default and covers the token delete, the token fetch and AddToken for every call site. The saved record gains lastOkAt. Only an ok sets it; any other result carries the previous value forward, and logout clears it with the rest of the record. Records written before this change still decode, with no lastOkAt. A timed-out attempt now reports the token it sent instead of none.
…d report - Summary: a finished Fail or Warning wins over a row still checking. The "Checked just now" line is hidden until the first run finishes. - The transport Warning keys off lastRegistrationOkAt from the record read before the attempt, not the last saved result. - Remove the Unknown status and its "The check didn't finish" string. A page closed mid-run saves nothing. - A grant from the in-app Turn On re-reads the phone and registers again. - Registration failures put the failure in the row title: no token, rejected token and "Registration failed". - The test button is also disabled while channel_chat is off, with "Turn on chat notifications to send a test." - Report: the registration line is "<status> (<result>, <source>, <time>)", the result left out when ok, names in camelCase. The token is the one the latest attempt sent, or none.
A timeout during deleteToken() or getToken() returned Transport and saved a transport record, though AddToken was never called. Save only when a token was sent.
…heck Again The folded "N checks passed" row keeps its title; only its mark shows Checking. A row checking again keeps its fix pill, disabled until the result is in. The registration row keeps the Try Again from the page's last run.
…ok time The registration line printed the saved record even when the latest run saved nothing, so a run with no token showed an older login result. It now reads <status> (<reason>) for such a run, e.g. fail (noToken), and checking while the run is in flight. A Last ok line follows it.
bmc08gt
force-pushed
the
feat/notification-status
branch
from
October 29, 2026 10:56
97fd484 to
3fcfcca
Compare
The test button now calls SendTestPush, so a notification that arrives shows Flipcash's servers can reach the phone, not only that it can post. The button loads and disables while the call runs, with a 10 s timeout. OK reads "Send Again" and toasts "Test notification sent"; a transport failure or the timeout toasts "Couldn't reach Flipcash"; anything else toasts "Couldn't send a test notification". The server's test push has an empty payload, so NotificationService posts it on the default channel (system name "Misc.") with the launcher as its tap target. The test button now gates on that channel instead of chat. Removes TestNotificationPoster, its strings, and the /settings/notifications deeplink, which only the poster used.
Check Again turned every row to Checking, so the summary card flickered to "Checking…" for the 0.6 s the run takes. The view model now keeps the summary from the last finished run until the new run finishes, and the card crossfades to the new one. "Checking…" shows only on the first run after the page opens.
…n On The summary getter from d587f39 keeps the last finished summary whenever any check is running, so Try Again and the re-run after Turn On is granted already held it. These tests pin that: neither run shows "Checking…" or an in-between summary before the new result.
The disabled test button now reads "Turn on Misc. notifications in Android settings to send a test." The channel can only be turned on from system settings, and the old copy didn't say so.
A SendTestPush that ends in gRPC CANCELLED now shows "Couldn't reach Flipcash", as the spec asks. CANCELLED is added only to the test-push classification; AddToken registration keeps its old transport codes. Coroutine cancellation still propagates, since foldWithSuppression rethrows it before the error is built. Tests pin the CANCELLED case, a cancelled send showing no result, a failed send after a successful one keeping "Send Again", and a push with no or undecodable payload opening the app without navigating. Also corrects the channel comment for the blocked-channel footer.
…k channel Misc. Passing-row titles and the report's check names are now title case, per the spec. The blocked fallback channel row reads "Misc. notifications are off", the name Android settings show for fcm_fallback_notification_channel.
…nnel
The server's test push has no payload, so it landed on
fcm_fallback_notification_channel, which is IMPORTANCE_DEFAULT and never
pops up as a heads-up. An app can't raise an existing channel's
importance, so the test gets its own channel, channel_test_push ("Test
Notifications", IMPORTANCE_HIGH), created at app start with the others.
The page sets a TestPushMark just before SendTestPush. While it is set,
NotificationService posts the next push with an empty payload on
channel_test_push and clears the mark. The mark also clears when the
send fails, or 30 s after it was set. Every other push is unchanged.
The test button's channel gate now reads channel_test_push. The channel
has no row and is left out of Other Categories; the report lists it as
the seventh channel. The fallback channel's description changes to
"Other updates from Flipcash".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When a user says they aren't getting notifications, there's nothing on the phone that tells them, or us, which part is broken: the permission, a blocked channel, battery optimization, or push registration with Flipcash. This adds a status page at Settings › Advanced › Notifications that runs those checks, offers a fix for each one that fails, asks Flipcash to send a test notification, and shares a plain-text report for support.
Spec: code-payments/flipcash-client-orchestrator#73 (Android and Both items). Figma page 12952:56; S5 is the Android frame.
Checks and registration
features/notification-statusmodule. The status model is a pure function from a device snapshot plus the last registration record to rows and a summary, with no Android types. The device read is the only Android-facing part.PushRegistrarinauthenticationrecords each AddToken attempt per account, with the time of the lastok, and clears the record on logout. Login, token refresh and the status page all go through it. If the page closes mid-attempt, or the timeout fires before a token is fetched, nothing is saved.okis on record, and a Fail otherwise.FirebasePushTokenProvider.deleteToken()now waits for the delete to finish, so Try again can't get the old token back.Page
UserLinkCarduses), the footer buttons scroll with the page instead of staying pinned.PushController.sendTestPush()with a 10 s timeout and shows loading while it's in flight. The server sends "Test Notification" with an empty payload, whichNotificationServiceposts on the general channel (fcm_fallback_notification_channel, shown as "Misc.") with no navigation. The button is disabled while notifications or that channel are off, with a line under it saying which to turn on.<status> (<reason>), e.g.fail (noToken), rather than an older record from login; a run still going readschecking. ALast ok: <time>line (ornever) follows it.TopScrollEdge/BottomScrollEdgeover haze, matching Settings. Group headers useSectionHeaderin title case ("On This Phone", "With Flipcash"), as are the buttons.Theme
warningTextcolour token, named to matchsuccessText/errorText(the spec calls ittextWarning). Flipcash uses the existingFlipcash2ColorSpec.warning(#FFA953); the Code theme usesWarning.Copy not in the spec
apps/flipcash/corestrings.xml.