Skip to content

feat(notifications): fronting notification options, and stop home waiting on a slow call - #76

Merged
SiteRelEnby merged 2 commits into
mainfrom
feat/fronting-notification-options
Sep 16, 2026
Merged

SiteRelEnby merged 2 commits into
mainfrom
feat/fronting-notification-options

Conversation

@SiteRelEnby

Copy link
Copy Markdown
Collaborator

Two commits, each standing alone.

perf(home): paint who is fronting without waiting on the slowest call

The home refresh fanned out nine calls in parallel and then awaited every one before touching state, so the screen was as slow as its slowest call. /members/top-fronters is occasionally that call - 2.5s seen in the wild, and it gets worse with member count and history depth - and it feeds the quick-switch carousel's ordering and nothing else.

Everything it delayed was on the visible path: the fronting cards at cold start, the post-switch refresh leaving a new front unconfirmed, and the pull-to-refresh spinner running until the last background call returned. Home reloads on resume, so it was paid on every navigation back.

Now the three calls the screen is made of - fronts, members, system - are awaited and painted, the spinner settles there, and the rest folds in behind on its own. A secondary failure leaves the previous value rather than blanking anything. The carousel already fell back to plain member order without its ranking, which is what made this a poor thing to block on.

The watch had the same shape sequentially, with the ranking fetch sitting between the data load and the tile refresh; it now runs after.

Measured with a 3s delay injected on that one endpoint: before, the spinner was still turning 1.2s after returning to Home; after, the screen was settled and current.

feat(notifications): settings of its own

One switch becomes a screen - on/off, icon, names-behind-an-expand, and bring-it-back-if-dismissed. Every default is what the notification already did, so an upgrade changes nobody's shade. The parent row is now a plain link reading On or Off, rather than a row that was both a switch and a way in, which hid four settings behind a control that looked like it had already done its job.

Names behind an expand. The collapsed line can read "Tap to expand", with the names in the expanded view. A public version carries the same wording to the lock screen so the system's generic placeholder does not replace it with something louder.

Bringing it back. Android 14 made ongoing notifications dismissable with no way to opt out, so setOngoing no longer means what its name says. A foreground service would not restore it either - also dismissable - and would cost two permissions on a four-line manifest. So a dismissal schedules a re-post five minutes later. Instant would be an app fighting its user; five minutes still lets a swipe clear the shade now. The worker re-checks both settings and the permission before posting and reads fronters from cache, so being offline cannot turn a re-post into a failed request.

The icon. ic_notification_sheaf.xml is the mark reduced to what survives 24dp, derived from AppIcon-Tinted.svg - gradients, glow copies, shine overlays and the container all removed, since Android tints a small icon from its alpha channel alone. Five stalks, not three: a three-stalk reduction is legible but reads as a letter H and stops being the mark.

Two things worth knowing, both found on device

  • Stock Android hides silent notifications from the status bar (hide_silent_status_icons, default on); Samsung One UI does not. So the icon choice does what you expect on a Galaxy and nothing on a stock Pixel. The setting says so rather than promising otherwise.
  • The shade always draws the app's launcher icon, not the small icon. No icon setting can make the shade entry discreet; only the wording is ours, which the screen now states. A discreet shade entry would need a disguised launcher icon and label - a different feature.

A "show in the status bar" option would work (IMPORTANCE_DEFAULT, quiet with a null sound) but needs a second channel, since channel importance cannot be changed after creation - two permanent entries in system notification settings for everyone. Deliberately not done; the reasoning and the recipe are written down in case that changes.

Checked

  • The settings screen in both states, and the notification in the shade, on API 36.
  • Unit tests cover the notification wording, including that the discreet line names nobody and does not even say the word "fronting".

The home refresh fanned out nine calls in parallel and then awaited every one
of them before touching state, so the screen was as slow as its slowest call.
/members/top-fronters is occasionally that call - 2.5s has been seen in the
wild, and it gets slower with member count and history depth - and it feeds
the quick-switch carousel's ordering and nothing else.

Consequences were all on the visible path: the fronting cards waited on it at
cold start, a post-switch refresh left the new front unconfirmed for the
duration, and the pull-to-refresh spinner ran until the last background call
returned. Home reloads on every resume, so this was paid on each navigation
back to it.

Now the three calls the screen is actually made of - fronts, members, system -
are awaited and painted, the spinner settles there, and everything else folds
in behind on its own. A failure in the secondary set leaves the previous value
rather than blanking anything. The carousel already fell back to plain member
order while its ranking was missing, which is what made this call a poor
choice of thing to block on in the first place.

The watch had the same shape sequentially: the ranking fetch sat between the
data load and cacheTileData / requestTileUpdate, so every slow second was a
second of stale tile on the wrist. It now runs after the tile refresh.

Measured on a device with a 3s delay injected on that one endpoint: before,
the refresh spinner was still turning 1.2s after returning to Home; after, the
screen was already settled and current.
One switch becomes a screen: the on/off control, which icon it uses, whether
Every default is what the notification did before any of it was configurable,
so an upgrade changes nobody's shade.

The parent row is now a plain link reading On or Off. It used to be a row that
was both a switch and a way in, which hid four settings behind a tap on a
control that looked like it had already done its job.

**Names behind an expand.** The collapsed notification can say only "Tap to
expand", with who is fronting in the expanded view. A public version carries
the same wording to the lock screen, so the system's own "contents hidden"
placeholder does not replace it with something louder.

**Bringing it back.** Android 14 made ongoing notifications dismissable and
left no API to opt out, so setOngoing is no longer the promise its name makes.
A foreground service would not restore it either - those are dismissable too -
and would cost two permissions on a manifest that is deliberately four lines
long. Instead a dismissal schedules a re-post five minutes later: instant
working as a way to clear the shade now. The worker re-reads both settings and
the permission before posting, and reads fronters from the cache so being
offline cannot turn a re-post into a failed request.

**The icon.** ic_notification_sheaf.xml is the Sheaf mark reduced to what
survives a 24dp status-bar icon, derived from AppIcon-Tinted.svg: the
gradients, blurred glow copies, shine overlays and rounded-square container
all had to go, since Android tints a small icon from its alpha channel alone.
Five stalks rather than three - a three-stalk reduction is legible but reads
as a letter H and stops being the mark.

Two things the screen now says out loud, because both were surprises when
checked on real devices. Stock Android hides silent notifications from the
status bar entirely while Samsung does not, so the icon choice may do nothing
on a given phone. And the notification itself always draws the app's launcher
icon, which no setting here can change - only the wording is ours.
@SiteRelEnby
SiteRelEnby merged commit bf633e8 into main Sep 16, 2026
1 check passed
@SiteRelEnby
SiteRelEnby deleted the feat/fronting-notification-options branch September 16, 2026 18:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant