diff options
| author | Albin <albin@mullvad.net> | 2022-07-08 11:20:56 +0200 |
|---|---|---|
| committer | Albin <albin@mullvad.net> | 2022-07-08 11:20:56 +0200 |
| commit | b7011b47e05dfc1aa53066ad7ad5af3ad62320aa (patch) | |
| tree | 13ee01d89df09f7ac40c22069a4e68bfaf948d3a | |
| parent | 67b0483662f66a601d2ef7c7ee30f7e52d7b2c05 (diff) | |
| parent | 706bd96d62b044bec62b4615b200a043b387bb5d (diff) | |
| download | mullvadvpn-b7011b47e05dfc1aa53066ad7ad5af3ad62320aa.tar.xz mullvadvpn-b7011b47e05dfc1aa53066ad7ad5af3ad62320aa.zip | |
Merge branch 'fix-text-views-sometimes-missing'
6 files changed, 168 insertions, 104 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountFragment.kt index b3e8e9f89b..c648c3f7e6 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountFragment.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountFragment.kt @@ -5,11 +5,13 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.lifecycle.Lifecycle -import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle import java.text.DateFormat +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.model.TunnelState @@ -69,18 +71,6 @@ class AccountFragment : ServiceDependentFragment(OnNoService.GoBack) { private lateinit var redeemVoucherButton: RedeemVoucherButton private lateinit var titleController: CollapsibleTitleController - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - lifecycleScope.launch { - deviceRepository.deviceState - .flowWithLifecycle(lifecycle, Lifecycle.State.RESUMED) - .collect { state -> - accountNumberView.information = state.token() - deviceNameView.information = state.deviceName()?.capitalizeFirstCharOfEachWord() - } - } - } - override fun onSafelyCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -119,16 +109,11 @@ class AccountFragment : ServiceDependentFragment(OnNoService.GoBack) { return view } - override fun onSafelyStart() { - jobTracker.newUiJob("updateAccountExpiry") { - accountRepository.accountExpiryState - .map { state -> state.date() } - .collect { expiryDate -> - currentAccountExpiry = expiryDate - updateAccountExpiry(expiryDate) - } - } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + lifecycleScope.launchUiSubscriptionsOnResume() + } + override fun onSafelyStart() { connectionProxy.onUiStateChange.subscribe(this) { uiState -> jobTracker.newUiJob("updateHasConnectivity") { hasConnectivity = uiState is TunnelState.Connected || @@ -140,7 +125,6 @@ class AccountFragment : ServiceDependentFragment(OnNoService.GoBack) { } sitePaymentButton.updateAuthTokenCache(authTokenCache) - accountRepository.fetchAccountExpiry() } override fun onSafelyStop() { @@ -151,6 +135,36 @@ class AccountFragment : ServiceDependentFragment(OnNoService.GoBack) { titleController.onDestroy() } + private fun CoroutineScope.launchUiSubscriptionsOnResume() = launch { + repeatOnLifecycle(Lifecycle.State.RESUMED) { + launchUpdateTextOnDeviceChanges() + launchUpdateTextOnExpiryChanges() + } + } + + private fun CoroutineScope.launchUpdateTextOnDeviceChanges() { + launch { + deviceRepository.deviceState + .collect { state -> + accountNumberView.information = state.token() + deviceNameView.information = + state.deviceName()?.capitalizeFirstCharOfEachWord() + } + } + } + + private fun CoroutineScope.launchUpdateTextOnExpiryChanges() { + launch { + accountRepository.accountExpiryState + .onStart { accountRepository.fetchAccountExpiry() } + .map { state -> state.date() } + .collect { expiryDate -> + currentAccountExpiry = expiryDate + updateAccountExpiry(expiryDate) + } + } + } + private fun checkForAddedTime() { currentAccountExpiry?.let { expiry -> oldAccountExpiry = expiry diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectFragment.kt index 31cf1876f5..31d1c0dd9c 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectFragment.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectFragment.kt @@ -5,9 +5,14 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.content.ContextCompat +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.model.TunnelState import net.mullvad.mullvadvpn.ui.notification.AccountExpiryNotification @@ -89,6 +94,10 @@ class ConnectFragment : return view } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + lifecycleScope.launchUiSubscriptionsOnResume() + } + override fun onSafelyStart() { locationInfo.isTunnelInfoExpanded = isTunnelInfoExpanded @@ -111,17 +120,6 @@ class ConnectFragment : updateTunnelState(uiState, connectionProxy.state) } } - - jobTracker.newUiJob("updateAccountExpiry") { - accountRepository.accountExpiryState - .map { state -> state.date() } - .collect { expiryDate -> - if (expiryDate?.isBeforeNow == true) { - openOutOfTimeScreen() - } else if (expiryDate != null) - scheduleNextAccountExpiryCheck(expiryDate) - } - } } override fun onSafelyStop() { @@ -151,6 +149,23 @@ class ConnectFragment : paintNavigationBar(ContextCompat.getColor(requireContext(), R.color.blue)) } + private fun CoroutineScope.launchUiSubscriptionsOnResume() = launch { + repeatOnLifecycle(Lifecycle.State.RESUMED) { + launchScheduledExpiryCheck() + } + } + + private fun CoroutineScope.launchScheduledExpiryCheck() = launch { + accountRepository.accountExpiryState + .map { state -> state.date() } + .collect { expiryDate -> + if (expiryDate?.isBeforeNow == true) { + openOutOfTimeScreen() + } else if (expiryDate != null) + scheduleNextAccountExpiryCheck(expiryDate) + } + } + private fun updateTunnelState(uiState: TunnelState, realState: TunnelState) { locationInfo.state = realState headerBar.tunnelState = realState diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt index aa146f2984..d0e6fbf2f3 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt @@ -11,6 +11,7 @@ import androidx.core.content.ContextCompat import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import net.mullvad.mullvadvpn.R @@ -37,11 +38,6 @@ class LoginFragment : private lateinit var background: View private lateinit var headerBar: HeaderBar - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setupLifecycleSubscriptionsToViewModel() - } - override fun onSafelyCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -78,6 +74,10 @@ class LoginFragment : return view } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + lifecycleScope.launchUiSubscriptionsOnResume() + } + override fun onSafelyStart() { parentActivity.backButtonHandler = { if (accountLogin.hasFocus) { @@ -105,21 +105,23 @@ class LoginFragment : } } - private fun setupLifecycleSubscriptionsToViewModel() { - lifecycleScope.launch { - repeatOnLifecycle(Lifecycle.State.RESUMED) { - launch { - loginViewModel.accountHistory.collect { history -> - accountLogin.accountHistory = history.accountToken() - } - } - launch { - loginViewModel.uiState.collect { uiState -> updateUi(uiState) } - } - } + private fun CoroutineScope.launchUiSubscriptionsOnResume() = launch { + repeatOnLifecycle(Lifecycle.State.RESUMED) { + lanuchUpdateAccountHistory() + launchUpdateUiOnViewModelStateChanges() } } + private fun CoroutineScope.lanuchUpdateAccountHistory() = launch { + loginViewModel.accountHistory.collect { history -> + accountLogin.accountHistory = history.accountToken() + } + } + + private fun CoroutineScope.launchUpdateUiOnViewModelStateChanges() = launch { + loginViewModel.uiState.collect { uiState -> updateUi(uiState) } + } + private fun updateUi(uiState: LoginViewModel.LoginUiState) { when (uiState) { is LoginViewModel.LoginUiState.Default -> { diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/OutOfTimeFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/OutOfTimeFragment.kt index 02b6f1d059..03aa10c264 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/OutOfTimeFragment.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/OutOfTimeFragment.kt @@ -5,10 +5,15 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle import kotlin.properties.Delegates.observable +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map +import kotlinx.coroutines.launch import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.model.TunnelState import net.mullvad.mullvadvpn.ui.serviceconnection.AccountRepository @@ -79,15 +84,11 @@ class OutOfTimeFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) return view } - override fun onSafelyStart() { - jobTracker.newUiJob("updateAccountExpiry") { - accountRepository.accountExpiryState - .map { state -> state.date() } - .collect { expiryDate -> - checkExpiry(expiryDate) - } - } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + lifecycleScope.launchUiSubscriptionsOnResume() + } + override fun onSafelyStart() { jobTracker.newBackgroundJob("pollAccountData") { while (true) { accountRepository.fetchAccountExpiry() @@ -99,7 +100,6 @@ class OutOfTimeFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) } override fun onSafelyStop() { - jobTracker.cancelJob("updateAccountExpiry") jobTracker.cancelJob("pollAccountData") } @@ -107,6 +107,20 @@ class OutOfTimeFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) connectionProxy.onStateChange.unsubscribe(this) } + private fun CoroutineScope.launchUiSubscriptionsOnResume() = launch { + repeatOnLifecycle(Lifecycle.State.RESUMED) { + launchProceedToConnectViewIfExpiryExtended() + } + } + + private fun CoroutineScope.launchProceedToConnectViewIfExpiryExtended() = launch { + accountRepository.accountExpiryState + .map { state -> state.date() } + .collect { expiryDate -> + checkExpiry(expiryDate) + } + } + private fun updateDisconnectButton() { val state = tunnelState diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/SettingsFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/SettingsFragment.kt index d9a28a9ad7..e0f619550c 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/SettingsFragment.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/SettingsFragment.kt @@ -7,10 +7,12 @@ import android.view.ViewGroup import android.widget.ImageButton import androidx.core.content.ContextCompat import androidx.lifecycle.Lifecycle -import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.model.DeviceState @@ -49,17 +51,6 @@ class SettingsFragment : ServiceAwareFragment(), StatusBarPainter, NavigationBar versionInfoCache = null } - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - lifecycleScope.launch { - deviceRepository.deviceState - .flowWithLifecycle(lifecycle, Lifecycle.State.RESUMED) - .collect { device -> - updateLoggedInStatus(device is DeviceState.LoggedIn) - } - } - } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -95,12 +86,7 @@ class SettingsFragment : ServiceAwareFragment(), StatusBarPainter, NavigationBar } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - lifecycleScope.launchWhenResumed { - transitionFinishedFlow.collect { - paintStatusBar(ContextCompat.getColor(requireContext(), R.color.darkBlue)) - } - } + lifecycleScope.launchUiSubscriptionsOnResume() } override fun onResume() { @@ -129,17 +115,37 @@ class SettingsFragment : ServiceAwareFragment(), StatusBarPainter, NavigationBar titleController.onDestroy() } - private fun configureListeners() { - jobTracker.newUiJob("updateAccountExpiry") { - accountRepository.accountExpiryState - .map { state -> state.date() } - .collect { expiryDate -> - accountMenu.accountExpiry = expiryDate - } + private fun CoroutineScope.launchUiSubscriptionsOnResume() = launch { + repeatOnLifecycle(Lifecycle.State.RESUMED) { + launchPaintStatusBarAfterTransition() + luanchConfigureMenuOnDeviceChanges() + launchUpdateExpiryTextOnExpiryChanges() + } + } + + private fun CoroutineScope.launchPaintStatusBarAfterTransition() = launch { + transitionFinishedFlow.collect { + paintStatusBar(ContextCompat.getColor(requireContext(), R.color.darkBlue)) } + } + + private fun CoroutineScope.luanchConfigureMenuOnDeviceChanges() = launch { + deviceRepository.deviceState + .collect { device -> + updateLoggedInStatus(device is DeviceState.LoggedIn) + } + } - accountRepository.fetchAccountExpiry() + private fun CoroutineScope.launchUpdateExpiryTextOnExpiryChanges() = launch { + accountRepository.accountExpiryState + .onStart { accountRepository.fetchAccountExpiry() } + .map { state -> state.date() } + .collect { expiryDate -> + accountMenu.accountExpiry = expiryDate + } + } + private fun configureListeners() { versionInfoCache?.onUpdate = { jobTracker.newUiJob("updateVersionInfo") { updateVersionInfo() diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/WelcomeFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/WelcomeFragment.kt index 7b8978e669..3acf9b3eee 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/WelcomeFragment.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/WelcomeFragment.kt @@ -9,8 +9,13 @@ import android.view.View import android.view.ViewGroup import android.widget.TextView import android.widget.Toast +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.model.TunnelState import net.mullvad.mullvadvpn.ui.serviceconnection.AccountRepository @@ -65,19 +70,11 @@ class WelcomeFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) { return view } - override fun onSafelyStart() { - jobTracker.newUiJob("updateAccountNumber") { - deviceRepository.deviceState.collect { state -> - updateAccountNumber(state.token()) - } - } - - jobTracker.newUiJob("checkAccountExpiry") { - accountRepository.accountExpiryState.collect { - checkExpiry(it.date()) - } - } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + lifecycleScope.launchUiSubscriptionsOnResume() + } + override fun onSafelyStart() { jobTracker.newBackgroundJob("pollAccountData") { while (true) { accountRepository.fetchAccountExpiry() @@ -89,9 +86,27 @@ class WelcomeFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) { } override fun onSafelyStop() { - jobTracker.cancelJob("checkAccountExpiry") jobTracker.cancelJob("pollAccountData") - jobTracker.cancelJob("updateAccountNumber") + } + + private fun CoroutineScope.launchUiSubscriptionsOnResume() = launch { + repeatOnLifecycle(Lifecycle.State.RESUMED) { + launchUpdateAccountNumberOnDeviceChanges() + launchAdvanceToConnectViewOnExpiryExtended() + } + } + + private fun CoroutineScope.launchUpdateAccountNumberOnDeviceChanges() = launch { + deviceRepository.deviceState + .collect { state -> + updateAccountNumber(state.token()) + } + } + + private fun CoroutineScope.launchAdvanceToConnectViewOnExpiryExtended() = launch { + accountRepository.accountExpiryState.collect { + checkExpiry(it.date()) + } } private fun updateAccountNumber(rawAccountNumber: String?) { @@ -99,10 +114,8 @@ class WelcomeFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) { addSpacesToAccountText(account) } - jobTracker.newUiJob("updateAccountNumber") { - accountLabel.text = accountText ?: "" - accountLabel.setEnabled(accountText != null && accountText.length > 0) - } + accountLabel.text = accountText ?: "" + accountLabel.setEnabled(accountText != null && accountText.length > 0) } private fun addSpacesToAccountText(account: String): String { |
