diff options
Diffstat (limited to 'android')
7 files changed, 35 insertions, 93 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt index 7134f7b7d2..1d4421b063 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt @@ -15,6 +15,7 @@ import net.mullvad.mullvadvpn.repository.ChangelogRepository import net.mullvad.mullvadvpn.repository.DeviceRepository import net.mullvad.mullvadvpn.repository.PrivacyDisclaimerRepository import net.mullvad.mullvadvpn.repository.SettingsRepository +import net.mullvad.mullvadvpn.ui.serviceconnection.MessageHandler import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager import net.mullvad.mullvadvpn.ui.serviceconnection.SplitTunneling import net.mullvad.mullvadvpn.util.ChangelogDataProvider @@ -40,6 +41,7 @@ import org.koin.android.ext.koin.androidApplication import org.koin.android.ext.koin.androidContext import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.core.qualifier.named +import org.koin.dsl.bind import org.koin.dsl.module import org.koin.dsl.onClose @@ -59,7 +61,7 @@ val uiModule = module { SplitTunneling(messenger, dispatcher) } - single { ServiceConnectionManager(androidContext()) } + single { ServiceConnectionManager(androidContext()) } bind MessageHandler::class single { InetAddressValidator.getInstance() } single { androidContext().resources } single { androidContext().assets } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/AccountRepository.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/AccountRepository.kt index de72fa8d93..0bf8b1b8ec 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/AccountRepository.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/AccountRepository.kt @@ -10,43 +10,41 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.withContext import net.mullvad.mullvadvpn.lib.ipc.Event +import net.mullvad.mullvadvpn.lib.ipc.Request import net.mullvad.mullvadvpn.model.AccountCreationResult import net.mullvad.mullvadvpn.model.AccountExpiry import net.mullvad.mullvadvpn.model.AccountHistory import net.mullvad.mullvadvpn.model.LoginResult -import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager -import net.mullvad.mullvadvpn.ui.serviceconnection.accountDataSource -import net.mullvad.mullvadvpn.util.flatMapReadyConnectionOrDefault +import net.mullvad.mullvadvpn.ui.serviceconnection.MessageHandler +import net.mullvad.mullvadvpn.ui.serviceconnection.events class AccountRepository( - private val serviceConnectionManager: ServiceConnectionManager, - val dispatcher: CoroutineDispatcher = Dispatchers.IO + private val messageHandler: MessageHandler, + private val dispatcher: CoroutineDispatcher = Dispatchers.IO ) { private val _cachedCreatedAccount = MutableStateFlow<String?>(null) val cachedCreatedAccount = _cachedCreatedAccount.asStateFlow() private val accountCreationEvents: SharedFlow<AccountCreationResult> = - serviceConnectionManager.connectionState - .flatMapReadyConnectionOrDefault(flowOf()) { state -> - state.container.accountDataSource.accountCreationResult - } + messageHandler + .events<Event.AccountCreationEvent>() + .map { it.result } .onEach { _cachedCreatedAccount.value = (it as? AccountCreationResult.Success)?.accountToken } .shareIn(CoroutineScope(dispatcher), SharingStarted.WhileSubscribed()) val accountExpiryState: StateFlow<AccountExpiry> = - serviceConnectionManager.connectionState - .flatMapReadyConnectionOrDefault(flowOf()) { state -> - state.container.accountDataSource.accountExpiry - } + messageHandler + .events<Event.AccountExpiryEvent>() + .map { it.expiry } .stateIn( CoroutineScope(dispatcher), SharingStarted.WhileSubscribed(), @@ -54,10 +52,9 @@ class AccountRepository( ) val accountHistory: StateFlow<AccountHistory> = - serviceConnectionManager.connectionState - .flatMapReadyConnectionOrDefault(flowOf()) { state -> - state.container.accountDataSource.accountHistory - } + messageHandler + .events<Event.AccountHistoryEvent>() + .map { it.history } .onStart { fetchAccountHistory() } .stateIn( CoroutineScope(dispatcher), @@ -65,42 +62,41 @@ class AccountRepository( AccountHistory.Missing ) - private val loginEvents: SharedFlow<Event.LoginEvent> = - serviceConnectionManager.connectionState - .flatMapReadyConnectionOrDefault(flowOf()) { state -> - state.container.accountDataSource.loginEvents - } + private val loginEvents: SharedFlow<LoginResult> = + messageHandler + .events<Event.LoginEvent>() + .map { it.result } .shareIn(CoroutineScope(dispatcher), SharingStarted.WhileSubscribed()) suspend fun createAccount(): AccountCreationResult = withContext(dispatcher) { val deferred = async { accountCreationEvents.first() } - serviceConnectionManager.accountDataSource()?.createAccount() + messageHandler.trySendRequest(Request.CreateAccount) deferred.await() } suspend fun login(accountToken: String): LoginResult = withContext(Dispatchers.IO) { - val deferred = async { loginEvents.first().result } - serviceConnectionManager.accountDataSource()?.login(accountToken) + val deferred = async { loginEvents.first() } + messageHandler.trySendRequest(Request.Login(accountToken)) deferred.await() } fun logout() { clearCreatedAccountCache() - serviceConnectionManager.accountDataSource()?.logout() + messageHandler.trySendRequest(Request.Logout) } fun fetchAccountExpiry() { - serviceConnectionManager.accountDataSource()?.fetchAccountExpiry() + messageHandler.trySendRequest(Request.FetchAccountExpiry) } fun fetchAccountHistory() { - serviceConnectionManager.accountDataSource()?.fetchAccountHistory() + messageHandler.trySendRequest(Request.FetchAccountHistory) } fun clearAccountHistory() { - serviceConnectionManager.accountDataSource()?.clearAccountHistory() + messageHandler.trySendRequest(Request.ClearAccountHistory) } private fun clearCreatedAccountCache() { diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt index 3d30d28845..e8c8cefb81 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt @@ -25,6 +25,7 @@ import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onSubscription import kotlinx.coroutines.launch import kotlinx.coroutines.withTimeoutOrNull import net.mullvad.mullvadvpn.BuildConfig @@ -312,6 +313,7 @@ open class MainActivity : FragmentActivity() { private suspend fun isExpired(timeoutMillis: Long): Boolean { return withTimeoutOrNull(timeoutMillis) { accountRepository.accountExpiryState + .onSubscription { accountRepository.fetchAccountExpiry() } .filter { it is AccountExpiry.Available } .map { it.date()?.isBeforeNow } .first() diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionAccountDataSource.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionAccountDataSource.kt deleted file mode 100644 index d383035102..0000000000 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionAccountDataSource.kt +++ /dev/null @@ -1,58 +0,0 @@ -package net.mullvad.mullvadvpn.ui.serviceconnection - -import android.os.Messenger -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.callbackFlow -import net.mullvad.mullvadvpn.lib.ipc.Event -import net.mullvad.mullvadvpn.lib.ipc.EventDispatcher -import net.mullvad.mullvadvpn.lib.ipc.Request - -class ServiceConnectionAccountDataSource( - private val connection: Messenger, - private val dispatcher: EventDispatcher -) { - val accountCreationResult = callbackFlow { - val handler: (Event.AccountCreationEvent) -> Unit = { event -> trySend(event.result) } - dispatcher.registerHandler(Event.AccountCreationEvent::class, handler) - awaitClose { - // The current dispatcher doesn't support unregistration of handlers. - } - } - - val accountExpiry = callbackFlow { - val handler: (Event.AccountExpiryEvent) -> Unit = { event -> trySend(event.expiry) } - dispatcher.registerHandler(Event.AccountExpiryEvent::class, handler) - connection.send(Request.FetchAccountExpiry.message) - awaitClose { - // The current dispatcher doesn't support unregistration of handlers. - } - } - - val accountHistory = callbackFlow { - val handler: (Event.AccountHistoryEvent) -> Unit = { event -> trySend(event.history) } - dispatcher.registerHandler(Event.AccountHistoryEvent::class, handler) - awaitClose { - // The current dispatcher doesn't support unregistration of handlers. - } - } - - val loginEvents = callbackFlow { - val handler: (Event.LoginEvent) -> Unit = { event -> trySend(event) } - dispatcher.registerHandler(Event.LoginEvent::class, handler) - awaitClose { - // The current dispatcher doesn't support unregistration of handlers. - } - } - - fun createAccount() = connection.send(Request.CreateAccount.message) - - fun login(accountToken: String) = connection.send(Request.Login(accountToken).message) - - fun logout() = connection.send(Request.Logout.message) - - fun fetchAccountExpiry() = connection.send(Request.FetchAccountExpiry.message) - - fun fetchAccountHistory() = connection.send(Request.FetchAccountHistory.message) - - fun clearAccountHistory() = connection.send(Request.ClearAccountHistory.message) -} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt index 93dcd75359..7d34f2a96f 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt @@ -25,7 +25,6 @@ class ServiceConnectionContainer( val events = dispatcher.parsedMessages.filterIsInstance<Event>() - val accountDataSource = ServiceConnectionAccountDataSource(connection, dispatcher) val authTokenCache = AuthTokenCache(connection, dispatcher) val connectionProxy = ConnectionProxy(connection, dispatcher) val deviceDataSource = ServiceConnectionDeviceDataSource(connection, dispatcher) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt index f7be833792..c4b3d100bd 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt @@ -1,8 +1,5 @@ package net.mullvad.mullvadvpn.ui.serviceconnection -fun ServiceConnectionManager.accountDataSource() = - this.connectionState.value.readyContainer()?.accountDataSource - fun ServiceConnectionManager.appVersionInfoCache() = this.connectionState.value.readyContainer()?.appVersionInfoCache 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 a03de806b4..fb3e3d6393 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 @@ -41,6 +41,10 @@ class AccountViewModel( @Suppress("konsist.ensure public properties use permitted names") val enterTransitionEndAction = _enterTransitionEndAction.asSharedFlow() + init { + accountRepository.fetchAccountExpiry() + } + fun onManageAccountClick() { viewModelScope.launch { _uiSideEffect.tryEmit( |
