mirror of
https://github.com/bitwarden/android.git
synced 2026-03-21 13:52:07 -05:00
PM-19099: Centralize app metadata (#4847)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.x8bit.bitwarden.data.platform.util
|
||||
|
||||
import android.os.Build
|
||||
import com.x8bit.bitwarden.BuildConfig
|
||||
|
||||
/**
|
||||
@@ -7,3 +8,55 @@ import com.x8bit.bitwarden.BuildConfig
|
||||
*/
|
||||
val isFdroid: Boolean
|
||||
get() = BuildConfig.FLAVOR == "fdroid"
|
||||
|
||||
/**
|
||||
* A string that represents a displayable app version.
|
||||
*/
|
||||
val versionData: String
|
||||
get() = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
|
||||
|
||||
/**
|
||||
* A string that represents device data.
|
||||
*/
|
||||
val deviceData: String get() = "$deviceBrandModel $osInfo $buildInfo"
|
||||
|
||||
/**
|
||||
* A string representing the CI information if available.
|
||||
*/
|
||||
val ciBuildInfo: String? get() = BuildConfig.CI_INFO.takeUnless { it.isBlank() }
|
||||
|
||||
/**
|
||||
* A string representing the build flavor or blank if it is the standard configuration.
|
||||
*/
|
||||
private val buildFlavorName: String
|
||||
get() = when (BuildConfig.FLAVOR) {
|
||||
"standard" -> ""
|
||||
else -> "-${BuildConfig.FLAVOR}"
|
||||
}
|
||||
|
||||
/**
|
||||
* A string representing the build type.
|
||||
*/
|
||||
private val buildTypeName: String
|
||||
get() = when (BuildConfig.BUILD_TYPE) {
|
||||
"debug" -> "dev"
|
||||
"release" -> "prod"
|
||||
else -> BuildConfig.BUILD_TYPE
|
||||
}
|
||||
|
||||
/**
|
||||
* A string representing the device brand and model.
|
||||
*/
|
||||
private val deviceBrandModel: String get() = "\uD83D\uDCF1 ${Build.BRAND} ${Build.MODEL}"
|
||||
|
||||
/**
|
||||
* A string representing the operating system information.
|
||||
*/
|
||||
private val osInfo: String get() = "\uD83E\uDD16 ${Build.VERSION.RELEASE}@${Build.VERSION.SDK_INT}"
|
||||
|
||||
/**
|
||||
* A string representing the build information.
|
||||
*/
|
||||
private val buildInfo: String
|
||||
get() = "\uD83D\uDCE6 $buildTypeName" +
|
||||
buildFlavorName.takeUnless { it.isBlank() }?.let { " $it" }.orEmpty()
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
package com.x8bit.bitwarden.ui.platform.feature.settings.about
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Parcelable
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.x8bit.bitwarden.BuildConfig
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.data.platform.manager.LogsManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
||||
import com.x8bit.bitwarden.data.platform.repository.EnvironmentRepository
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.baseWebVaultUrlOrDefault
|
||||
import com.x8bit.bitwarden.data.platform.util.ciBuildInfo
|
||||
import com.x8bit.bitwarden.data.platform.util.deviceData
|
||||
import com.x8bit.bitwarden.data.platform.util.isFdroid
|
||||
import com.x8bit.bitwarden.data.platform.util.versionData
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.Text
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||
@@ -37,10 +38,15 @@ class AboutViewModel @Inject constructor(
|
||||
private val logsManager: LogsManager,
|
||||
private val environmentRepository: EnvironmentRepository,
|
||||
) : BaseViewModel<AboutState, AboutEvent, AboutAction>(
|
||||
initialState = savedStateHandle[KEY_STATE] ?: createInitialState(
|
||||
clock = clock,
|
||||
isCrashLoggingEnabled = logsManager.isEnabled,
|
||||
),
|
||||
initialState = savedStateHandle[KEY_STATE]
|
||||
?: AboutState(
|
||||
version = R.string.version.asText().concat(": $versionData".asText()),
|
||||
deviceData = deviceData.asText(),
|
||||
ciData = ciBuildInfo?.let { "\n$it" }.orEmpty().asText(),
|
||||
isSubmitCrashLogsEnabled = logsManager.isEnabled,
|
||||
shouldShowCrashLogsButton = !isFdroid,
|
||||
copyrightInfo = "© Bitwarden Inc. 2015-${Year.now(clock).value}".asText(),
|
||||
),
|
||||
) {
|
||||
init {
|
||||
stateFlow
|
||||
@@ -92,34 +98,13 @@ class AboutViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
private fun handleVersionClick() {
|
||||
val buildFlavour = when (BuildConfig.FLAVOR) {
|
||||
"standard" -> ""
|
||||
else -> "-${BuildConfig.FLAVOR}"
|
||||
}
|
||||
|
||||
val buildVariant = when (BuildConfig.BUILD_TYPE) {
|
||||
"debug" -> "dev"
|
||||
"release" -> "prod"
|
||||
else -> BuildConfig.BUILD_TYPE
|
||||
}
|
||||
|
||||
val deviceBrandModel = "\uD83D\uDCF1 ${Build.BRAND} ${Build.MODEL}"
|
||||
val osInfo = "\uD83E\uDD16 ${Build.VERSION.RELEASE}@${Build.VERSION.SDK_INT}"
|
||||
val buildInfo = "\uD83D\uDCE6 $buildVariant$buildFlavour"
|
||||
val ciBuildInfoString = BuildConfig.CI_INFO
|
||||
|
||||
clipboardManager.setText(
|
||||
text = state.copyrightInfo
|
||||
.concat("\n\n".asText())
|
||||
.concat(state.version)
|
||||
.concat("\n".asText())
|
||||
.concat("$deviceBrandModel $osInfo $buildInfo".asText())
|
||||
.concat(
|
||||
"\n$ciBuildInfoString"
|
||||
.takeUnless { ciBuildInfoString.isEmpty() }
|
||||
.orEmpty()
|
||||
.asText(),
|
||||
),
|
||||
.concat(state.deviceData)
|
||||
.concat(state.ciData),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -130,26 +115,6 @@ class AboutViewModel @Inject constructor(
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("UndocumentedPublicClass")
|
||||
companion object {
|
||||
/**
|
||||
* Create initial state for the About View model.
|
||||
*/
|
||||
fun createInitialState(clock: Clock, isCrashLoggingEnabled: Boolean): AboutState {
|
||||
val currentYear = Year.now(clock).value
|
||||
val copyrightInfo = "© Bitwarden Inc. 2015-$currentYear".asText()
|
||||
|
||||
return AboutState(
|
||||
version = R.string.version
|
||||
.asText()
|
||||
.concat(": ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})".asText()),
|
||||
isSubmitCrashLogsEnabled = isCrashLoggingEnabled,
|
||||
shouldShowCrashLogsButton = !isFdroid,
|
||||
copyrightInfo = copyrightInfo,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,6 +123,8 @@ class AboutViewModel @Inject constructor(
|
||||
@Parcelize
|
||||
data class AboutState(
|
||||
val version: Text,
|
||||
val deviceData: Text,
|
||||
val ciData: Text,
|
||||
val isSubmitCrashLogsEnabled: Boolean,
|
||||
val shouldShowCrashLogsButton: Boolean,
|
||||
val copyrightInfo: Text,
|
||||
|
||||
@@ -39,6 +39,8 @@ class AboutScreenTest : BaseComposeTest() {
|
||||
private val mutableStateFlow = MutableStateFlow(
|
||||
AboutState(
|
||||
version = "Version: 1.0.0 (1)".asText(),
|
||||
deviceData = "device_data".asText(),
|
||||
ciData = "ci_data".asText(),
|
||||
isSubmitCrashLogsEnabled = false,
|
||||
copyrightInfo = "".asText(),
|
||||
shouldShowCrashLogsButton = true,
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package com.x8bit.bitwarden.ui.platform.feature.settings.about
|
||||
|
||||
import android.os.Build
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import app.cash.turbine.test
|
||||
import com.x8bit.bitwarden.BuildConfig
|
||||
import com.x8bit.bitwarden.data.platform.manager.LogsManager
|
||||
import com.x8bit.bitwarden.data.platform.manager.clipboard.BitwardenClipboardManager
|
||||
import com.x8bit.bitwarden.data.platform.repository.util.FakeEnvironmentRepository
|
||||
@@ -110,31 +108,17 @@ class AboutViewModelTest : BaseViewModelTest() {
|
||||
|
||||
@Test
|
||||
fun `on VersionClick should call setText on the ClipboardManager with specific Text`() {
|
||||
val versionName = BuildConfig.VERSION_NAME
|
||||
val versionCode = BuildConfig.VERSION_CODE
|
||||
|
||||
val deviceBrandModel = "\uD83D\uDCF1 ${Build.BRAND} ${Build.MODEL}"
|
||||
val osInfo = "\uD83E\uDD16 ${Build.VERSION.RELEASE}@${Build.VERSION.SDK_INT}"
|
||||
val buildInfo = "\uD83D\uDCE6 dev"
|
||||
val ciInfo = BuildConfig.CI_INFO
|
||||
|
||||
val expectedText = "© Bitwarden Inc. 2015-"
|
||||
.asText()
|
||||
.concat(Year.now(fixedClock).value.toString().asText())
|
||||
val state = DEFAULT_ABOUT_STATE
|
||||
val expectedText = state.copyrightInfo
|
||||
.concat("\n\n".asText())
|
||||
.concat("Version: $versionName ($versionCode)".asText())
|
||||
.concat(state.version)
|
||||
.concat("\n".asText())
|
||||
.concat("$deviceBrandModel $osInfo $buildInfo".asText())
|
||||
.concat(
|
||||
"\n$ciInfo"
|
||||
.takeUnless { ciInfo.isEmpty() }
|
||||
.orEmpty()
|
||||
.asText(),
|
||||
)
|
||||
.concat(state.deviceData)
|
||||
.concat(state.ciData)
|
||||
|
||||
every { clipboardManager.setText(expectedText, true, null) } just runs
|
||||
|
||||
val viewModel = createViewModel(DEFAULT_ABOUT_STATE)
|
||||
val viewModel = createViewModel(state)
|
||||
viewModel.trySendAction(AboutAction.VersionClick)
|
||||
|
||||
verify(exactly = 1) {
|
||||
@@ -175,10 +159,10 @@ private val fixedClock = Clock.fixed(
|
||||
ZoneId.systemDefault(),
|
||||
)
|
||||
private val DEFAULT_ABOUT_STATE: AboutState = AboutState(
|
||||
version = "Version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})".asText(),
|
||||
version = "Version: <version_name> (<version_code>)".asText(),
|
||||
deviceData = "<device_data>".asText(),
|
||||
ciData = "\n<ci_info>".asText(),
|
||||
isSubmitCrashLogsEnabled = false,
|
||||
copyrightInfo = "© Bitwarden Inc. 2015-"
|
||||
.asText()
|
||||
.concat(Year.now(fixedClock).value.toString().asText()),
|
||||
copyrightInfo = "© Bitwarden Inc. 2015-${Year.now(fixedClock).value}".asText(),
|
||||
shouldShowCrashLogsButton = true,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.x8bit.bitwarden.ui.platform.util
|
||||
|
||||
import android.os.Build
|
||||
import com.x8bit.bitwarden.BuildConfig
|
||||
import com.x8bit.bitwarden.data.platform.util.deviceData
|
||||
import com.x8bit.bitwarden.data.platform.util.versionData
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class BuildConfigTest {
|
||||
@Test
|
||||
fun `deviceData should be formatted correctly`() {
|
||||
val deviceBrandModel = "\uD83D\uDCF1 ${Build.BRAND} ${Build.MODEL}"
|
||||
val osInfo = "\uD83E\uDD16 ${Build.VERSION.RELEASE}@${Build.VERSION.SDK_INT}"
|
||||
val buildInfo = "\uD83D\uDCE6 dev"
|
||||
|
||||
assertEquals("$deviceBrandModel $osInfo $buildInfo", deviceData)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `versionData should be formatted correctly`() {
|
||||
val versionName = BuildConfig.VERSION_NAME
|
||||
val versionCode = BuildConfig.VERSION_CODE
|
||||
|
||||
assertEquals("$versionName ($versionCode)", versionData)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user