Skip to content

Commit 0cb4345

Browse files
committed
Improved AboutContent
1 parent 1e01838 commit 0cb4345

File tree

6 files changed

+108
-2
lines changed

6 files changed

+108
-2
lines changed

app/src/main/kotlin/com/darkrockstudios/app/securecamera/AppModule.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.darkrockstudios.app.securecamera
22

33
import androidx.work.WorkManager
4+
import com.darkrockstudios.app.securecamera.about.AboutViewModel
5+
import com.darkrockstudios.app.securecamera.about.AboutViewModelImpl
46
import com.darkrockstudios.app.securecamera.auth.AuthorizationRepository
57
import com.darkrockstudios.app.securecamera.auth.PinVerificationViewModel
68
import com.darkrockstudios.app.securecamera.camera.SecureImageRepository
@@ -92,4 +94,5 @@ val appModule = module {
9294
viewModelOf(::IntroductionViewModelImpl) bind IntroductionViewModel::class
9395
viewModelOf(::PinVerificationViewModel)
9496
viewModelOf(::ImportPhotosViewModel)
97+
viewModelOf(::AboutViewModelImpl) bind AboutViewModel::class
9598
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.darkrockstudios.app.securecamera.about
2+
3+
import androidx.compose.foundation.layout.PaddingValues
4+
import androidx.compose.material3.MaterialTheme
5+
import androidx.compose.material3.Surface
6+
import androidx.compose.runtime.Composable
7+
import androidx.compose.ui.Modifier
8+
import androidx.compose.ui.tooling.preview.Preview
9+
import androidx.compose.ui.unit.dp
10+
import androidx.navigation3.runtime.NavKey
11+
import com.darkrockstudios.app.securecamera.navigation.NavController
12+
13+
private class DummyNavController : NavController {
14+
override fun navigate(
15+
key: NavKey,
16+
builder: (com.darkrockstudios.app.securecamera.navigation.NavOptions.() -> Unit)?
17+
) {
18+
}
19+
20+
override fun navigate(key: NavKey) {}
21+
override fun navigateUp(): Boolean = true
22+
}
23+
24+
@Preview(name = "About", showBackground = true)
25+
@Composable
26+
private fun AboutContentPreview() {
27+
Surface(color = MaterialTheme.colorScheme.background) {
28+
val dummyVm = object : AboutViewModel {
29+
private val _state = kotlinx.coroutines.flow.MutableStateFlow(AboutUiState(versionName = "1.2.3"))
30+
override val uiState: kotlinx.coroutines.flow.StateFlow<AboutUiState> = _state
31+
}
32+
AboutContent(
33+
navController = DummyNavController(),
34+
modifier = Modifier,
35+
paddingValues = PaddingValues(0.dp),
36+
viewModel = dummyVm
37+
)
38+
}
39+
}
40+

app/src/main/kotlin/com/darkrockstudios/app/securecamera/about/AboutContent.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@ import androidx.compose.material.icons.Icons
1010
import androidx.compose.material.icons.automirrored.filled.ArrowBack
1111
import androidx.compose.material3.*
1212
import androidx.compose.runtime.Composable
13+
import androidx.compose.runtime.getValue
1314
import androidx.compose.ui.Alignment
1415
import androidx.compose.ui.Modifier
1516
import androidx.compose.ui.platform.LocalContext
1617
import androidx.compose.ui.res.stringResource
1718
import androidx.compose.ui.text.style.TextDecoration
1819
import androidx.compose.ui.unit.dp
1920
import androidx.core.net.toUri
21+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
2022
import com.darkrockstudios.app.securecamera.R
2123
import com.darkrockstudios.app.securecamera.navigation.NavController
24+
import org.koin.androidx.compose.koinViewModel
2225

2326
/**
2427
* About screen content
@@ -29,6 +32,7 @@ fun AboutContent(
2932
navController: NavController,
3033
modifier: Modifier = Modifier,
3134
paddingValues: PaddingValues,
35+
viewModel: AboutViewModel = koinViewModel<AboutViewModelImpl>()
3236
) {
3337
Column(
3438
modifier = modifier
@@ -58,6 +62,7 @@ fun AboutContent(
5862
)
5963

6064
val context = LocalContext.current
65+
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
6166

6267
// About content
6368
Column(
@@ -189,9 +194,8 @@ fun AboutContent(
189194
style = MaterialTheme.typography.bodyLarge,
190195
modifier = Modifier.weight(1f)
191196
)
192-
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
193197
Text(
194-
text = packageInfo.versionName ?: "---",
198+
text = uiState.versionName,
195199
style = MaterialTheme.typography.bodyMedium,
196200
color = MaterialTheme.colorScheme.primary
197201
)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.darkrockstudios.app.securecamera.about
2+
3+
import kotlinx.coroutines.flow.StateFlow
4+
5+
interface AboutViewModel {
6+
val uiState: StateFlow<AboutUiState>
7+
}
8+
9+
data class AboutUiState(
10+
val versionName: String = "---",
11+
)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.darkrockstudios.app.securecamera.about
2+
3+
import android.content.Context
4+
import com.darkrockstudios.app.securecamera.BaseViewModel
5+
6+
class AboutViewModelImpl(
7+
private val appContext: Context,
8+
) : BaseViewModel<AboutUiState>(), AboutViewModel {
9+
10+
override fun createState(): AboutUiState {
11+
val pm = appContext.packageManager
12+
val pkg = appContext.packageName
13+
val version = try {
14+
val info = pm.getPackageInfo(pkg, 0)
15+
info.versionName ?: "---"
16+
} catch (e: Exception) {
17+
"---"
18+
}
19+
return AboutUiState(versionName = version)
20+
}
21+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.darkrockstudios.app.securecamera.about
2+
3+
import android.content.Context
4+
import android.content.pm.PackageInfo
5+
import android.content.pm.PackageManager
6+
import io.mockk.every
7+
import io.mockk.mockk
8+
import org.junit.Assert.assertEquals
9+
import org.junit.Test
10+
11+
class AboutViewModelImplTest {
12+
@Test
13+
fun `uiState exposes app version`() {
14+
val pm = mockk<PackageManager>()
15+
val ctx = mockk<Context>()
16+
every { ctx.packageManager } returns pm
17+
every { ctx.packageName } returns "com.example.app"
18+
19+
val pkgInfo = PackageInfo()
20+
pkgInfo.versionName = "9.9.9"
21+
every { pm.getPackageInfo("com.example.app", 0) } returns pkgInfo
22+
23+
val vm = AboutViewModelImpl(ctx)
24+
val state = vm.uiState.value
25+
assertEquals("9.9.9", state.versionName)
26+
}
27+
}

0 commit comments

Comments
 (0)