feat(messages): feed view preferences — All / My / Following / Followers (#19) - #103
Merged
Merged
Conversation
The feed ignored `viewingPreference` entirely and always asked for the whole feed. It now opens on whatever the account has saved and offers the same four choices as Settings -> View Preferences on the web. `GET /api/messages` takes only `limit`, `offset`, `onlyMine` and `tag` (/help/api/messages) — there is no following/followers parameter, and search is documented as "scoped to your feed visibility (honors your viewingPreference)". So the server scopes the feed from the saved preference: switching PATCHes the account first and only then reloads the feed from the top, with `onlyMine=true` remaining the request-level mechanism for My Messages. The switcher updates optimistically but rolls back and surfaces the error if the PATCH fails, so it can never show a view the account never stored. Switching resets the keyset cursor, so paging restarts under the new view. `viewingPreference` is shared through `:core:model` plus a small `ViewingPreferenceStore` in `:core:network` rather than by depending on `:feature:profile` — no feature module depends on another here. That leaves `:feature:profile`'s `SettingsRepository` and this store as two paths to the same field; they should be consolidated behind one owner. Closes #19
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.
Closes #19. Part of epic #17. P0.
The mechanism is confirmed from the docs, not assumed
The issue asked to "confirm the exact query contract live for the following/followers variants".
Done — and the answer is that there is no such query parameter:
helpapi/messages.txt:GET /api/messagestakeslimit,offset,onlyMine,tag. Nofollowing/followers parameter exists. The same page says a signed-in token personalises the
feed, and for search: "scoped to your feed visibility (honors your
viewingPreference)".That is the documentation stating the server applies the stored preference when scoping the feed.
helpapi/users-and-profile.txt:viewingPreferenceis aPATCH /api/user/updatefield, and theresponse is "the updated user object (same shape as
GET /api/user)".helpapi/following.txt: no feed mechanism at all — follow/unfollow/counts/requests only.So: persist the preference, then reload.
onlyMine=trueremains the per-request mechanism forMy Messages; the other three are left to the server-side preference.
One doc/live discrepancy handled defensively: the help page's
GET /api/userexample shows a baretop-level user object while live returns
{ "user": … }, so the PATCH response DTO tolerates bothand falls back to the requested value when the field is not echoed.
Implementation
FilterChips under the top bar, visible even when the feed is subscription-gated, so auser can switch away from a view they cannot see.
optimistically but rolls back on failure and surfaces the mapped error, with no refresh — the
switcher can never show a view that was never saved. The server's echoed value wins over the
tapped one. The row disables while a save is in flight; re-tapping the current selection is a
no-op.
GET /api/userbefore the first refresh, so the feed's very first request alreadyruns under the saved view rather than flashing All Messages.
from Feed: switch to cursor (keyset) pagination #22's
refresh()and is pinned by a test proving the stale cursor is discarded.Module-dependency decision
No feature→feature dependency was created.
ViewingPreferencewent into:core:model;:core:networkgained a partialPATCH api/user/updateon the existingInterlinedListApiplus asmall
ViewingPreferenceStorethat:feature:messagesconsumes.Flagging explicitly:
:feature:profile'sSettingsRepository(#33) and thisViewingPreferenceStoreare now two independent writers of the same field, each with its ownin-flight state and neither aware of the other. In practice, changing the view in Settings will not
update an already-composed feed switcher until the feed is re-entered. They should be consolidated
behind one owner — most likely a shared account-preferences module — once both surfaces settle.
Filed as a follow-up.
Verification
TDD: tests written first and confirmed red, then implemented to green.
./gradlew :app:assembleDebug testDebugUnitTest(plus acleanrun) → BUILD SUCCESSFUL,842 tests, 0 failures, 0 skipped.
New coverage: 8 in
ViewingPreferenceStoreTest(every wire value both directions, the partial body{"viewingPreference":"followers_only"}, unknown/absent fallback, the server's real 400 message);7 in
MessagesFeedViewPreferenceTest(each preference's exact query, preference + cursor on page 2,read from
GET /api/user, PATCH on save); 8 added toMessagesFeedViewModelTest(initial read,unreadable-preference fallback, PATCH + refresh, cursor restart, rollback on failure, server value
wins, no-op re-tap, refresh keeps selection). 4 Compose tests compile, not executed (no emulator).
Known rough edge
After switching, previously cached rows stay on screen until the refresh lands (with the refresh
indicator showing), so My Messages can briefly show other authors' messages. Clearing the cache
eagerly would fix it but cause a blank flash on every switch — left as-is rather than adding the
complexity.