Skip to content

Commit

Permalink
fix: inject usecases lazily in WireActivityViewModel (WPB-6874) (#3096)
Browse files Browse the repository at this point in the history
  • Loading branch information
ohassine authored Jun 14, 2024
1 parent a573beb commit ee78771
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 71 deletions.
111 changes: 57 additions & 54 deletions app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import com.wire.kalium.logic.feature.session.GetSessionsUseCase
import com.wire.kalium.logic.feature.user.screenshotCensoring.ObserveScreenshotCensoringConfigResult
import com.wire.kalium.logic.feature.user.webSocketStatus.ObservePersistentWebSocketConnectionStatusUseCase
import com.wire.kalium.util.DateTimeUtil.toIsoDateTimeString
import dagger.Lazy
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
Expand All @@ -99,32 +100,32 @@ import javax.inject.Inject
@OptIn(ExperimentalCoroutinesApi::class)
@HiltViewModel
class WireActivityViewModel @Inject constructor(
@KaliumCoreLogic private val coreLogic: CoreLogic,
private val dispatchers: DispatcherProvider,
private val currentSessionFlow: CurrentSessionFlowUseCase,
private val doesValidSessionExist: DoesValidSessionExistUseCase,
private val getServerConfigUseCase: GetServerConfigUseCase,
private val deepLinkProcessor: DeepLinkProcessor,
private val authServerConfigProvider: AuthServerConfigProvider,
private val getSessions: GetSessionsUseCase,
private val accountSwitch: AccountSwitchUseCase,
private val migrationManager: MigrationManager,
private val servicesManager: ServicesManager,
@KaliumCoreLogic private val coreLogic: Lazy<CoreLogic>,
private val dispatchers: Lazy<DispatcherProvider>,
private val currentSessionFlow: Lazy<CurrentSessionFlowUseCase>,
private val doesValidSessionExist: Lazy<DoesValidSessionExistUseCase>,
private val getServerConfigUseCase: Lazy<GetServerConfigUseCase>,
private val deepLinkProcessor: Lazy<DeepLinkProcessor>,
private val authServerConfigProvider: Lazy<AuthServerConfigProvider>,
private val getSessions: Lazy<GetSessionsUseCase>,
private val accountSwitch: Lazy<AccountSwitchUseCase>,
private val migrationManager: Lazy<MigrationManager>,
private val servicesManager: Lazy<ServicesManager>,
private val observeSyncStateUseCaseProviderFactory: ObserveSyncStateUseCaseProvider.Factory,
private val observeIfAppUpdateRequired: ObserveIfAppUpdateRequiredUseCase,
private val observeNewClients: ObserveNewClientsUseCase,
private val clearNewClientsForUser: ClearNewClientsForUserUseCase,
private val currentScreenManager: CurrentScreenManager,
private val observeIfAppUpdateRequired: Lazy<ObserveIfAppUpdateRequiredUseCase>,
private val observeNewClients: Lazy<ObserveNewClientsUseCase>,
private val clearNewClientsForUser: Lazy<ClearNewClientsForUserUseCase>,
private val currentScreenManager: Lazy<CurrentScreenManager>,
private val observeScreenshotCensoringConfigUseCaseProviderFactory: ObserveScreenshotCensoringConfigUseCaseProvider.Factory,
private val globalDataStore: GlobalDataStore,
private val globalDataStore: Lazy<GlobalDataStore>,
private val observeIfE2EIRequiredDuringLoginUseCaseProviderFactory: ObserveIfE2EIRequiredDuringLoginUseCaseProvider.Factory,
private val workManager: WorkManager
private val workManager: Lazy<WorkManager>
) : ViewModel() {

var globalAppState: GlobalAppState by mutableStateOf(GlobalAppState())
private set

private val observeUserId = currentSessionFlow()
private val observeUserId = currentSessionFlow.get().invoke()
.distinctUntilChanged()
.onEach {
if (it is CurrentSessionResult.Success) {
Expand All @@ -145,7 +146,7 @@ class WireActivityViewModel @Inject constructor(
}
}
.distinctUntilChanged()
.flowOn(dispatchers.io())
.flowOn(dispatchers.get().io())
.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), 1)

private val _observeSyncFlowState: MutableStateFlow<SyncState?> = MutableStateFlow(null)
Expand All @@ -167,8 +168,8 @@ class WireActivityViewModel @Inject constructor(
}

private fun observeAppThemeState() {
viewModelScope.launch(dispatchers.io()) {
globalDataStore.selectedThemeOptionFlow()
viewModelScope.launch(dispatchers.get().io()) {
globalDataStore.get().selectedThemeOptionFlow()
.distinctUntilChanged()
.collect {
globalAppState = globalAppState.copy(themeOption = it)
Expand All @@ -177,7 +178,7 @@ class WireActivityViewModel @Inject constructor(
}

private fun observeSyncState() {
viewModelScope.launch(dispatchers.io()) {
viewModelScope.launch(dispatchers.get().io()) {
observeUserId
.flatMapLatest {
it?.let { observeSyncStateUseCaseProviderFactory.create(it).observeSyncState() } ?: flowOf(null)
Expand All @@ -189,7 +190,7 @@ class WireActivityViewModel @Inject constructor(

private fun observeUpdateAppState() {
viewModelScope.launch {
observeIfAppUpdateRequired(BuildConfig.VERSION_CODE)
observeIfAppUpdateRequired.get().invoke(BuildConfig.VERSION_CODE)
.distinctUntilChanged()
.collect {
globalAppState = globalAppState.copy(updateAppDialog = it)
Expand All @@ -198,11 +199,14 @@ class WireActivityViewModel @Inject constructor(
}

private fun observeNewClientState() {
viewModelScope.launch(dispatchers.io()) {
currentScreenManager.observeCurrentScreen(this)
viewModelScope.launch(dispatchers.get().io()) {
currentScreenManager.get().observeCurrentScreen(this)
.flatMapLatest {
if (it.isGlobalDialogAllowed()) observeNewClients()
else flowOf(NewClientResult.Empty)
if (it.isGlobalDialogAllowed()) {
observeNewClients.get().invoke()
} else {
flowOf(NewClientResult.Empty)
}
}
.collect {
val newClientDialog = NewClientsData.fromUseCaseResul(it)
Expand All @@ -212,7 +216,7 @@ class WireActivityViewModel @Inject constructor(
}

private fun observeScreenshotCensoringConfigState() {
viewModelScope.launch(dispatchers.io()) {
viewModelScope.launch(dispatchers.get().io()) {
observeUserId
.flatMapLatest {
it?.let {
Expand All @@ -227,7 +231,7 @@ class WireActivityViewModel @Inject constructor(
}

private suspend fun handleInvalidSession(logoutReason: LogoutReason) {
withContext(dispatchers.main()) {
withContext(dispatchers.get().main()) {
when (logoutReason) {
LogoutReason.SELF_SOFT_LOGOUT, LogoutReason.SELF_HARD_LOGOUT -> {
// Self logout is handled from the Self user profile screen directly
Expand All @@ -244,7 +248,6 @@ class WireActivityViewModel @Inject constructor(
}
}
}

val initialAppState: InitialAppState
get() = when {
shouldMigrate() -> InitialAppState.NOT_MIGRATED
Expand All @@ -259,11 +262,11 @@ class WireActivityViewModel @Inject constructor(

@VisibleForTesting
internal suspend fun canLoginThroughDeepLinks() = viewModelScope.async {
coreLogic.getGlobalScope().session.currentSession().takeIf {
coreLogic.get().getGlobalScope().session.currentSession().takeIf {
it is CurrentSessionResult.Success
}?.let {
val currentUserId = (it as CurrentSessionResult.Success).accountInfo.userId
coreLogic.getSessionScope(currentUserId).calls.establishedCall().first().isEmpty()
coreLogic.get().getSessionScope(currentUserId).calls.establishedCall().first().isEmpty()
} ?: true
}

Expand All @@ -281,7 +284,7 @@ class WireActivityViewModel @Inject constructor(
return
}
viewModelScope.launch {
val result = intent?.data?.let { deepLinkProcessor(it) }
val result = intent?.data?.let { deepLinkProcessor.get().invoke(it) }
when {
result is DeepLinkResult.SSOLogin -> {
if (canLoginThroughDeepLinks().await()) {
Expand Down Expand Up @@ -320,7 +323,7 @@ class WireActivityViewModel @Inject constructor(
fun customBackendDialogProceedButtonClicked(onProceed: () -> Unit) {
if (globalAppState.customBackendDialog != null) {
viewModelScope.launch {
authServerConfigProvider.updateAuthServer(globalAppState.customBackendDialog!!.serverLinks)
authServerConfigProvider.get().updateAuthServer(globalAppState.customBackendDialog!!.serverLinks)
dismissCustomBackendDialog()
if (checkNumberOfSessions() >= BuildConfig.MAX_ACCOUNTS) {
globalAppState = globalAppState.copy(maxAccountDialog = true)
Expand All @@ -337,16 +340,16 @@ class WireActivityViewModel @Inject constructor(
switchAccountActions: SwitchAccountActions
) {
viewModelScope.launch {
coreLogic.getGlobalScope().session.currentSession().takeIf {
coreLogic.get().getGlobalScope().session.currentSession().takeIf {
it is CurrentSessionResult.Success
}?.let {
val currentUserId = (it as CurrentSessionResult.Success).accountInfo.userId
coreLogic.getSessionScope(currentUserId).logout(LogoutReason.SELF_HARD_LOGOUT)
coreLogic.get().getSessionScope(currentUserId).logout(LogoutReason.SELF_HARD_LOGOUT)
clearUserData(currentUserId)
}
accountSwitch(SwitchAccountParam.TryToSwitchToNextAccount).also {
accountSwitch.get().invoke(SwitchAccountParam.TryToSwitchToNextAccount).also {
if (it == SwitchAccountResult.NoOtherAccountToSwitch) {
globalDataStore.clearAppLockPasscode()
globalDataStore.get().clearAppLockPasscode()
}
}.callAction(switchAccountActions)
}
Expand All @@ -355,17 +358,17 @@ class WireActivityViewModel @Inject constructor(
fun dismissNewClientsDialog(userId: UserId) {
globalAppState = globalAppState.copy(newClientDialog = null)
viewModelScope.launch {
doesValidSessionExist(userId).let {
doesValidSessionExist.get().invoke(userId).let {
if (it is DoesValidSessionExistResult.Success && it.doesValidSessionExist) {
clearNewClientsForUser(userId)
clearNewClientsForUser.get().invoke(userId)
}
}
}
}

fun switchAccount(userId: UserId, actions: SwitchAccountActions, onComplete: () -> Unit) {
viewModelScope.launch {
accountSwitch(SwitchAccountParam.SwitchToAccount(userId))
accountSwitch.get().invoke(SwitchAccountParam.SwitchToAccount(userId))
.callAction(actions)
onComplete()
}
Expand All @@ -374,13 +377,13 @@ class WireActivityViewModel @Inject constructor(
fun tryToSwitchAccount(actions: SwitchAccountActions) {
viewModelScope.launch {
globalAppState = globalAppState.copy(blockUserUI = null)
accountSwitch(SwitchAccountParam.TryToSwitchToNextAccount)
accountSwitch.get().invoke(SwitchAccountParam.TryToSwitchToNextAccount)
.callAction(actions)
}
}

private suspend fun checkNumberOfSessions(): Int {
getSessions().let {
getSessions.get().invoke().let {
return when (it) {
is GetAllSessionsResult.Success -> {
it.sessions.filterIsInstance<AccountInfo.Valid>().size
Expand All @@ -392,7 +395,7 @@ class WireActivityViewModel @Inject constructor(
}
}

private suspend fun loadServerConfig(url: String): ServerConfig.Links? = when (val result = getServerConfigUseCase(url)) {
private suspend fun loadServerConfig(url: String): ServerConfig.Links? = when (val result = getServerConfigUseCase.get().invoke(url)) {
is GetServerConfigResult.Success -> result.serverConfigLinks
// TODO: show error message on failure
is GetServerConfigResult.Failure.Generic -> {
Expand All @@ -416,11 +419,11 @@ class WireActivityViewModel @Inject constructor(
key: String,
domain: String?,
onSuccess: (ConversationId) -> Unit
) = when (val currentSession = coreLogic.getGlobalScope().session.currentSession()) {
) = when (val currentSession = coreLogic.get().getGlobalScope().session.currentSession()) {
is CurrentSessionResult.Failure.Generic -> null
CurrentSessionResult.Failure.SessionNotFound -> null
is CurrentSessionResult.Success -> {
coreLogic.sessionScope(currentSession.accountInfo.userId) {
coreLogic.get().sessionScope(currentSession.accountInfo.userId) {
when (val result = conversations.checkIConversationInviteCode(code, key, domain)) {
is CheckConversationInviteCodeUseCase.Result.Success -> {
if (result.isSelfMember) {
Expand Down Expand Up @@ -460,7 +463,7 @@ class WireActivityViewModel @Inject constructor(

private fun hasValidCurrentSession(): Boolean = runBlocking {
// TODO: the usage of currentSessionFlow is a temporary solution, it should be replaced with a proper solution
currentSessionFlow().first().let {
currentSessionFlow.get().invoke().first().let {
when (it) {
is CurrentSessionResult.Failure.Generic -> false
CurrentSessionResult.Failure.SessionNotFound -> false
Expand All @@ -470,7 +473,7 @@ class WireActivityViewModel @Inject constructor(
}

fun shouldMigrate(): Boolean = runBlocking {
migrationManager.shouldMigrate()
migrationManager.get().shouldMigrate()
}

fun dismissMaxAccountDialog() {
Expand All @@ -479,7 +482,7 @@ class WireActivityViewModel @Inject constructor(

fun observePersistentConnectionStatus() {
viewModelScope.launch {
coreLogic.getGlobalScope().observePersistentWebSocketConnectionStatus().let { result ->
coreLogic.get().getGlobalScope().observePersistentWebSocketConnectionStatus().let { result ->
when (result) {
is ObservePersistentWebSocketConnectionStatusUseCase.Result.Failure -> {
appLogger.e("Failure while fetching persistent web socket status flow from wire activity")
Expand All @@ -489,13 +492,13 @@ class WireActivityViewModel @Inject constructor(
result.persistentWebSocketStatusListFlow.collect { statuses ->

if (statuses.any { it.isPersistentWebSocketEnabled }) {
if (!servicesManager.isPersistentWebSocketServiceRunning()) {
servicesManager.startPersistentWebSocketService()
workManager.enqueuePeriodicPersistentWebsocketCheckWorker()
if (!servicesManager.get().isPersistentWebSocketServiceRunning()) {
servicesManager.get().startPersistentWebSocketService()
workManager.get().enqueuePeriodicPersistentWebsocketCheckWorker()
}
} else {
servicesManager.stopPersistentWebSocketService()
workManager.cancelPeriodicPersistentWebsocketCheckWorker()
servicesManager.get().stopPersistentWebSocketService()
workManager.get().cancelPeriodicPersistentWebsocketCheckWorker()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -741,26 +741,26 @@ class WireActivityViewModelTest {

private val viewModel by lazy {
WireActivityViewModel(
coreLogic = coreLogic,
dispatchers = TestDispatcherProvider(),
currentSessionFlow = currentSessionFlow,
doesValidSessionExist = doesValidSessionExist,
getServerConfigUseCase = getServerConfigUseCase,
deepLinkProcessor = deepLinkProcessor,
authServerConfigProvider = authServerConfigProvider,
getSessions = getSessionsUseCase,
accountSwitch = switchAccount,
migrationManager = migrationManager,
servicesManager = servicesManager,
coreLogic = { coreLogic },
dispatchers = { TestDispatcherProvider() },
currentSessionFlow = { currentSessionFlow },
doesValidSessionExist = { doesValidSessionExist },
getServerConfigUseCase = { getServerConfigUseCase },
deepLinkProcessor = { deepLinkProcessor },
authServerConfigProvider = { authServerConfigProvider },
getSessions = { getSessionsUseCase },
accountSwitch = { switchAccount },
migrationManager = { migrationManager },
servicesManager = { servicesManager },
observeSyncStateUseCaseProviderFactory = observeSyncStateUseCaseProviderFactory,
observeIfAppUpdateRequired = observeIfAppUpdateRequired,
observeNewClients = observeNewClients,
clearNewClientsForUser = clearNewClientsForUser,
currentScreenManager = currentScreenManager,
observeIfAppUpdateRequired = { observeIfAppUpdateRequired },
observeNewClients = { observeNewClients },
clearNewClientsForUser = { clearNewClientsForUser },
currentScreenManager = { currentScreenManager },
observeScreenshotCensoringConfigUseCaseProviderFactory = observeScreenshotCensoringConfigUseCaseProviderFactory,
globalDataStore = globalDataStore,
globalDataStore = { globalDataStore },
observeIfE2EIRequiredDuringLoginUseCaseProviderFactory = observeIfE2EIRequiredDuringLoginUseCaseProviderFactory,
workManager = workManager
workManager = { workManager }
)
}

Expand Down

0 comments on commit ee78771

Please sign in to comment.