Repository navigation
Conversation
Load, Unsilence and Unban become Events handled in one eventFlow collector, so a second tap on a row still sees the first one's pending entry. Every state change now goes through updateStateForEvent; the row-lifting rules move from lambdas passed to run() into the Unsilenced and Unbanned reducer branches. The screen dispatches the events instead of calling load, unsilence and unban, and reads stateFlow instead of state.
Submit becomes an Event; Sending, Sent and SendFailed carry the button state through updateStateForEvent. Sending is dispatched before the send launches, so a second Submit still sees a non-idle button and is dropped, as before. confirmed stays a buffered Channel: it fires from a bottom bar onDismiss that can outlive the collecting composition, and eventFlow has no buffer.
loadedFor was the last private var on the view model. It is now State.loadedFor, set by LoadStarted(chatId) and cleared by LoadFailed, so the repeat-open guard reads stateFlow and the reducer owns every change to it.
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.
Moves
RestrictedMembersViewModelandReportViewModelontoBaseViewModel<State, Event>, so both screens have one State, one sealed Event type and a reducer (updateStateForEventin the companion). This is the first area of the roll-in. The audit below covers every Android view model that doesn't follow that contract yet.What changed
RestrictedMembersViewModel:Load,UnsilenceandUnbanare Events, handled in oneeventFlowcollector so a second tap on a row still sees the first one'spendingentry. The row-lifting rules that were lambdas passed torun()are now theUnsilencedandUnbannedreducer branches. The repeat-open guardloadedForis nowState.loadedFor, so neither view model keeps a mutable field outside State.ReportViewModel: State is the existingLoadingSuccessState.Submitis an Event;Sending,SentandSendFailedmove the button.Sendingis dispatched before the send launches, so a second press is still dropped.confirmedstays a bufferedChannel: it fires from a bottom baronDismissthat can outlive the composition, andeventFlowhas no buffer.DispatcherProviderand passDefaulttoBaseViewModel, so tests run the event collectors on the test dispatcher.stateFlow. Existing VM tests now readstateFlow; new reducer tests:RestrictedMembersStateTest,ReportStateTest.Audit
Rule for every migration: no mutable fields outside State. Guards, cursors and once-only flags (
loadedFor,prefilled,seededEntry,started) go into State too; what stays outside is limited to collaborators, Compose-owned holders likeTextFieldState,PagingData, and one-shot effect channels.Verdicts: migrate fits State + sealed Event + reducer without behaviour change; partial folds the extra flows into State but leaves something out; leave has a reason. Paths are under
apps/flipcash/. "common" means the State types have no Android imports and could move tocommonMain.Plain
ViewModel(): messenger (features/messenger/.../internal/)_state+loadedFor_state: LoadingSuccessState+confirmedchannel_state, effects channel,chatIdvar_state(link), effects channel,chatId/specific/jobvarshandOverCard(): Booleanstays a function (common onceInviteLinkStatemoves)_state, effects channel,pending: Job_state,invitedchannel_state, effects channel,secret/token/startedvarssecret/tokengo into State with a redactingtoString, since State is logged_state(incl. paging cursor), effects,amountDelegate, derivedstateInsback(): Booleanstays a function (State common)_state,mintMSF,_bill/_done/effectschannels,amountDelegatemint(keysmaxAmount) stay (common)_state,_nowticker, derivedrequest/unavailable/members,payFlowpayFlowstate belongs toRequestPayFlow_now,_expanded,_deck,cycled,chatIdMSFs;held/missingcache passthroughs; settle-hold varsrequestscache and settle-hold; first-frame deck publish must be re-checked_restrictions,_rosterFailedMSFs,rosterscache passthroughrostersand the suspend roster calls; shared by five screens_chats,_selected,_done,_limitHitsMSFs; twoTextFieldState;images: List<Uri>TextFieldState/Uristay out; needs a VM test firstcanInvitepassthrough + suspendapproveOnRequestPayFlowRequestPayFlowowns the statesilence()amountDelegate+ one nullable_splitPlain
ViewModel(): other modulesuiFlow+_navigationEventsSharedFlow_state+loadedguardmutableStateOfcard; AssistedInjectuiFlowwith twoandroid.graphics.BitmapsuiFlow)Resultactions stay functionsTextFieldStatequery,_chip, derivedrecents/results, private cachesState(chip, recents, results);querystays outside_requireBiometrics, derivedcanSwitchAccounts, callback-based login handlingremoveinitisStaff, rawbetaOverrideflowPagingDatapassthrough + suspend route lookupSavedStateHandleholderBaseViewModelsubclasses with state outside the reducerrefactor/chat-vm-scopes; not touched hereentryChanged,styleisLastStepandentryChangedinto State,stylederived fromstateFlowcanSave, a constant style flowcanSaveandseededEntryinto Statefetchedmetadata cacheThe four
Hilt*ViewModelwrappers over commonMain view models already conform.No open PR or pushed branch changes any file in this PR. The messenger branches that touched nearby files (
feat/chat-media-save-stack-edit,fix/request-pay-no-balance,feat/chat-send-back,feat/standard-cash-bubbles,perf/parallel-async,feat/group-send-per-person) have all merged.