summaryrefslogtreecommitdiffhomepage
path: root/android/app/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'android/app/src/main')
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt16
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SplitTunnelingFragment.kt22
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionContainer.kt16
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManagerExtensions.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/ApplicationImageView.kt12
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModel.kt60
-rw-r--r--android/app/src/main/res/values/dimensions.xml1
-rw-r--r--android/app/src/main/res/values/styles.xml15
9 files changed, 65 insertions, 82 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt
index 8c5a295308..5fc222bf0a 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreen.kt
@@ -98,7 +98,7 @@ fun SplitTunnelingScreen(
title = stringResource(id = R.string.split_tunneling),
progress = progress,
modifier = scaffoldModifier,
- backTitle = stringResource(id = R.string.settings_vpn)
+ backTitle = stringResource(id = R.string.settings)
)
},
) {
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 26703d98ec..f0fcc4fa65 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
@@ -45,16 +45,12 @@ val uiModule = module {
single<PackageManager> { androidContext().packageManager }
single<String>(named(SELF_PACKAGE_NAME)) { androidContext().packageName }
- scope(named(APPS_SCOPE)) {
- viewModel { SplitTunnelingViewModel(get(), get(), Dispatchers.Default) }
- scoped { ApplicationsIconManager(get()) } onClose { it?.dispose() }
- scoped { ApplicationsProvider(get(), get(named(SELF_PACKAGE_NAME))) }
- }
+ viewModel { SplitTunnelingViewModel(get(), get(), Dispatchers.Default) }
+ single { ApplicationsIconManager(get()) } onClose { it?.dispose() }
+ single { ApplicationsProvider(get(), get(named(SELF_PACKAGE_NAME))) }
- scope(named(SERVICE_CONNECTION_SCOPE)) {
- scoped<SplitTunneling> { (messenger: Messenger, dispatcher: EventDispatcher) ->
- SplitTunneling(messenger, dispatcher)
- }
+ single { (messenger: Messenger, dispatcher: EventDispatcher) ->
+ SplitTunneling(messenger, dispatcher)
}
single { ServiceConnectionManager(androidContext()) }
@@ -97,7 +93,5 @@ val uiModule = module {
}
}
-const val APPS_SCOPE = "APPS_SCOPE"
-const val SERVICE_CONNECTION_SCOPE = "SERVICE_CONNECTION_SCOPE"
const val SELF_PACKAGE_NAME = "SELF_PACKAGE_NAME"
const val APP_PREFERENCES_NAME = "net.mullvad.mullvadvpn.app_preferences"
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SplitTunnelingFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SplitTunnelingFragment.kt
index 910588e580..9a920d7324 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SplitTunnelingFragment.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/SplitTunnelingFragment.kt
@@ -9,24 +9,11 @@ import androidx.compose.ui.platform.ComposeView
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.screen.SplitTunnelingScreen
import net.mullvad.mullvadvpn.compose.theme.AppTheme
-import net.mullvad.mullvadvpn.di.APPS_SCOPE
-import net.mullvad.mullvadvpn.di.SERVICE_CONNECTION_SCOPE
import net.mullvad.mullvadvpn.viewmodel.SplitTunnelingViewModel
-import org.koin.android.ext.android.getKoin
-import org.koin.androidx.viewmodel.ViewModelOwner
-import org.koin.androidx.viewmodel.scope.viewModel
-import org.koin.core.qualifier.named
-import org.koin.core.scope.Scope
+import org.koin.androidx.viewmodel.ext.android.viewModel
class SplitTunnelingFragment : BaseFragment() {
- private val scope: Scope =
- getKoin().getOrCreateScope(APPS_SCOPE, named(APPS_SCOPE)).also { appsScope ->
- getKoin().getScopeOrNull(SERVICE_CONNECTION_SCOPE)?.let { serviceConnectionScope ->
- appsScope.linkTo(serviceConnectionScope)
- }
- }
- private val viewModel by
- scope.viewModel<SplitTunnelingViewModel>(owner = { ViewModelOwner.from(this, this) })
+ private val viewModel: SplitTunnelingViewModel by viewModel()
override fun onCreateView(
inflater: LayoutInflater,
@@ -48,9 +35,4 @@ class SplitTunnelingFragment : BaseFragment() {
}
}
}
-
- override fun onDestroy() {
- scope.close()
- super.onDestroy()
- }
}
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 a58db46ff7..7f895618fb 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
@@ -4,15 +4,12 @@ import android.os.Looper
import android.os.Messenger
import android.os.RemoteException
import android.util.Log
-import net.mullvad.mullvadvpn.di.SERVICE_CONNECTION_SCOPE
import net.mullvad.mullvadvpn.ipc.DispatchingHandler
import net.mullvad.mullvadvpn.ipc.Event
import net.mullvad.mullvadvpn.ipc.Request
import org.koin.core.component.KoinApiExtension
-import org.koin.core.parameter.parametersOf
-import org.koin.core.qualifier.named
-import org.koin.core.scope.KoinScopeComponent
-import org.koin.core.scope.get
+import org.koin.core.component.KoinComponent
+import org.koin.core.component.get
// Container of classes that communicate with the service through an active connection
//
@@ -23,13 +20,10 @@ class ServiceConnectionContainer(
val connection: Messenger,
onServiceReady: (ServiceConnectionContainer) -> Unit,
onVpnPermissionRequest: () -> Unit
-) : KoinScopeComponent {
+) : KoinComponent {
private val dispatcher =
DispatchingHandler(Looper.getMainLooper()) { message -> Event.fromMessage(message) }
- override val scope =
- getKoin().getOrCreateScope(SERVICE_CONNECTION_SCOPE, named(SERVICE_CONNECTION_SCOPE), this)
-
val accountDataSource = ServiceConnectionAccountDataSource(connection, dispatcher)
val authTokenCache = AuthTokenCache(connection, dispatcher)
val connectionProxy = ConnectionProxy(connection, dispatcher)
@@ -37,8 +31,7 @@ class ServiceConnectionContainer(
val locationInfoCache = LocationInfoCache(dispatcher)
val settingsListener = SettingsListener(connection, dispatcher)
- // NOTE: `org.koin.core.scope.get` must be used here rather than `org.koin.core.component.get`.
- val splitTunneling = get<SplitTunneling>(parameters = { parametersOf(connection, dispatcher) })
+ val splitTunneling = SplitTunneling(connection, dispatcher)
val voucherRedeemer = VoucherRedeemer(connection, dispatcher)
val vpnPermission = VpnPermission(connection, dispatcher)
@@ -61,7 +54,6 @@ class ServiceConnectionContainer(
fun onDestroy() {
unregisterListener()
- closeScope()
dispatcher.onDestroy()
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 1de160ffe8..f7be833792 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
@@ -22,3 +22,6 @@ fun ServiceConnectionManager.relayListListener() =
fun ServiceConnectionManager.settingsListener() =
this.connectionState.value.readyContainer()?.settingsListener
+
+fun ServiceConnectionManager.splitTunneling() =
+ this.connectionState.value.readyContainer()?.splitTunneling
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/ApplicationImageView.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/ApplicationImageView.kt
index 8c840357e0..519fefb180 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/ApplicationImageView.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/ApplicationImageView.kt
@@ -15,25 +15,23 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.applist.ApplicationsIconManager
-import net.mullvad.mullvadvpn.di.APPS_SCOPE
-import org.koin.core.scope.inject
-import org.koin.core.scope.KoinScopeComponent
-import org.koin.core.scope.Scope
+import org.koin.core.component.KoinApiExtension
+import org.koin.core.component.KoinComponent
+import org.koin.core.component.inject
+@OptIn(KoinApiExtension::class)
class ApplicationImageView
@JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = R.attr.applicationListItemViewStyle,
-) : AppCompatImageView(context, attrs, defStyleAttr), KoinScopeComponent {
+) : AppCompatImageView(context, attrs, defStyleAttr), KoinComponent {
private val viewScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
private val iconManager: ApplicationsIconManager by inject()
private var updateImageJob: Job? = null
- override val scope: Scope = getKoin().getScope(APPS_SCOPE)
-
var packageName: String = ""
set(value) {
field = value
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModel.kt
index 38803cfc21..a1376eabb4 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModel.kt
@@ -5,36 +5,60 @@ import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import net.mullvad.mullvadvpn.applist.AppData
import net.mullvad.mullvadvpn.applist.ApplicationsProvider
import net.mullvad.mullvadvpn.compose.state.SplitTunnelingUiState
+import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionContainer
+import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
+import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
import net.mullvad.mullvadvpn.ui.serviceconnection.SplitTunneling
+import net.mullvad.mullvadvpn.ui.serviceconnection.splitTunneling
class SplitTunnelingViewModel(
private val appsProvider: ApplicationsProvider,
- private val splitTunneling: SplitTunneling,
+ private val serviceConnectionManager: ServiceConnectionManager,
private val dispatcher: CoroutineDispatcher
) : ViewModel() {
private val allApps = MutableStateFlow<List<AppData>?>(null)
private val showSystemApps = MutableStateFlow(false)
+ private val _shared: SharedFlow<ServiceConnectionContainer> =
+ serviceConnectionManager.connectionState
+ .flatMapLatest { state ->
+ if (state is ServiceConnectionState.ConnectedReady) {
+ flowOf(state.container)
+ } else {
+ emptyFlow()
+ }
+ }
+ .shareIn(viewModelScope, SharingStarted.WhileSubscribed())
+
private val vmState =
- combine(splitTunneling.excludedAppsCallbackFlow(), allApps, showSystemApps) {
- excludedApps,
- allApps,
- showSystemApps ->
- SplitTunnelingViewModelState(
- excludedApps = excludedApps,
- allApps = allApps,
- showSystemApps = showSystemApps
- )
+ _shared
+ .flatMapLatest { serviceConnection ->
+ combine(
+ serviceConnection.splitTunneling.excludedAppsCallbackFlow(),
+ allApps,
+ showSystemApps
+ ) { excludedApps, allApps, showSystemApps ->
+ SplitTunnelingViewModelState(
+ excludedApps = excludedApps,
+ allApps = allApps,
+ showSystemApps = showSystemApps
+ )
+ }
}
.stateIn(
viewModelScope,
@@ -53,22 +77,28 @@ class SplitTunnelingViewModel(
init {
viewModelScope.launch(dispatcher) {
- if (!splitTunneling.enabled) splitTunneling.enabled = true
+ if (serviceConnectionManager.splitTunneling()?.enabled == false) {
+ serviceConnectionManager.splitTunneling()?.enabled = true
+ }
fetchApps()
}
}
override fun onCleared() {
- splitTunneling.persist()
+ serviceConnectionManager.splitTunneling()?.persist()
super.onCleared()
}
-
+
fun onIncludeAppClick(packageName: String) {
- viewModelScope.launch(dispatcher) { splitTunneling.includeApp(packageName) }
+ viewModelScope.launch(dispatcher) {
+ serviceConnectionManager.splitTunneling()?.includeApp(packageName)
+ }
}
fun onExcludeAppClick(packageName: String) {
- viewModelScope.launch(dispatcher) { splitTunneling.excludeApp(packageName) }
+ viewModelScope.launch(dispatcher) {
+ serviceConnectionManager.splitTunneling()?.excludeApp(packageName)
+ }
}
fun onShowSystemAppsClicked(show: Boolean) {
diff --git a/android/app/src/main/res/values/dimensions.xml b/android/app/src/main/res/values/dimensions.xml
index 76fa24032d..d6bab1dade 100644
--- a/android/app/src/main/res/values/dimensions.xml
+++ b/android/app/src/main/res/values/dimensions.xml
@@ -39,7 +39,6 @@
<dimen name="half_vertical_space">10dp</dimen>
<dimen name="button_separation">18dp</dimen>
<dimen name="screen_vertical_margin">22dp</dimen>
- <dimen name="app_list_item_icon_size">35dp</dimen>
<dimen name="progress_size">60dp</dimen>
<dimen name="icon_size">24dp</dimen>
<dimen name="widget_padding">16dp</dimen>
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
index 9a808e9c3b..dab9229592 100644
--- a/android/app/src/main/res/values/styles.xml
+++ b/android/app/src/main/res/values/styles.xml
@@ -56,10 +56,6 @@
<item name="android:textColor">@color/white</item>
<item name="android:textSize">@dimen/text_medium_plus</item>
</style>
- <style name="TextAppearance.Mullvad.Title2">
- <item name="android:textColor">@color/white</item>
- <item name="android:textSize">@dimen/text_medium</item>
- </style>
<style name="TextAppearance.Mullvad.Small">
<item name="android:textColor">@color/white60</item>
<item name="android:textSize">@dimen/text_small</item>
@@ -90,17 +86,6 @@
<item name="android:clickable">false</item>
<item name="android:focusable">false</item>
</style>
- <style name="TextAppearance.Mullvad.CollapsingToolbar">
- <item name="android:textColor">@color/white</item>
- </style>
- <style name="TextAppearance.Mullvad.CollapsingToolbar.Expanded">
- <item name="android:textSize">30sp</item>
- <item name="android:textStyle">bold</item>
- </style>
- <style name="TextAppearance.Mullvad.CollapsingToolbar.Collapsed">
- <item name="android:textSize">20sp</item>
- <item name="android:textStyle">bold</item>
- </style>
<!-- Switch Style -->
<style name="AppTheme.Switch">
<item name="android:layout_width">@dimen/switch_width</item>