Skip to content
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

feat: display avs and CC version on all builds #2900

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
260 changes: 32 additions & 228 deletions app/src/main/kotlin/com/wire/android/ui/debug/DebugDataOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
*/
package com.wire.android.ui.debug

import android.content.Context
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
Expand All @@ -26,19 +25,12 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wire.android.BuildConfig
import com.wire.android.R
import com.wire.android.datastore.GlobalDataStore
import com.wire.android.di.CurrentAccount
import com.wire.android.migration.failure.UserMigrationStatus
import com.wire.android.model.Clickable
import com.wire.android.ui.common.RowItemTemplate
import com.wire.android.ui.common.WireDialog
Expand All @@ -53,214 +45,13 @@ import com.wire.android.ui.home.settings.SettingsItem
import com.wire.android.ui.theme.wireColorScheme
import com.wire.android.ui.theme.wireDimensions
import com.wire.android.ui.theme.wireTypography
import com.wire.android.util.getDependenciesVersion
import com.wire.android.util.getDeviceIdString
import com.wire.android.util.getGitBuildId
import com.wire.android.util.ui.PreviewMultipleThemes
import com.wire.kalium.logic.CoreFailure
import com.wire.kalium.logic.E2EIFailure
import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.feature.debug.DisableEventProcessingUseCase
import com.wire.kalium.logic.feature.e2ei.CheckCrlRevocationListUseCase
import com.wire.kalium.logic.feature.e2ei.usecase.E2EIEnrollmentResult
import com.wire.kalium.logic.feature.keypackage.MLSKeyPackageCountResult
import com.wire.kalium.logic.feature.keypackage.MLSKeyPackageCountUseCase
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.fold
import com.wire.kalium.logic.sync.periodic.UpdateApiVersionsScheduler
import com.wire.kalium.logic.sync.slow.RestartSlowSyncProcessForRecoveryUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.collections.immutable.ImmutableMap
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import javax.inject.Inject

//region DebugDataOptionsViewModel
data class DebugDataOptionsState(
val isEncryptedProteusStorageEnabled: Boolean = false,
val isEventProcessingDisabled: Boolean = false,
val keyPackagesCount: Int = 0,
val mslClientId: String = "null",
val mlsErrorMessage: String = "null",
val isManualMigrationAllowed: Boolean = false,
val debugId: String = "null",
val commitish: String = "null",
val certificate: String = "null",
val showCertificate: Boolean = false,
val startGettingE2EICertificate: Boolean = false,
val dependencies: ImmutableMap<String, String?> = persistentMapOf()
)

