summaryrefslogtreecommitdiffhomepage
path: root/android/app
diff options
context:
space:
mode:
authorAlbin <albin@mullvad.net>2022-07-07 12:15:58 +0200
committerAlbin <albin@mullvad.net>2022-07-20 09:59:02 +0200
commit8f05c4d31cd58f830217bd8feffb737c264913a3 (patch)
tree41d22bc429615667c81fcb90b0f118c623909e11 /android/app
parent96de567548c0d999f56d2c4b416d7ab0a26890f4 (diff)
downloadmullvadvpn-8f05c4d31cd58f830217bd8feffb737c264913a3.tar.xz
mullvadvpn-8f05c4d31cd58f830217bd8feffb737c264913a3.zip
Decouple AdvancedFragment
Diffstat (limited to 'android/app')
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/AdvancedFragment.kt184
1 files changed, 125 insertions, 59 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/AdvancedFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/AdvancedFragment.kt
index 275981bd83..12282c30a9 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/AdvancedFragment.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/AdvancedFragment.kt
@@ -4,22 +4,45 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.LinearLayoutManager
import java.net.InetAddress
import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.collect
+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.launch
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.model.Settings
import net.mullvad.mullvadvpn.ui.customdns.CustomDnsAdapter
+import net.mullvad.mullvadvpn.ui.extension.requireMainActivity
+import net.mullvad.mullvadvpn.ui.fragments.BaseFragment
import net.mullvad.mullvadvpn.ui.fragments.SplitTunnelingFragment
-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.customDns
+import net.mullvad.mullvadvpn.ui.serviceconnection.settingsListener
import net.mullvad.mullvadvpn.ui.widget.CellSwitch
import net.mullvad.mullvadvpn.ui.widget.CustomRecyclerView
import net.mullvad.mullvadvpn.ui.widget.MtuCell
import net.mullvad.mullvadvpn.ui.widget.NavigateCell
import net.mullvad.mullvadvpn.ui.widget.ToggleCell
import net.mullvad.mullvadvpn.util.AdapterWithHeader
+import net.mullvad.mullvadvpn.util.JobTracker
+import net.mullvad.mullvadvpn.util.callbackFlowFromNotifier
+import org.koin.android.ext.android.inject
+
+class AdvancedFragment : BaseFragment() {
+
+ // Injected dependencies
+ private val serviceConnectionManager: ServiceConnectionManager by inject()
-class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) {
private var isAllowLanEnabled = false
// Both customDnsAdapter and customDnsToggle are nullable since onNewServiceConnection,
@@ -30,38 +53,115 @@ class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) {
private lateinit var wireguardMtuInput: MtuCell
private lateinit var titleController: CollapsibleTitleController
- override fun onSafelyCreateView(
+ @Deprecated("Refactor code to instead rely on Lifecycle.")
+ private val jobTracker = JobTracker()
+
+ val shared = serviceConnectionManager.connectionState
+ .flatMapLatest { state ->
+ if (state is ServiceConnectionState.ConnectedReady) {
+ flowOf(state.container)
+ } else {
+ emptyFlow()
+ }
+ }
+ .map {
+ it.customDns
+ }
+ .shareIn(lifecycleScope, SharingStarted.WhileSubscribed())
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ lifecycleScope.launch {
+ repeatOnLifecycle(Lifecycle.State.RESUMED) {
+ launch {
+ serviceConnectionManager.connectionState
+ .flatMapLatest { state ->
+ if (state is ServiceConnectionState.ConnectedReady) {
+ flowOf(state.container)
+ } else {
+ emptyFlow()
+ }
+ }
+ .flatMapLatest {
+ callbackFlowFromNotifier(it.settingsListener.settingsNotifier)
+ }
+ .collect { settings ->
+ if (settings != null) {
+ updateUi(settings)
+ }
+ }
+ }
+
+ launch {
+ shared
+ .flatMapLatest {
+ callbackFlowFromNotifier(it.onEnabledChanged)
+ }
+ .collect { isEnabled ->
+ customDnsAdapter?.updateState(isEnabled)
+ jobTracker.newUiJob("updateEnabled") {
+ if (isEnabled) {
+ customDnsToggle?.state = CellSwitch.State.ON
+ } else {
+ customDnsToggle?.state = CellSwitch.State.OFF
+ }
+ }
+ }
+ }
+
+ launch {
+ shared
+ .flatMapLatest {
+ callbackFlowFromNotifier(it.onDnsServersChanged)
+ }
+ .collect { servers ->
+ customDnsAdapter?.updateServers(servers)
+ }
+ }
+ }
+ }
+ }
+
+ override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
- ): View {
+ ): View? {
val view = inflater.inflate(R.layout.advanced, container, false)
view.findViewById<View>(R.id.back).setOnClickListener {
customDnsAdapter?.stopEditing()
- parentActivity.onBackPressed()
+ requireActivity().onBackPressed()
}
titleController = CollapsibleTitleController(view, R.id.contents)
customDnsAdapter = CustomDnsAdapter(
- onAddServer = { address -> customDns.addDnsServer(address) },
- onRemoveDnsServer = { address -> customDns.removeDnsServer(address) },
+ onAddServer = { address ->
+ serviceConnectionManager.customDns()?.addDnsServer(address) ?: false
+ },
+ onRemoveDnsServer = { address ->
+ serviceConnectionManager.customDns()?.removeDnsServer(address) ?: false
+ },
onSetCustomDnsEnabled = { isEnabled ->
if (isEnabled) {
- customDns.enable()
+ serviceConnectionManager.customDns()?.enable()
} else {
- customDns.disable()
+ serviceConnectionManager.customDns()?.disable()
}
},
onReplaceDnsServer = { oldServer, newServer ->
- customDns.replaceDnsServer(oldServer, newServer)
+ serviceConnectionManager.customDns()?.replaceDnsServer(
+ oldServer,
+ newServer
+ ) ?: false
}
).also { newCustomDnsAdapter ->
+
newCustomDnsAdapter.confirmAddAddress = ::confirmAddAddress
view.findViewById<CustomRecyclerView>(R.id.contents).apply {
- layoutManager = LinearLayoutManager(parentActivity)
+ layoutManager = LinearLayoutManager(requireContext())
adapter = AdapterWithHeader(newCustomDnsAdapter, R.layout.advanced_header).apply {
onHeaderAvailable = { headerView ->
@@ -84,21 +184,21 @@ class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) {
return view
}
- override fun onNewServiceConnection(serviceConnectionContainer: ServiceConnectionContainer) {
- super.onNewServiceConnection(serviceConnectionContainer)
- subscribeToCustomDnsChanges()
- }
-
- override fun onSafelyDestroyView() {
+ override fun onDestroyView() {
detachBackButtonHandler()
customDnsAdapter?.onDestroy()
titleController.onDestroy()
- settingsListener.settingsNotifier.unsubscribe(this)
+ super.onDestroyView()
}
private fun configureHeader(view: View) {
wireguardMtuInput = view.findViewById<MtuCell>(R.id.wireguard_mtu).apply {
- onSubmit = { mtu -> settingsListener.wireguardMtu = mtu }
+ onSubmit = { mtu ->
+ serviceConnectionManager.settingsListener()?.wireguardMtu = mtu
+ }
+ value = serviceConnectionManager.settingsListener()?.let { settingsNotifier ->
+ settingsNotifier.wireguardMtu
+ }
}
view.findViewById<NavigateCell>(R.id.split_tunneling).apply {
@@ -109,52 +209,18 @@ class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) {
listener = { state ->
jobTracker.newBackgroundJob("toggleCustomDns") {
if (state == CellSwitch.State.ON) {
- customDns.enable()
+ serviceConnectionManager.customDns()?.enable()
} else {
- customDns.disable()
+ serviceConnectionManager.customDns()?.disable()
}
}
}
}
-
- settingsListener.settingsNotifier.subscribe(this) { maybeSettings ->
- maybeSettings?.let { settings ->
- updateUi(settings)
- }
-
- isAllowLanEnabled = maybeSettings?.allowLan ?: false
- }
-
- subscribeToCustomDnsChanges()
- }
-
- private fun subscribeToCustomDnsChanges() {
- // Ensure there are no previous subscriptions as this function might be called either when
- // there view has been created or when there is a new service connection.
- customDns.onEnabledChanged.unsubscribe(this)
- customDns.onDnsServersChanged.unsubscribe(this)
-
- customDns.onEnabledChanged.subscribe(this) { isEnabled ->
- customDnsAdapter?.updateState(isEnabled)
- jobTracker.newUiJob("updateEnabled") {
- if (isEnabled) {
- customDnsToggle?.state = CellSwitch.State.ON
- } else {
- customDnsToggle?.state = CellSwitch.State.OFF
- }
- }
- }
-
- customDns.onDnsServersChanged.subscribe(this) { servers ->
- customDnsAdapter?.updateServers(servers)
- }
}
private fun updateUi(settings: Settings) {
- jobTracker.newUiJob("updateUi") {
- if (!wireguardMtuInput.hasFocus) {
- wireguardMtuInput.value = settings.tunnelOptions.wireguard.options.mtu
- }
+ if (this::wireguardMtuInput.isInitialized && wireguardMtuInput.hasFocus == false) {
+ wireguardMtuInput.value = settings.tunnelOptions.wireguard.options.mtu
}
}
@@ -182,7 +248,7 @@ class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) {
}
private fun attachBackButtonHandler() {
- parentActivity.backButtonHandler = {
+ requireMainActivity().backButtonHandler = {
if (customDnsAdapter?.isEditing == true) {
customDnsAdapter?.stopEditing()
}
@@ -191,6 +257,6 @@ class AdvancedFragment : ServiceDependentFragment(OnNoService.GoBack) {
}
private fun detachBackButtonHandler() {
- parentActivity.backButtonHandler = null
+ requireMainActivity().backButtonHandler = null
}
}