Skip to content

Remember flows #4533

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 4, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ class ConfigureRoomPresenter @Inject constructor(
val cameraPermissionState = cameraPermissionPresenter.present()
val createRoomConfig by dataStore.createRoomConfigWithInvites.collectAsState(CreateRoomConfig())
val homeserverName = remember { matrixClient.userIdServerName() }
val isKnockFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock).collectAsState(initial = false)
val isKnockFeatureEnabled by remember {
featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock)
}.collectAsState(initial = false)
val roomAddressValidity = remember {
mutableStateOf<RoomAddressValidity>(RoomAddressValidity.Unknown)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ class CreateRoomRootPresenter @Inject constructor(
val localCoroutineScope = rememberCoroutineScope()
val startDmActionState: MutableState<AsyncAction<RoomId>> = remember { mutableStateOf(AsyncAction.Uninitialized) }

val isRoomDirectorySearchEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomDirectorySearch).collectAsState(initial = false)
val isRoomDirectorySearchEnabled by remember {
featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomDirectorySearch)
}.collectAsState(initial = false)

fun handleEvents(event: CreateRoomRootEvents) {
when (event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ class JoinRoomPresenter @AssistedInject constructor(
override fun present(): JoinRoomState {
val coroutineScope = rememberCoroutineScope()
var retryCount by remember { mutableIntStateOf(0) }
val roomInfo by matrixClient.getRoomInfoFlow(roomId.toRoomIdOrAlias()).collectAsState(initial = Optional.empty())
val roomInfo by remember {
matrixClient.getRoomInfoFlow(roomId.toRoomIdOrAlias())
}.collectAsState(initial = Optional.empty())
val joinAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
val knockAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
val cancelKnockAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ class DefaultBiometricAuthenticatorManager @Inject constructor(

@Composable
override fun rememberUnlockBiometricAuthenticator(): BiometricAuthenticator {
val isBiometricAllowed by lockScreenStore.isBiometricUnlockAllowed().collectAsState(initial = false)
val isBiometricAllowed by remember {
lockScreenStore.isBiometricUnlockAllowed()
}.collectAsState(initial = false)
val lifecycleState by LocalLifecycleOwner.current.lifecycle.currentStateFlow.collectAsState()
val isAvailable by remember(lifecycleState) {
derivedStateOf { isBiometricAllowed && hasAvailableAuthenticator }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ class LockScreenSettingsPresenter @Inject constructor(
value = !lockScreenConfig.isPinMandatory && hasPinCode
}
}
val isBiometricEnabled by lockScreenStore.isBiometricUnlockAllowed().collectAsState(initial = false)
val isBiometricEnabled by remember {
lockScreenStore.isBiometricUnlockAllowed()
}.collectAsState(initial = false)
var showRemovePinConfirmation by remember {
mutableStateOf(false)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ class DefaultActionListPresenter @AssistedInject constructor(
mutableStateOf(ActionListState.Target.None)
}

val isDeveloperModeEnabled by appPreferencesStore.isDeveloperModeEnabledFlow().collectAsState(initial = false)
val isDeveloperModeEnabled by remember {
appPreferencesStore.isDeveloperModeEnabledFlow()
}.collectAsState(initial = false)
val isPinnedEventsEnabled = isPinnedMessagesFeatureEnabled()
val pinnedEventIds by remember {
room.roomInfoFlow.map { it.pinnedEventIds }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,12 @@ class AttachmentsPreviewPresenter @AssistedInject constructor(

val ongoingSendAttachmentJob = remember { mutableStateOf<Job?>(null) }

val allowCaption by featureFlagService.isFeatureEnabledFlow(FeatureFlags.MediaCaptionCreation).collectAsState(initial = false)
val showCaptionCompatibilityWarning by featureFlagService.isFeatureEnabledFlow(FeatureFlags.MediaCaptionWarning).collectAsState(initial = false)
val allowCaption by remember {
featureFlagService.isFeatureEnabledFlow(FeatureFlags.MediaCaptionCreation)
}.collectAsState(initial = false)
val showCaptionCompatibilityWarning by remember {
featureFlagService.isFeatureEnabledFlow(FeatureFlags.MediaCaptionWarning)
}.collectAsState(initial = false)

var useSendQueue by remember { mutableStateOf(false) }
var preprocessMediaJob by remember { mutableStateOf<Job?>(null) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,9 @@ class MessageComposerPresenter @AssistedInject constructor(
}
var showAttachmentSourcePicker: Boolean by remember { mutableStateOf(false) }

val sendTypingNotifications by sessionPreferencesStore.isSendTypingNotificationsEnabled().collectAsState(initial = true)
val sendTypingNotifications by remember {
sessionPreferencesStore.isSendTypingNotificationsEnabled()
}.collectAsState(initial = true)

LaunchedEffect(cameraPermissionState.permissionGranted) {
if (cameraPermissionState.permissionGranted) {
Expand Down Expand Up @@ -397,16 +399,16 @@ class MessageComposerPresenter @AssistedInject constructor(
.stateIn(this, SharingStarted.Lazily, emptyList())

combine(mentionTriggerFlow, room.membersStateFlow, roomAliasSuggestionsFlow) { suggestion, roomMembersState, roomAliasSuggestions ->
val result = suggestionsProcessor.process(
suggestion = suggestion,
roomMembersState = roomMembersState,
roomAliasSuggestions = roomAliasSuggestions,
currentUserId = currentUserId,
canSendRoomMention = ::canSendRoomMention,
)
suggestions.clear()
suggestions.addAll(result)
}
val result = suggestionsProcessor.process(
suggestion = suggestion,
roomMembersState = roomMembersState,
roomAliasSuggestions = roomAliasSuggestions,
currentUserId = currentUserId,
canSendRoomMention = ::canSendRoomMention,
)
suggestions.clear()
suggestions.addAll(result)
}
.collect()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,15 @@ class TimelinePresenter @AssistedInject constructor(
val messageShield: MutableState<MessageShield?> = remember { mutableStateOf(null) }

val resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailurePresenter.present()
val isSendPublicReadReceiptsEnabled by sessionPreferencesStore.isSendPublicReadReceiptsEnabled().collectAsState(initial = true)
val renderReadReceipts by sessionPreferencesStore.isRenderReadReceiptsEnabled().collectAsState(initial = true)
val isLive by timelineController.isLive().collectAsState(initial = true)
val isSendPublicReadReceiptsEnabled by remember {
sessionPreferencesStore.isSendPublicReadReceiptsEnabled()
}.collectAsState(initial = true)
val renderReadReceipts by remember {
sessionPreferencesStore.isRenderReadReceiptsEnabled()
}.collectAsState(initial = true)
val isLive by remember {
timelineController.isLive()
}.collectAsState(initial = true)

fun handleEvents(event: TimelineEvents) {
when (event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ class TimelineProtectionPresenter @Inject constructor(
) : Presenter<TimelineProtectionState> {
@Composable
override fun present(): TimelineProtectionState {
val hideMediaContent by appPreferencesStore.doesHideImagesAndVideosFlow().collectAsState(initial = false)
val hideMediaContent by remember {
appPreferencesStore.doesHideImagesAndVideosFlow()
}.collectAsState(initial = false)
var allowedEvents by remember { mutableStateOf<Set<EventId>>(setOf()) }
val protectionState by remember(hideMediaContent) {
derivedStateOf {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ class TypingNotificationPresenter @Inject constructor(
) : Presenter<TypingNotificationState> {
@Composable
override fun present(): TypingNotificationState {
val renderTypingNotifications by sessionPreferencesStore.isRenderTypingNotificationsEnabled().collectAsState(initial = true)
val renderTypingNotifications by remember {
sessionPreferencesStore.isRenderTypingNotificationsEnabled()
}.collectAsState(initial = true)
val typingMembersState by produceState(initialValue = persistentListOf(), key1 = renderTypingNotifications) {
if (renderTypingNotifications) {
observeRoomTypingMembers()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ class MigrationPresenter @Inject constructor(

@Composable
override fun present(): MigrationState {
val migrationStoreVersion by migrationStore.applicationMigrationVersion().collectAsState(initial = null)
val migrationStoreVersion by remember {
migrationStore.applicationMigrationVersion()
}.collectAsState(initial = null)
var migrationAction: AsyncData<Unit> by remember { mutableStateOf(AsyncData.Uninitialized) }

// Uncomment this block to run the migration everytime
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,18 @@ class AdvancedSettingsPresenter @Inject constructor(
@Composable
override fun present(): AdvancedSettingsState {
val localCoroutineScope = rememberCoroutineScope()
val isDeveloperModeEnabled by appPreferencesStore
.isDeveloperModeEnabledFlow()
.collectAsState(initial = false)
val isSharePresenceEnabled by sessionPreferencesStore
.isSharePresenceEnabled()
.collectAsState(initial = true)
val doesCompressMedia by sessionPreferencesStore
.doesCompressMedia()
.collectAsState(initial = true)
val isDeveloperModeEnabled by remember {
appPreferencesStore.isDeveloperModeEnabledFlow()
}.collectAsState(initial = false)
val isSharePresenceEnabled by remember {
sessionPreferencesStore.isSharePresenceEnabled()
}.collectAsState(initial = true)
val doesCompressMedia by remember {
sessionPreferencesStore.doesCompressMedia()
}.collectAsState(initial = true)
val theme by remember {
appPreferencesStore.getThemeFlow().mapToTheme()
}
.collectAsState(initial = Theme.System)
}.collectAsState(initial = Theme.System)
var showChangeThemeDialog by remember { mutableStateOf(false) }

fun handleEvents(event: AdvancedSettingsEvents) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,17 @@ class BlockedUsersPresenter @Inject constructor(
mutableStateOf(AsyncAction.Uninitialized)
}

val renderBlockedUsersDetail = featureFlagService
.isFeatureEnabledFlow(FeatureFlags.ShowBlockedUsersDetails)
.collectAsState(initial = false)
val renderBlockedUsersDetail by remember {
featureFlagService.isFeatureEnabledFlow(FeatureFlags.ShowBlockedUsersDetails)
}.collectAsState(initial = false)
val ignoredUserIds by matrixClient.ignoredUsersFlow.collectAsState()
val ignoredMatrixUser by produceState(
initialValue = ignoredUserIds.map { MatrixUser(userId = it) },
key1 = renderBlockedUsersDetail.value,
key1 = renderBlockedUsersDetail,
key2 = ignoredUserIds
) {
value = ignoredUserIds.map {
if (renderBlockedUsersDetail.value) {
if (renderBlockedUsersDetail) {
matrixClient.getProfile(it).getOrNull()
} else {
null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,14 @@ class DeveloperSettingsPresenter @Inject constructor(
val clearCacheAction = remember {
mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized)
}
val customElementCallBaseUrl by appPreferencesStore
.getCustomElementCallBaseUrlFlow()
.collectAsState(initial = null)
val hideImagesAndVideos by appPreferencesStore
.doesHideImagesAndVideosFlow()
.collectAsState(initial = false)
val customElementCallBaseUrl by remember {
appPreferencesStore
.getCustomElementCallBaseUrlFlow()
}.collectAsState(initial = null)
val hideImagesAndVideos by remember {
appPreferencesStore
.doesHideImagesAndVideosFlow()
}.collectAsState(initial = false)

val tracingLogLevelFlow = remember {
appPreferencesStore.getTracingLogLevelFlow().map { AsyncData.Success(it.toLogLevelItem()) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ class NotificationSettingsPresenter @Inject constructor(
val changeNotificationSettingAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }

val localCoroutineScope = rememberCoroutineScope()
val appNotificationsEnabled = userPushStore
.getNotificationEnabledForDevice()
.collectAsState(initial = false)
val appNotificationsEnabled by remember {
userPushStore.getNotificationEnabledForDevice()
}.collectAsState(initial = false)

val matrixSettings: MutableState<NotificationSettingsState.MatrixSettings> = remember {
mutableStateOf(NotificationSettingsState.MatrixSettings.Uninitialized)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ class BugReportPresenter @Inject constructor(
screenshotHolder.getFileUri()
)
}
val crashInfo: String by crashDataStore
.crashInfo()
.collectAsState(initial = "")
val crashInfo: String by remember {
crashDataStore.crashInfo()
}.collectAsState(initial = "")

val sendingProgress = remember {
mutableFloatStateOf(0f)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package io.element.android.features.rageshake.impl.preferences
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
Expand Down Expand Up @@ -39,13 +40,13 @@ class DefaultRageshakePreferencesPresenter @Inject constructor(
mutableStateOf(rageshake.isAvailable())
}
val isFeatureAvailable = remember { rageshakeFeatureAvailability.isAvailable() }
val isEnabled = rageshakeDataStore
.isEnabled()
.collectAsState(initial = false)
val isEnabled by remember {
rageshakeDataStore.isEnabled()
}.collectAsState(initial = false)

val sensitivity = rageshakeDataStore
.sensitivity()
.collectAsState(initial = 0f)
val sensitivity by remember {
rageshakeDataStore.sensitivity()
}.collectAsState(initial = 0f)

fun handleEvents(event: RageshakePreferencesEvents) {
when (event) {
Expand All @@ -56,9 +57,9 @@ class DefaultRageshakePreferencesPresenter @Inject constructor(

return RageshakePreferencesState(
isFeatureEnabled = isFeatureAvailable,
isEnabled = isEnabled.value,
isEnabled = isEnabled,
isSupported = isSupported.value,
sensitivity = sensitivity.value,
sensitivity = sensitivity,
eventSink = ::handleEvents
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ class RoomDetailsPresenter @Inject constructor(
}

val canHandleKnockRequests by room.canHandleKnockRequestsAsState(syncUpdateFlow.value)
val isKnockRequestsEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock).collectAsState(false)
val isKnockRequestsEnabled by remember {
featureFlagService.isFeatureEnabledFlow(FeatureFlags.Knock)
}.collectAsState(false)
val knockRequestsCount by produceState<Int?>(null) {
room.knockRequestsFlow.collect { value = it.size }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ class SignedOutPresenter @AssistedInject constructor(

@Composable
override fun present(): SignedOutState {
val sessions by sessionStore.sessionsFlow().collectAsState(initial = emptyList())
val sessions by remember {
sessionStore.sessionsFlow()
}.collectAsState(initial = emptyList())
val signedOutSession by remember {
derivedStateOf { sessions.firstOrNull { it.userId == sessionId } }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import com.google.accompanist.permissions.ExperimentalPermissionsApi
Expand Down Expand Up @@ -56,13 +57,13 @@ class DefaultPermissionsPresenter @AssistedInject constructor(

// To reset the store: ResetStore()

val isAlreadyDenied: Boolean by permissionsStore
.isPermissionDenied(permission)
.collectAsState(initial = false)
val isAlreadyDenied: Boolean by remember {
permissionsStore.isPermissionDenied(permission)
}.collectAsState(initial = false)

val isAlreadyAsked: Boolean by permissionsStore
.isPermissionAsked(permission)
.collectAsState(initial = false)
val isAlreadyAsked: Boolean by remember {
permissionsStore.isPermissionAsked(permission)
}.collectAsState(initial = false)

var permissionState: PermissionState? = null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ class KonsistFlowTest {
val regex = "(.*)\\)(\n\\s*)*\\.collectAsState".toRegex()

val allowedMethods = listOf(
"isOnline()",
"syncService.isOnline()",
"userListDataStore.selectedUsers()",
"accountProviderDataSource.flow()",
"syncService.isOnline()",
"timeline.paginationStatus",
"analyticsService.getUserConsent()",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe using an annotation to suppress the warning would be better, but I don't know if that's possible/easy. Just something we could keep in mind for future usages of Konsist.

)
Konsist
.scopeFromProject()
Expand Down
Loading