Skip to content

feat: notification tray limit — setting plus both consumers (#35) - #112

Merged
Adron merged 1 commit into
parity/queuefrom
issue/35-notification-tray-limit
Sep 16, 2026
Merged

Adron merged 1 commit into
parity/queuefrom
issue/35-notification-tray-limit

Conversation

@Adron

@Adron Adron commented Sep 16, 2026

Copy link
Copy Markdown
Member

Closes #35. Part of epic #31.

Placement and range are documented, not invented

The web files Notification tray limit under View preferences, not under a notifications group.
/help/settings lists it there alongside Messages per page, and its own Notifications section
points back: "Open it to see your most recent notifications, up to your Notification tray limit
(see View Preferences above)". So it went into ViewPreferencesGroup, directly under Messages per
page.

Range 10–40, default 20. /help/settings: "The default is 20 and you can set any value from 10
to 40." Corroborated by /help/api/notifications ("default 20, clamped to 10–40") and by the live
GET /api/user value of 20.

Both consumers honour it — this is the part that makes the issue worth doing

  • In-app list: DefaultNotificationsRepository replaces PaginationDto.DEFAULT_LIMIT with the
    account's limit for refresh, loadMore and fetchLatest. The endpoint's own limit accepts
    1–50, which contains 10–40, so the preference is sent verbatim.
  • System tray: SystemNotificationRaiser.post now takes maxIndividual, supplied by
    NotificationPollRunner from the account's limit (cached by then, so no second request). The
    hard-coded SystemNotificationPoster.MAX_INDIVIDUAL = 5 is gone, replaced by a pure
    collapsesToSummary(count, maxIndividual) so the grouping rule is assertable without an Android
    notification manager.

How the value crosses modules

Follows the #19 pattern exactly: a second narrow accessor in :core:network/preferences/ —
NotificationTrayLimitStore, beside ViewingPreferenceStore. It reads notificationTrayLimit off
the shared GET /api/user, clamps to the documented range, caches for the process, and exposes
publish(Int?) so DefaultSettingsRepository forwards the saved value after every read/write —
without that forward, a limit changed in Settings would not take effect until a restart.

This adds a reader to the ownership tangle already tracked as #104, noted in the store's KDoc
and the commit body.

Verification

./gradlew :app:assembleDebug testDebugUnitTest → BUILD SUCCESSFUL, 1102 tests, 0 failures.
Every required behaviour is covered: the PATCH carries only notificationTrayLimit (asserted
both against the real serializer via touchedFieldNames() and against the wire body), out-of-range
refused with no request, the list honours the limit, the tray grouping honours it, optimistic apply
and rollback on failure. 5 Compose tests compile, not executed (no emulator).

Two judgement calls worth a second opinion

  1. DefaultSettingsRepository now depends on NotificationTrayLimitStore — one constructor arg,
    one line in publish. Without it the notifications side caches a stale limit for the process. The
    alternative, never caching, costs an extra GET /api/user per pull-to-refresh and per
    background poll.
  2. Behaviour change in the tray: a batch of six now posts six individual notifications where it
    previously collapsed to one summary. That is the point of the issue, but with a limit of 40 the
    shade can hold considerably more than before. Android caps an app at ~25 active notifications
    anyway, so the practical ceiling is lower than 40.

The bell tray's size was configurable on the web and unreachable on Android,
where two independent constants decided it instead: the notifications list
paged by a hard-coded 20 and the push-poll collapsed anything over five items
into a single tray summary.

Expose the preference and have both consumers respect it:

- Settings gains a "Notification tray limit" number row under View preferences,
  which is where the web files it — /help/settings lists it there alongside
  Messages per page, and that page's Notifications section points back with
  "up to your Notification tray limit (see View Preferences above)". The range
  is the documented one, 10 to 40 with a default of 20 (/help/settings, echoed
  by /help/api/notifications' "clamped to 10-40"), enforced client-side so an
  out-of-range entry never costs a request.
- :feature:notifications sizes both its list pages and the poll's fetch by the
  preference, and the poll passes the same number to the tray raiser as its
  group cap, replacing SystemNotificationPoster's fixed five.

The value reaches :feature:notifications through NotificationTrayLimitStore in
:core:network, following the ViewingPreferenceStore pattern #19 established for
exactly this problem: no feature module here depends on another, and
:feature:profile owns SettingsRepository. The store caches for the process and
DefaultSettingsRepository publishes into it on every read and write, so a limit
changed in Settings takes effect on the next refresh rather than after a
restart. That leaves two narrow accessors in :core:network beside the full
SettingsRepository, which adds a reader to the ownership tangle issue #104
already tracks.

Closes #35
@Adron
Adron merged commit 68ece5e into parity/queue Sep 16, 2026
1 check passed
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