@Suppress("LongParameterList")
@HiltViewModel
class DebugDataOptionsViewModel
@Inject constructor(
@ApplicationContext private val context: Context,
@CurrentAccount val currentAccount: UserId,
private val globalDataStore: GlobalDataStore,
private val updateApiVersions: UpdateApiVersionsScheduler,
private val mlsKeyPackageCountUseCase: MLSKeyPackageCountUseCase,
private val restartSlowSyncProcessForRecovery: RestartSlowSyncProcessForRecoveryUseCase,
private val disableEventProcessingUseCase: DisableEventProcessingUseCase,
private val checkCrlRevocationListUseCase: CheckCrlRevocationListUseCase
) : ViewModel() {

var state by mutableStateOf(
DebugDataOptionsState()
)

init {
observeEncryptedProteusStorageState()
observeMlsMetadata()
checkIfCanTriggerManualMigration()
checkDependenciesVersion()
setGitHashAndDeviceId()
}

private fun setGitHashAndDeviceId() {
viewModelScope.launch {
val deviceId = context.getDeviceIdString() ?: "null"
val gitBuildId = context.getGitBuildId()
state = state.copy(
debugId = deviceId,
commitish = gitBuildId
)
}
}

fun checkDependenciesVersion() {
viewModelScope.launch {
val dependencies = context.getDependenciesVersion().toImmutableMap()
state = state.copy(
dependencies = dependencies
)
}
}

fun checkCrlRevocationList() {
viewModelScope.launch {
checkCrlRevocationListUseCase(
forceUpdate = true
)
}
}

fun enableEncryptedProteusStorage(enabled: Boolean) {
if (enabled) {
viewModelScope.launch {
globalDataStore.setEncryptedProteusStorageEnabled(true)
}
}
}

fun restartSlowSyncForRecovery() {
viewModelScope.launch {
restartSlowSyncProcessForRecovery()
}
}

fun enrollE2EICertificate() {
state = state.copy(startGettingE2EICertificate = true)
}

fun handleE2EIEnrollmentResult(result: Either<CoreFailure, E2EIEnrollmentResult>) {
result.fold({
state = state.copy(
certificate = (it as E2EIFailure.OAuth).reason,
showCertificate = true,
startGettingE2EICertificate = false
)
}, {
if (it is E2EIEnrollmentResult.Finalized) {
state = state.copy(
certificate = it.certificate,
showCertificate = true,
startGettingE2EICertificate = false
)
} else {
state.copy(
certificate = it.toString(),
showCertificate = true,
startGettingE2EICertificate = false
)
}
})
}

fun dismissCertificateDialog() {
state = state.copy(
showCertificate = false,
)
}

fun forceUpdateApiVersions() {
updateApiVersions.scheduleImmediateApiVersionUpdate()
}

fun disableEventProcessing(disabled: Boolean) {
viewModelScope.launch {
disableEventProcessingUseCase(disabled)
state = state.copy(isEventProcessingDisabled = disabled)
}
}

//region Private
private fun observeEncryptedProteusStorageState() {
viewModelScope.launch {
globalDataStore.isEncryptedProteusStorageEnabled().collect {
state = state.copy(isEncryptedProteusStorageEnabled = it)
}
}
}

// If status is NoNeed, it means that the user has already been migrated in and older app version,
// or it is a new install
// this is why we check the existence of the database file
private fun checkIfCanTriggerManualMigration() {
viewModelScope.launch {
globalDataStore.getUserMigrationStatus(currentAccount.value).first()
.let { migrationStatus ->
if (migrationStatus != UserMigrationStatus.NoNeed) {
context.getDatabasePath(currentAccount.value).let {
state = state.copy(
isManualMigrationAllowed = (it.exists() && it.isFile)
)
}
}
}
}
}

private fun observeMlsMetadata() {
viewModelScope.launch {
mlsKeyPackageCountUseCase().let {
when (it) {
is MLSKeyPackageCountResult.Success -> {
state = state.copy(
keyPackagesCount = it.count,
mslClientId = it.clientId.value
)
}

is MLSKeyPackageCountResult.Failure.NetworkCallFailure -> {
state = state.copy(mlsErrorMessage = "Network Error!")
}

is MLSKeyPackageCountResult.Failure.FetchClientIdFailure -> {
state = state.copy(mlsErrorMessage = "ClientId Fetch Error!")
}

is MLSKeyPackageCountResult.Failure.Generic -> {}
}
}
}
}
//endregion
}
//endregion

@Composable
fun DebugDataOptions(
Expand All @@ -283,7 +74,8 @@ fun DebugDataOptions(
enrollE2EICertificate = viewModel::enrollE2EICertificate,
handleE2EIEnrollmentResult = viewModel::handleE2EIEnrollmentResult,
dismissCertificateDialog = viewModel::dismissCertificateDialog,
checkCrlRevocationList = viewModel::checkCrlRevocationList
checkCrlRevocationList = viewModel::checkCrlRevocationList,
dependenciesMap = viewModel.state.dependencies
)
}

