summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorsaber safavi <saber.safavi@codic.se>2023-08-24 10:51:29 +0200
committersaber safavi <saber.safavi@codic.se>2023-09-28 14:51:15 +0200
commitaae59ac285b264fb163fba1470a6e83df8892eb7 (patch)
tree8b99d589a1bd445802163b0e653cb0e1ae1ea4b6 /android
parent34758da9ee93e22dce2bac98722d322414195d14 (diff)
downloadmullvadvpn-aae59ac285b264fb163fba1470a6e83df8892eb7.tar.xz
mullvadvpn-aae59ac285b264fb163fba1470a6e83df8892eb7.zip
Add info dialog for device name
Diffstat (limited to 'android')
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeviceNameInfoDialog.kt20
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt42
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreen.kt15
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AccountUiState.kt9
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AccountFragment.kt7
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModel.kt38
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt2
8 files changed, 82 insertions, 53 deletions
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt
index 5d3e229a8b..c4d2fab62e 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt
@@ -9,7 +9,7 @@ import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
-import net.mullvad.mullvadvpn.compose.state.AccountUiState
+import net.mullvad.mullvadvpn.viewmodel.AccountUiState
import net.mullvad.mullvadvpn.viewmodel.AccountViewModel
import org.junit.Before
import org.junit.Rule
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeviceNameInfoDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeviceNameInfoDialog.kt
new file mode 100644
index 0000000000..39e82bc57d
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/DeviceNameInfoDialog.kt
@@ -0,0 +1,20 @@
+package net.mullvad.mullvadvpn.compose.dialog
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.res.stringResource
+import net.mullvad.mullvadvpn.R
+
+@Composable
+fun DeviceNameInfoDialog(onDismiss: () -> Unit) {
+ InfoDialog(
+ message =
+ buildString {
+ appendLine(stringResource(id = R.string.device_name_info_first_paragraph))
+ appendLine()
+ appendLine(stringResource(id = R.string.device_name_info_second_paragraph))
+ appendLine()
+ append(stringResource(id = R.string.device_name_info_third_paragraph))
+ },
+ onDismiss = onDismiss
+ )
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt
index 22dfc34269..b3bc9e7f3b 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt
@@ -1,9 +1,9 @@
package net.mullvad.mullvadvpn.compose.screen
import androidx.compose.animation.animateContentSize
-import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
@@ -11,14 +11,21 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.google.accompanist.systemuicontroller.rememberSystemUiController
@@ -35,12 +42,13 @@ import net.mullvad.mullvadvpn.compose.component.CopyableObfuscationView
import net.mullvad.mullvadvpn.compose.component.InformationView
import net.mullvad.mullvadvpn.compose.component.MissingPolicy
import net.mullvad.mullvadvpn.compose.component.drawVerticalScrollbar
-import net.mullvad.mullvadvpn.compose.state.AccountUiState
+import net.mullvad.mullvadvpn.compose.dialog.DeviceNameInfoDialog
import net.mullvad.mullvadvpn.constant.IS_PLAY_BUILD
import net.mullvad.mullvadvpn.lib.common.util.capitalizeFirstCharOfEachWord
import net.mullvad.mullvadvpn.lib.common.util.openAccountPageInBrowser
import net.mullvad.mullvadvpn.lib.theme.Dimens
import net.mullvad.mullvadvpn.util.toExpiryDateString
+import net.mullvad.mullvadvpn.viewmodel.AccountUiState
import net.mullvad.mullvadvpn.viewmodel.AccountViewModel
@OptIn(ExperimentalMaterial3Api::class)
@@ -76,9 +84,15 @@ fun AccountScreen(
val backgroundColor = MaterialTheme.colorScheme.background
val systemUiController = rememberSystemUiController()
+ var showDeviceNameInfoDialog by remember { mutableStateOf(false) }
+
LaunchedEffect(Unit) {
enterTransitionEndAction.collect { systemUiController.setStatusBarColor(backgroundColor) }
}
+ if (showDeviceNameInfoDialog) {
+ DeviceNameInfoDialog { showDeviceNameInfoDialog = false }
+ }
+
CollapsingToolbarScaffold(
backgroundColor = MaterialTheme.colorScheme.background,
modifier = Modifier.fillMaxSize(),
@@ -127,10 +141,22 @@ fun AccountScreen(
modifier = Modifier.padding(start = Dimens.sideMargin, end = Dimens.sideMargin)
)
- InformationView(
- content = uiState.deviceName.capitalizeFirstCharOfEachWord(),
- whenMissing = MissingPolicy.SHOW_SPINNER
- )
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ InformationView(
+ content = uiState.deviceName?.capitalizeFirstCharOfEachWord() ?: "",
+ whenMissing = MissingPolicy.SHOW_SPINNER
+ )
+ IconButton(
+ modifier = Modifier.align(Alignment.CenterVertically),
+ onClick = { showDeviceNameInfoDialog = true }
+ ) {
+ Icon(
+ painter = painterResource(id = R.drawable.icon_info),
+ contentDescription = null,
+ tint = MaterialTheme.colorScheme.inverseSurface
+ )
+ }
+ }
Text(
style = MaterialTheme.typography.labelMedium,
@@ -142,9 +168,7 @@ fun AccountScreen(
top = Dimens.smallPadding
)
)
-
- CopyableObfuscationView(content = uiState.accountNumber)
-
+ CopyableObfuscationView(content = uiState.accountNumber ?: "")
Text(
style = MaterialTheme.typography.labelMedium,
text = stringResource(id = R.string.paid_until),
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreen.kt
index b78f767f76..140b9824df 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreen.kt
@@ -38,7 +38,7 @@ import net.mullvad.mullvadvpn.compose.button.SitePaymentButton
import net.mullvad.mullvadvpn.compose.component.CopyAnimatedIconButton
import net.mullvad.mullvadvpn.compose.component.ScaffoldWithTopBar
import net.mullvad.mullvadvpn.compose.component.drawVerticalScrollbar
-import net.mullvad.mullvadvpn.compose.dialog.InfoDialog
+import net.mullvad.mullvadvpn.compose.dialog.DeviceNameInfoDialog
import net.mullvad.mullvadvpn.compose.state.WelcomeUiState
import net.mullvad.mullvadvpn.compose.util.createCopyToClipboardHandle
import net.mullvad.mullvadvpn.lib.common.util.groupWithSpaces
@@ -47,7 +47,6 @@ import net.mullvad.mullvadvpn.lib.theme.AlphaTopBar
import net.mullvad.mullvadvpn.lib.theme.AppTheme
import net.mullvad.mullvadvpn.lib.theme.Dimens
import net.mullvad.mullvadvpn.lib.theme.MullvadWhite
-import net.mullvad.mullvadvpn.ui.extension.copyToClipboard
import net.mullvad.mullvadvpn.viewmodel.WelcomeViewModel
@Preview
@@ -253,17 +252,7 @@ fun DeviceNameRow(deviceName: String?) {
)
}
if (showDeviceNameDialog) {
- InfoDialog(
- message =
- buildString {
- appendLine(stringResource(id = R.string.device_name_info_first_paragraph))
- appendLine()
- appendLine(stringResource(id = R.string.device_name_info_second_paragraph))
- appendLine()
- appendLine(stringResource(id = R.string.device_name_info_third_paragraph))
- },
- onDismiss = { showDeviceNameDialog = false }
- )
+ DeviceNameInfoDialog { showDeviceNameDialog = false }
}
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AccountUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AccountUiState.kt
deleted file mode 100644
index a952795571..0000000000
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AccountUiState.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package net.mullvad.mullvadvpn.compose.state
-
-import org.joda.time.DateTime
-
-data class AccountUiState(
- val deviceName: String,
- val accountNumber: String,
- val accountExpiry: DateTime?
-)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AccountFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AccountFragment.kt
index 39013f11a8..666bd19cdb 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AccountFragment.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AccountFragment.kt
@@ -36,10 +36,9 @@ class AccountFragment : BaseFragment(), StatusBarPainter, NavigationBarPainter {
enterTransitionEndAction = vm.enterTransitionEndAction,
onRedeemVoucherClick = { openRedeemVoucherFragment() },
onManageAccountClick = vm::onManageAccountClick,
- onLogoutClick = vm::onLogoutClick
- ) {
- activity?.onBackPressed()
- }
+ onLogoutClick = vm::onLogoutClick,
+ onBackClick = { activity?.onBackPressedDispatcher?.onBackPressed() }
+ )
}
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModel.kt
index e359deed2e..b1ce2e0027 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModel.kt
@@ -4,16 +4,17 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.compose.state.AccountUiState
+import net.mullvad.mullvadvpn.model.AccountExpiry
+import net.mullvad.mullvadvpn.model.DeviceState
import net.mullvad.mullvadvpn.repository.AccountRepository
import net.mullvad.mullvadvpn.repository.DeviceRepository
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.ui.serviceconnection.authTokenCache
+import org.joda.time.DateTime
class AccountViewModel(
private var accountRepository: AccountRepository,
@@ -25,27 +26,17 @@ class AccountViewModel(
private val _enterTransitionEndAction = MutableSharedFlow<Unit>()
val viewActions = _viewActions.asSharedFlow()
- private val vmState: StateFlow<AccountUiState> =
+ val uiState =
combine(deviceRepository.deviceState, accountRepository.accountExpiryState) {
deviceState,
accountExpiry ->
AccountUiState(
- deviceName = deviceState.deviceName() ?: "",
- accountNumber = deviceState.token() ?: "",
+ deviceName = deviceState.deviceName(),
+ accountNumber = deviceState.token(),
accountExpiry = accountExpiry.date()
)
}
- .stateIn(
- viewModelScope,
- SharingStarted.WhileSubscribed(),
- AccountUiState(deviceName = "", accountNumber = "", accountExpiry = null)
- )
- val uiState =
- vmState.stateIn(
- viewModelScope,
- SharingStarted.WhileSubscribed(),
- AccountUiState(deviceName = "", accountNumber = "", accountExpiry = null)
- )
+ .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), AccountUiState.default())
val enterTransitionEndAction = _enterTransitionEndAction.asSharedFlow()
@@ -71,3 +62,18 @@ class AccountViewModel(
data class OpenAccountManagementPageInBrowser(val token: String) : ViewAction()
}
}
+
+data class AccountUiState(
+ val deviceName: String?,
+ val accountNumber: String?,
+ val accountExpiry: DateTime?
+) {
+ companion object {
+ fun default() =
+ AccountUiState(
+ deviceName = DeviceState.Unknown.deviceName(),
+ accountNumber = DeviceState.Unknown.token(),
+ accountExpiry = AccountExpiry.Missing.date()
+ )
+ }
+}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt
index 82048b5fd1..fc1fd5e99b 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt
@@ -73,7 +73,7 @@ class AccountViewModelTest {
// Act, Assert
viewModel.uiState.test {
var result = awaitItem()
- assertEquals("", result.deviceName)
+ assertEquals(null, result.deviceName)
deviceState.value = DeviceState.LoggedIn(accountAndDevice = dummyAccountAndDevice)
result = awaitItem()
assertEquals(DUMMY_DEVICE_NAME, result.accountNumber)