From 7dbf3ed1f9cdbafabfb49e9f7065e86fe4e1aefb Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Thu, 29 Jan 2026 14:22:47 +0100 Subject: [PATCH 1/5] refactor: lazy calculate some kotlin config values --- .../com/wire/android/di/CoreLogicModule.kt | 10 ++++++++ .../wire/android/di/KaliumConfigsModule.kt | 25 ++++++++----------- .../create/code/CreateAccountCodeViewModel.kt | 5 +++- .../login/email/LoginEmailViewModel.kt | 3 +++ .../login/sso/LoginSSOViewModel.kt | 6 +++-- .../login/sso/LoginSSOViewModelExtension.kt | 2 ++ .../login/NewLoginViewModel.kt | 4 ++- .../CreateAccountVerificationCodeViewModel.kt | 5 +++- kalium | 2 +- 9 files changed, 42 insertions(+), 20 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt b/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt index 2448911d099..c2b8c16b74e 100644 --- a/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt +++ b/app/src/main/kotlin/com/wire/android/di/CoreLogicModule.kt @@ -23,6 +23,7 @@ import androidx.work.WorkManager import com.wire.android.datastore.UserDataStoreProvider import com.wire.android.util.ImageUtil import com.wire.android.util.UserAgentProvider +import com.wire.android.util.isWebsocketEnabledByDefault import com.wire.kalium.logic.CoreLogic import com.wire.kalium.logic.data.asset.KaliumFileSystem import com.wire.kalium.logic.data.id.FederatedIdMapper @@ -81,6 +82,10 @@ annotation class CurrentAccount @Retention(AnnotationRetention.BINARY) annotation class NoSession +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class DefaultWebSocketEnabledByDefault + @Module @InstallIn(SingletonComponent::class) class CoreLogicModule { @@ -144,6 +149,11 @@ class CoreLogicModule { @Provides fun provideAudioNormalizedLoudnessBuilder(@KaliumCoreLogic coreLogic: CoreLogic): AudioNormalizedLoudnessBuilder = coreLogic.audioNormalizedLoudnessBuilder + + @DefaultWebSocketEnabledByDefault + @Provides + fun provideDefaultWebSocketEnabledByDefault(@ApplicationContext context: Context): Boolean = + isWebsocketEnabledByDefault(context) } @Module diff --git a/app/src/main/kotlin/com/wire/android/di/KaliumConfigsModule.kt b/app/src/main/kotlin/com/wire/android/di/KaliumConfigsModule.kt index fd15acb73f3..a2673431d78 100644 --- a/app/src/main/kotlin/com/wire/android/di/KaliumConfigsModule.kt +++ b/app/src/main/kotlin/com/wire/android/di/KaliumConfigsModule.kt @@ -18,10 +18,8 @@ package com.wire.android.di -import android.content.Context import android.os.Build import com.wire.android.BuildConfig -import com.wire.android.util.isWebsocketEnabledByDefault import com.wire.kalium.logic.featureFlags.BuildFileRestrictionState import com.wire.kalium.logic.featureFlags.KaliumConfigs import dagger.Module @@ -34,20 +32,20 @@ import dagger.hilt.components.SingletonComponent class KaliumConfigsModule { @Provides - fun provideKaliumConfigs(context: Context): KaliumConfigs { - val fileRestriction: BuildFileRestrictionState = if (BuildConfig.FILE_RESTRICTION_ENABLED) { - BuildConfig.FILE_RESTRICTION_LIST.split(",").map { it.trim() }.let { - BuildFileRestrictionState.AllowSome(it) - } - } else { - BuildFileRestrictionState.NoRestriction - } - + fun provideKaliumConfigs(): KaliumConfigs { return KaliumConfigs( - fileRestrictionState = fileRestriction, + fileRestrictionState = { + if (BuildConfig.FILE_RESTRICTION_ENABLED) { + BuildConfig.FILE_RESTRICTION_LIST.split(",").map { it.trim() }.let { + BuildFileRestrictionState.AllowSome(it) + } + } else { + BuildFileRestrictionState.NoRestriction + } + }, forceConstantBitrateCalls = BuildConfig.FORCE_CONSTANT_BITRATE_CALLS, // we use upsert, available from SQL3.24, which is supported from Android API30, so for older APIs we have to use SQLCipher - shouldEncryptData = !BuildConfig.DEBUG || Build.VERSION.SDK_INT < Build.VERSION_CODES.R, + shouldEncryptData = { !BuildConfig.DEBUG || Build.VERSION.SDK_INT < Build.VERSION_CODES.R }, lowerKeyPackageLimits = BuildConfig.LOWER_KEYPACKAGE_LIMIT, developmentApiEnabled = BuildConfig.DEVELOPMENT_API_ENABLED, ignoreSSLCertificatesForUnboundCalls = BuildConfig.IGNORE_SSL_CERTIFICATES, @@ -57,7 +55,6 @@ class KaliumConfigsModule { wipeOnCookieInvalid = BuildConfig.WIPE_ON_COOKIE_INVALID, wipeOnDeviceRemoval = BuildConfig.WIPE_ON_DEVICE_REMOVAL, wipeOnRootedDevice = BuildConfig.WIPE_ON_ROOTED_DEVICE, - isWebSocketEnabledByDefault = isWebsocketEnabledByDefault(context), certPinningConfig = BuildConfig.CERTIFICATE_PINNING_CONFIG, maxRemoteSearchResultCount = BuildConfig.MAX_REMOTE_SEARCH_RESULT_COUNT, limitTeamMembersFetchDuringSlowSync = BuildConfig.LIMIT_TEAM_MEMBERS_FETCH_DURING_SLOW_SYNC, diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/create/code/CreateAccountCodeViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/create/code/CreateAccountCodeViewModel.kt index caf0e7fba37..4cc4d64769d 100644 --- a/app/src/main/kotlin/com/wire/android/ui/authentication/create/code/CreateAccountCodeViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/authentication/create/code/CreateAccountCodeViewModel.kt @@ -27,6 +27,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.wire.android.BuildConfig import com.wire.android.di.ClientScopeProvider +import com.wire.android.di.DefaultWebSocketEnabledByDefault import com.wire.android.di.KaliumCoreLogic import com.wire.android.ui.authentication.create.common.CreateAccountFlowType import com.wire.android.ui.authentication.create.common.CreateAccountNavArgs @@ -58,7 +59,8 @@ class CreateAccountCodeViewModel @Inject constructor( @KaliumCoreLogic private val coreLogic: CoreLogic, private val addAuthenticatedUser: AddAuthenticatedUserUseCase, private val clientScopeProviderFactory: ClientScopeProvider.Factory, - defaultServerConfig: ServerConfig.Links + defaultServerConfig: ServerConfig.Links, + @DefaultWebSocketEnabledByDefault private val defaultWebSocketEnabledByDefault: Boolean ) : ViewModel() { val createAccountNavArgs: CreateAccountNavArgs = savedStateHandle.navArgs() @@ -184,6 +186,7 @@ class CreateAccountCodeViewModel @Inject constructor( ssoId = registerResult.ssoID, serverConfigId = registerResult.serverConfigId, proxyCredentials = registerResult.proxyCredentials, + isPersistentWebSocketEnabled = defaultWebSocketEnabledByDefault, replace = false ).let { when (it) { diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModel.kt index d11883c65c2..b5ffe741f46 100644 --- a/app/src/main/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModel.kt @@ -29,6 +29,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import com.wire.android.datastore.UserDataStoreProvider import com.wire.android.di.ClientScopeProvider +import com.wire.android.di.DefaultWebSocketEnabledByDefault import com.wire.android.di.KaliumCoreLogic import com.wire.android.ui.authentication.login.LoginNavArgs import com.wire.android.ui.authentication.login.LoginState @@ -79,6 +80,7 @@ class LoginEmailViewModel @Inject constructor( private val resendCodeTimer: CountdownTimer, private val dispatchers: DispatcherProvider, defaultServerConfig: ServerConfig.Links, + @DefaultWebSocketEnabledByDefault private val defaultWebSocketEnabledByDefault: Boolean, ) : LoginViewModel( savedStateHandle, clientScopeProviderFactory, @@ -206,6 +208,7 @@ class LoginEmailViewModel @Inject constructor( managedBy = loginResult.managedBy, serverConfigId = loginResult.serverConfigId, proxyCredentials = loginResult.proxyCredentials, + isPersistentWebSocketEnabled = defaultWebSocketEnabledByDefault, replace = false ) }.let { diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/login/sso/LoginSSOViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/login/sso/LoginSSOViewModel.kt index a7fbab971fa..af846ad1584 100644 --- a/app/src/main/kotlin/com/wire/android/ui/authentication/login/sso/LoginSSOViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/authentication/login/sso/LoginSSOViewModel.kt @@ -29,6 +29,7 @@ import androidx.lifecycle.viewModelScope import com.wire.android.config.DefaultServerConfig import com.wire.android.datastore.UserDataStoreProvider import com.wire.android.di.ClientScopeProvider +import com.wire.android.di.DefaultWebSocketEnabledByDefault import com.wire.android.di.KaliumCoreLogic import com.wire.android.ui.authentication.login.LoginState import com.wire.android.ui.authentication.login.LoginViewModel @@ -82,7 +83,8 @@ class LoginSSOViewModel( @KaliumCoreLogic coreLogic: CoreLogic, clientScopeProviderFactory: ClientScopeProvider.Factory, userDataStoreProvider: UserDataStoreProvider, - serverConfig: ServerConfig.Links + serverConfig: ServerConfig.Links, + @DefaultWebSocketEnabledByDefault defaultWebSocketEnabledByDefault: Boolean, ) : this( savedStateHandle, addAuthenticatedUser, @@ -90,7 +92,7 @@ class LoginSSOViewModel( coreLogic, clientScopeProviderFactory, userDataStoreProvider, - LoginSSOViewModelExtension(addAuthenticatedUser, coreLogic), + LoginSSOViewModelExtension(addAuthenticatedUser, coreLogic, defaultWebSocketEnabledByDefault), serverConfig ) diff --git a/app/src/main/kotlin/com/wire/android/ui/authentication/login/sso/LoginSSOViewModelExtension.kt b/app/src/main/kotlin/com/wire/android/ui/authentication/login/sso/LoginSSOViewModelExtension.kt index f62001fa10f..c536ff6b939 100644 --- a/app/src/main/kotlin/com/wire/android/ui/authentication/login/sso/LoginSSOViewModelExtension.kt +++ b/app/src/main/kotlin/com/wire/android/ui/authentication/login/sso/LoginSSOViewModelExtension.kt @@ -32,6 +32,7 @@ import com.wire.kalium.logic.feature.auth.sso.ValidateSSOCodeUseCase.Companion.S class LoginSSOViewModelExtension( private val addAuthenticatedUser: AddAuthenticatedUserUseCase, private val coreLogic: CoreLogic, + private val defaultWebSocketEnabledByDefault: Boolean, ) { suspend fun withAuthenticationScope( serverConfig: ServerConfig.Links, @@ -100,6 +101,7 @@ class LoginSSOViewModelExtension( serverConfigId = serverConfigId, proxyCredentials = ssoLoginResult.proxyCredentials, managedBy = ssoLoginResult.managedBy, + isPersistentWebSocketEnabled = defaultWebSocketEnabledByDefault, replace = false ).let { authenticatedUserResult -> when (authenticatedUserResult) { diff --git a/app/src/main/kotlin/com/wire/android/ui/newauthentication/login/NewLoginViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/newauthentication/login/NewLoginViewModel.kt index 5fab862726b..d1bf10b96f1 100644 --- a/app/src/main/kotlin/com/wire/android/ui/newauthentication/login/NewLoginViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/newauthentication/login/NewLoginViewModel.kt @@ -29,6 +29,7 @@ import androidx.lifecycle.viewModelScope import com.wire.android.appLogger import com.wire.android.datastore.UserDataStoreProvider import com.wire.android.di.ClientScopeProvider +import com.wire.android.di.DefaultWebSocketEnabledByDefault import com.wire.android.di.KaliumCoreLogic import com.wire.android.ui.authentication.login.DomainClaimedByOrg import com.wire.android.ui.authentication.login.LoginNavArgs @@ -91,6 +92,7 @@ class NewLoginViewModel( dispatchers: DispatcherProvider, defaultServerConfig: ServerConfig.Links, @Named("ssoCodeConfig") defaultSSOCodeConfig: String, + @DefaultWebSocketEnabledByDefault defaultWebSocketEnabledByDefault: Boolean, ) : this( validateEmailOrSSOCode, coreLogic, @@ -98,7 +100,7 @@ class NewLoginViewModel( clientScopeProviderFactory, userDataStoreProvider, LoginViewModelExtension(clientScopeProviderFactory, userDataStoreProvider), - LoginSSOViewModelExtension(addAuthenticatedUser, coreLogic), + LoginSSOViewModelExtension(addAuthenticatedUser, coreLogic, defaultWebSocketEnabledByDefault), dispatchers, defaultServerConfig, defaultSSOCodeConfig diff --git a/app/src/main/kotlin/com/wire/android/ui/registration/code/CreateAccountVerificationCodeViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/registration/code/CreateAccountVerificationCodeViewModel.kt index dd7efdabf82..eafaa24b385 100644 --- a/app/src/main/kotlin/com/wire/android/ui/registration/code/CreateAccountVerificationCodeViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/registration/code/CreateAccountVerificationCodeViewModel.kt @@ -28,6 +28,7 @@ import androidx.lifecycle.viewModelScope import com.wire.android.BuildConfig import com.wire.android.analytics.RegistrationAnalyticsManagerUseCase import com.wire.android.di.ClientScopeProvider +import com.wire.android.di.DefaultWebSocketEnabledByDefault import com.wire.android.di.KaliumCoreLogic import com.wire.android.feature.analytics.model.AnalyticsEvent import com.wire.android.ui.authentication.create.common.CreateAccountDataNavArgs @@ -56,7 +57,8 @@ class CreateAccountVerificationCodeViewModel @Inject constructor( private val addAuthenticatedUser: AddAuthenticatedUserUseCase, private val registrationAnalyticsManager: RegistrationAnalyticsManagerUseCase, private val clientScopeProviderFactory: ClientScopeProvider.Factory, - defaultServerConfig: ServerConfig.Links + defaultServerConfig: ServerConfig.Links, + @DefaultWebSocketEnabledByDefault private val defaultWebSocketEnabledByDefault: Boolean, ) : ViewModel() { val createAccountNavArgs: CreateAccountDataNavArgs = savedStateHandle.navArgs() @@ -164,6 +166,7 @@ class CreateAccountVerificationCodeViewModel @Inject constructor( ssoId = registerResult.ssoID, serverConfigId = registerResult.serverConfigId, proxyCredentials = registerResult.proxyCredentials, + isPersistentWebSocketEnabled = defaultWebSocketEnabledByDefault, replace = false ).let { when (it) { diff --git a/kalium b/kalium index ae71a9a75ae..354c5e1e4da 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit ae71a9a75ae63027c8970905ef5bdeabc59fee8b +Subproject commit 354c5e1e4dab2c2baeae48e93692009f067a25b3 From f1f67a1d0720275f1fe21ec7049ee0c8cb6e00b8 Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Thu, 29 Jan 2026 14:45:48 +0100 Subject: [PATCH 2/5] refactor: change fileRestrictionState to use Lazy evaluation --- app/src/main/kotlin/com/wire/android/di/KaliumConfigsModule.kt | 2 +- kalium | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/com/wire/android/di/KaliumConfigsModule.kt b/app/src/main/kotlin/com/wire/android/di/KaliumConfigsModule.kt index a2673431d78..ca01f13766d 100644 --- a/app/src/main/kotlin/com/wire/android/di/KaliumConfigsModule.kt +++ b/app/src/main/kotlin/com/wire/android/di/KaliumConfigsModule.kt @@ -34,7 +34,7 @@ class KaliumConfigsModule { @Provides fun provideKaliumConfigs(): KaliumConfigs { return KaliumConfigs( - fileRestrictionState = { + fileRestrictionState = lazy { if (BuildConfig.FILE_RESTRICTION_ENABLED) { BuildConfig.FILE_RESTRICTION_LIST.split(",").map { it.trim() }.let { BuildFileRestrictionState.AllowSome(it) diff --git a/kalium b/kalium index 354c5e1e4da..5e348db6ee9 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit 354c5e1e4dab2c2baeae48e93692009f067a25b3 +Subproject commit 5e348db6ee9ed9fce69dacae3132633bb6142699 From e6f647e74bab7d3d2975cd83a6ddd32676b3254b Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Fri, 30 Jan 2026 17:14:57 +0100 Subject: [PATCH 3/5] tests --- .../login/email/LoginEmailViewModelTest.kt | 9 +++++---- kalium | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/src/test/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModelTest.kt b/app/src/test/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModelTest.kt index a2b69b4178a..b7d7a6b0799 100644 --- a/app/src/test/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModelTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/authentication/login/email/LoginEmailViewModelTest.kt @@ -453,7 +453,7 @@ class LoginEmailViewModelTest { loginViewModel.userIdentifierTextState.setTextAndPlaceCursorAtEnd(email) loginViewModel.secondFactorVerificationCodeTextState.setTextAndPlaceCursorAtEnd(code) advanceUntilIdle() - coVerify(exactly = 0) { arrangement.addAuthenticatedUserUseCase(any(), any(), any(), any()) } + coVerify(exactly = 0) { arrangement.addAuthenticatedUserUseCase(any(), any(), any(), any(), any()) } coVerify(exactly = 0) { arrangement.getOrRegisterClientUseCase(any()) } assertEquals(LoginState.Error.DialogError.Request2FAWithHandle, loginViewModel.loginState.flowState) } @@ -689,7 +689,7 @@ class LoginEmailViewModelTest { } coVerify(exactly = 1) { // verify that the second login job has been started arrangement.loginUseCase(any(), any(), any(), any(), any()) - arrangement.addAuthenticatedUserUseCase(any(), any(), eq(authToken2), any(), any()) + arrangement.addAuthenticatedUserUseCase(any(), any(), eq(authToken2), any(), any(), any(), any()) } } @@ -880,7 +880,8 @@ class LoginEmailViewModelTest { coreLogic, countdownTimer, dispatcherProvider, - ServerConfig.STAGING + ServerConfig.STAGING, + false, ).also { it.autoLoginWhenFullCodeEntered = true } fun withLoginReturning(result: AuthenticationResult) = apply { @@ -891,7 +892,7 @@ class LoginEmailViewModelTest { fun withAddAuthenticatedUserReturning(result: AddAuthenticatedUserUseCase.Result) = apply { coEvery { - addAuthenticatedUserUseCase(any(), any(), any(), any(), any()) + addAuthenticatedUserUseCase(any(), any(), any(), any(), any(), any(), any()) } returns result } diff --git a/kalium b/kalium index 5e348db6ee9..f3791af2abe 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit 5e348db6ee9ed9fce69dacae3132633bb6142699 +Subproject commit f3791af2abe309ec5b4b0c53d3877054ca2e9e3e From 2e237fbe4dc418014ccbc76db7595c4ddfe37fae Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Fri, 30 Jan 2026 17:17:51 +0100 Subject: [PATCH 4/5] build test service --- kalium | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kalium b/kalium index f3791af2abe..0ac7c385b7d 160000 --- a/kalium +++ b/kalium @@ -1 +1 @@ -Subproject commit f3791af2abe309ec5b4b0c53d3877054ca2e9e3e +Subproject commit 0ac7c385b7dbbf9334125ff4eae9636d212134ad From 49cff6302de6f8191e9d0b70e9d7b56ca0fa7083 Mon Sep 17 00:00:00 2001 From: Mohamad Jaara Date: Mon, 2 Feb 2026 11:32:32 +0100 Subject: [PATCH 5/5] feat: add provider for default WebSocket enabled configuration --- .../kotlin/com/wire/android/TestCoreLogicModule.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/androidTest/kotlin/com/wire/android/TestCoreLogicModule.kt b/app/src/androidTest/kotlin/com/wire/android/TestCoreLogicModule.kt index 1bbe357cc90..f8acaa6fd08 100644 --- a/app/src/androidTest/kotlin/com/wire/android/TestCoreLogicModule.kt +++ b/app/src/androidTest/kotlin/com/wire/android/TestCoreLogicModule.kt @@ -21,6 +21,7 @@ package com.wire.android import android.content.Context import androidx.work.WorkManager import com.wire.android.di.CoreLogicModule +import com.wire.android.di.DefaultWebSocketEnabledByDefault import com.wire.android.di.KaliumCoreLogic import com.wire.android.di.NoSession import com.wire.android.util.UserAgentProvider @@ -119,4 +120,8 @@ class TestCoreLogicModule { @Provides fun provideAudioNormalizedLoudnessBuilder(@KaliumCoreLogic coreLogic: CoreLogic): AudioNormalizedLoudnessBuilder = coreLogic.audioNormalizedLoudnessBuilder + + @DefaultWebSocketEnabledByDefault + @Provides + fun provideDefaultWebSocketEnabledByDefault(): Boolean = true }