Expand All @@ -302,7 +94,8 @@ fun DebugDataOptionsContent(
enrollE2EICertificate: () -> Unit,
handleE2EIEnrollmentResult: (Either<CoreFailure, E2EIEnrollmentResult>) -> Unit,
dismissCertificateDialog: () -> Unit,
checkCrlRevocationList: () -> Unit
checkCrlRevocationList: () -> Unit,
dependenciesMap: ImmutableMap<String, String?>
) {
Column {

Expand Down Expand Up @@ -337,6 +130,7 @@ fun DebugDataOptionsContent(
onClick = { onCopyText(state.commitish) }
)
)
DependenciesItem(dependenciesMap)
if (BuildConfig.PRIVATE_BUILD) {

SettingsItem(
Expand Down Expand Up @@ -399,7 +193,6 @@ fun DebugDataOptionsContent(
onDisableEventProcessingChange = onDisableEventProcessingChange,
onRestartSlowSyncForRecovery = onRestartSlowSyncForRecovery,
onForceUpdateApiVersions = onForceUpdateApiVersions,
dependenciesMap = state.dependencies,
checkCrlRevocationList = checkCrlRevocationList
)
}
Expand Down Expand Up @@ -569,7 +362,6 @@ private fun DebugToolsOptions(
onDisableEventProcessingChange: (Boolean) -> Unit,
onRestartSlowSyncForRecovery: () -> Unit,
onForceUpdateApiVersions: () -> Unit,
dependenciesMap: ImmutableMap<String, String?>,
checkCrlRevocationList: () -> Unit
) {
FolderHeader(stringResource(R.string.label_debug_tools_title))
Expand Down Expand Up @@ -641,20 +433,31 @@ private fun DebugToolsOptions(
)
}
)
RowItemTemplate(
modifier = Modifier.wrapContentWidth(),
title = {
Text(
style = MaterialTheme.wireTypography.body01,
color = MaterialTheme.wireColorScheme.onBackground,
text = prettyPrintMap(dependenciesMap),
modifier = Modifier.padding(start = dimensions().spacing8x)
)
}
)
}
}

/**
*
MohamadJaara marked this conversation as resolved.
Show resolved Hide resolved
*/
@Composable
fun DependenciesItem(dependencies: ImmutableMap<String, String?>) {
val title = stringResource(id = R.string.item_dependencies_title)
val text = remember {
prettyPrintMap(dependencies, title)
}
RowItemTemplate(
modifier = Modifier.wrapContentWidth(),
title = {
Text(
style = MaterialTheme.wireTypography.body01,
color = MaterialTheme.wireColorScheme.onBackground,
text = text,
modifier = Modifier.padding(start = dimensions().spacing8x)
)
}
)
}

@Composable
private fun DisableEventProcessingSwitch(
isEnabled: Boolean = false,
Expand Down Expand Up @@ -685,8 +488,8 @@ private fun DisableEventProcessingSwitch(
}

@Stable
private fun prettyPrintMap(map: ImmutableMap<String, String?>): String = StringBuilder().apply {
append("Dependencies:\n")
private fun prettyPrintMap(map: Map<String, String?>, title: String): String = StringBuilder().apply {
MohamadJaara marked this conversation as resolved.
Show resolved Hide resolved
append("$title\n")
map.forEach { (key, value) ->
append("$key: $value\n")
}
Expand Down Expand Up @@ -718,6 +521,7 @@ fun PreviewOtherDebugOptions() {
enrollE2EICertificate = {},
handleE2EIEnrollmentResult = {},
dismissCertificateDialog = {},
checkCrlRevocationList = {}
checkCrlRevocationList = {},
dependenciesMap = persistentMapOf()
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Wire
* Copyright (C) 2024 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.android.ui.debug

import kotlinx.collections.immutable.ImmutableMap
import kotlinx.collections.immutable.persistentMapOf

data class DebugDataOptionsState(
val isEncryptedProteusStorageEnabled: Boolean = false,
val isEventProcessingDisabled: Boolean = false,
val keyPackagesCount: Int = 0,
val mslClientId: String = "null",
val mlsErrorMessage: String = "null",
val isManualMigrationAllowed: Boolean = false,
val debugId: String = "null",
val commitish: String = "null",
val certificate: String = "null",
val showCertificate: Boolean = false,
val startGettingE2EICertificate: Boolean = false,
val dependencies: ImmutableMap<String, String?> = persistentMapOf()
)
Loading
Loading