diff options
| author | Albin <albin@mullvad.net> | 2022-07-07 12:15:58 +0200 |
|---|---|---|
| committer | Albin <albin@mullvad.net> | 2022-07-20 09:59:02 +0200 |
| commit | 8f05c4d31cd58f830217bd8feffb737c264913a3 (patch) | |
| tree | 41d22bc429615667c81fcb90b0f118c623909e11 /android/app/src | |
| parent | 96de567548c0d999f56d2c4b416d7ab0a26890f4 (diff) | |
| download | mullvadvpn-8f05c4d31cd58f830217bd8feffb737c264913a3.tar.xz mullvadvpn-8f05c4d31cd58f830217bd8feffb737c264913a3.zip | |
Decouple AdvancedFragment
Diffstat (limited to 'android/app/src')
| -rw-r--r-- | android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/AdvancedFragment.kt | 184 |
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 } } |
