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

Fix incorrect content of device name info dialog #5204

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
)
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
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
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
Expand All @@ -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)
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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,
Expand All @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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 }
}
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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() }
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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()

Expand All @@ -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()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down