diff options
7 files changed, 70 insertions, 90 deletions
diff --git a/ui/src/main/java/com/wireguard/android/fragment/AddTunnelsSheet.kt b/ui/src/main/java/com/wireguard/android/fragment/AddTunnelsSheet.kt index 3df141be..f823b2b5 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/AddTunnelsSheet.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/AddTunnelsSheet.kt @@ -51,9 +51,11 @@ class AddTunnelsSheet : BottomSheetDialogFragment() { view.viewTreeObserver.removeOnGlobalLayoutListener(this) val dialog = dialog as BottomSheetDialog? ?: return behavior = dialog.behavior - behavior.state = BottomSheetBehavior.STATE_EXPANDED - behavior.peekHeight = 0 - behavior.addBottomSheetCallback(bottomSheetCallback) + behavior.apply { + state = BottomSheetBehavior.STATE_EXPANDED + peekHeight = 0 + addBottomSheetCallback(bottomSheetCallback) + } dialog.findViewById<View>(R.id.create_empty)?.setOnClickListener { dismiss() onRequestCreateConfig() diff --git a/ui/src/main/java/com/wireguard/android/fragment/AppListDialogFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/AppListDialogFragment.kt index 01dadb08..34981bd3 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/AppListDialogFragment.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/AppListDialogFragment.kt @@ -19,9 +19,6 @@ import com.wireguard.android.model.ApplicationData import com.wireguard.android.util.ErrorMessages import com.wireguard.android.util.ObservableKeyedArrayList import com.wireguard.android.util.ObservableKeyedList -import java9.util.Comparators -import java9.util.function.Function -import java.util.Collections class AppListDialogFragment : DialogFragment() { private val appData: ObservableKeyedList<String, ApplicationData> = ObservableKeyedArrayList() @@ -39,8 +36,7 @@ class AppListDialogFragment : DialogFragment() { val packageName = it.activityInfo.packageName applicationData.add(ApplicationData(it.loadIcon(pm), it.loadLabel(pm).toString(), packageName, currentlyExcludedApps.contains(packageName))) } - - Collections.sort(applicationData, Comparators.comparing(Function { obj: ApplicationData -> obj.name }, java.lang.String.CASE_INSENSITIVE_ORDER)) + applicationData.sortWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name }) applicationData }.whenComplete { data, throwable -> if (data != null) { @@ -77,7 +73,7 @@ class AppListDialogFragment : DialogFragment() { dialog.setOnShowListener { dialog.getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener { val selectedItems = appData - .filter { obj: ApplicationData -> obj.isExcludedFromTunnel } + .filter { it.isExcludedFromTunnel } val excludeAll = selectedItems.isEmpty() appData.forEach { diff --git a/ui/src/main/java/com/wireguard/android/fragment/BaseFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/BaseFragment.kt index 12b99f25..35ebc462 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/BaseFragment.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/BaseFragment.kt @@ -69,7 +69,7 @@ abstract class BaseFragment : Fragment(), OnSelectedTunnelChangedListener { is TunnelDetailFragmentBinding -> binding.tunnel is TunnelListItemBinding -> binding.item else -> return - } + } ?: return Application.getBackendAsync().thenAccept { backend: Backend? -> if (backend is GoBackend) { val intent = GoBackend.VpnService.prepare(view.context) @@ -80,7 +80,7 @@ abstract class BaseFragment : Fragment(), OnSelectedTunnelChangedListener { return@thenAccept } } - setTunnelStateWithPermissionsResult(tunnel!!, checked) + setTunnelStateWithPermissionsResult(tunnel, checked) } } diff --git a/ui/src/main/java/com/wireguard/android/fragment/ConfigNamingDialogFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/ConfigNamingDialogFragment.kt index 6a60ead6..460c2146 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/ConfigNamingDialogFragment.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/ConfigNamingDialogFragment.kt @@ -4,7 +4,6 @@ */ package com.wireguard.android.fragment -import android.app.Activity import android.app.Dialog import android.content.Context import android.content.DialogInterface @@ -15,7 +14,6 @@ import androidx.fragment.app.DialogFragment import com.wireguard.android.Application import com.wireguard.android.R import com.wireguard.android.databinding.ConfigNamingDialogFragmentBinding -import com.wireguard.android.model.ObservableTunnel import com.wireguard.config.BadConfigException import com.wireguard.config.Config import java.io.ByteArrayInputStream @@ -28,13 +26,13 @@ class ConfigNamingDialogFragment : DialogFragment() { private var imm: InputMethodManager? = null private fun createTunnelAndDismiss() { - if (binding != null) { - val name = binding!!.tunnelNameText.text.toString() - Application.getTunnelManager().create(name, config).whenComplete { tunnel: ObservableTunnel?, throwable: Throwable -> + binding?.let { + val name = it.tunnelNameText.text.toString() + Application.getTunnelManager().create(name, config).whenComplete { tunnel, throwable -> if (tunnel != null) { dismiss() } else { - binding!!.tunnelNameTextLayout.error = throwable.message + it.tunnelNameTextLayout.error = throwable.message } } } @@ -51,15 +49,16 @@ class ConfigNamingDialogFragment : DialogFragment() { val configBytes = configText!!.toByteArray(StandardCharsets.UTF_8) config = try { Config.parse(ByteArrayInputStream(configBytes)) - } catch (e: BadConfigException) { - throw IllegalArgumentException("Invalid config passed to " + javaClass.simpleName, e) - } catch (e: IOException) { - throw IllegalArgumentException("Invalid config passed to " + javaClass.simpleName, e) + } catch(e: Exception) { + when(e) { + is BadConfigException, is IOException -> throw IllegalArgumentException("Invalid config passed to ${javaClass.simpleName}", e) + else -> throw e + } } } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val activity: Activity = requireActivity() + val activity = requireActivity() imm = activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager val alertDialogBuilder = AlertDialog.Builder(activity) alertDialogBuilder.setTitle(R.string.import_from_qr_code) diff --git a/ui/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.kt index 22e5d94e..2ed1b1df 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.kt @@ -18,7 +18,6 @@ import com.wireguard.android.databinding.TunnelDetailPeerBinding import com.wireguard.android.model.ObservableTunnel import com.wireguard.android.ui.EdgeToEdge.setUpRoot import com.wireguard.android.ui.EdgeToEdge.setUpScrollingContent -import com.wireguard.config.Config import java.util.Timer import java.util.TimerTask @@ -27,7 +26,7 @@ import java.util.TimerTask */ class TunnelDetailFragment : BaseFragment() { private var binding: TunnelDetailFragmentBinding? = null - private var lastState: Tunnel.State? = Tunnel.State.TOGGLE + private var lastState = Tunnel.State.TOGGLE private var timer: Timer? = null private fun formatBytes(bytes: Long): String { @@ -78,9 +77,9 @@ class TunnelDetailFragment : BaseFragment() { } override fun onSelectedTunnelChanged(oldTunnel: ObservableTunnel?, newTunnel: ObservableTunnel?) { - if (binding == null) return + binding ?: return binding!!.tunnel = newTunnel - if (newTunnel == null) binding!!.config = null else newTunnel.configAsync.thenAccept { config: Config? -> binding!!.config = config } + if (newTunnel == null) binding!!.config = null else newTunnel.configAsync.thenAccept { config -> binding!!.config = config } lastState = Tunnel.State.TOGGLE updateStats() } @@ -94,9 +93,7 @@ class TunnelDetailFragment : BaseFragment() { } override fun onViewStateRestored(savedInstanceState: Bundle?) { - if (binding == null) { - return - } + binding ?: return binding!!.fragment = this onSelectedTunnelChanged(null, selectedTunnel) super.onViewStateRestored(savedInstanceState) diff --git a/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt index b69f36bd..33749911 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt @@ -35,9 +35,7 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener { private var binding: TunnelEditorFragmentBinding? = null private var tunnel: ObservableTunnel? = null private fun onConfigLoaded(config: Config) { - if (binding != null) { - binding!!.config = ConfigProxy(config) - } + binding?.config = ConfigProxy(config) } private fun onConfigSaved(savedTunnel: Tunnel, throwable: Throwable?) { @@ -51,8 +49,8 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener { val error = ErrorMessages.get(throwable) message = getString(R.string.config_save_error, savedTunnel.name, error) Log.e(TAG, message, throwable) - if (binding != null) { - Snackbar.make(binding!!.mainContainer, message, Snackbar.LENGTH_LONG).show() + binding?.let { + Snackbar.make(it.mainContainer, message, Snackbar.LENGTH_LONG).show() } } } @@ -112,9 +110,8 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener { override fun onOptionsItemSelected(item: MenuItem): Boolean { if (item.itemId == R.id.menu_action_save) { - if (binding == null) return false - val newConfig: Config - newConfig = try { + binding ?: return false + val newConfig = try { binding!!.config!!.resolve() } catch (e: Exception) { val error = ErrorMessages.get(e) @@ -129,7 +126,7 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener { Log.d(TAG, "Attempting to create new tunnel " + binding!!.name) val manager = Application.getTunnelManager() manager.create(binding!!.name, newConfig) - .whenComplete { newTunnel, throwable -> onTunnelCreated(newTunnel, throwable) } + .whenComplete(this::onTunnelCreated) } tunnel!!.name != binding!!.name -> { Log.d(TAG, "Attempting to rename tunnel to " + binding!!.name) @@ -169,7 +166,7 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener { binding!!.config = ConfigProxy() if (tunnel != null) { binding!!.name = tunnel!!.name - tunnel!!.configAsync.thenAccept { config: Config -> onConfigLoaded(config) } + tunnel!!.configAsync.thenAccept(this::onConfigLoaded) } else { binding!!.name = "" } @@ -187,8 +184,8 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener { val error = ErrorMessages.get(throwable) message = getString(R.string.tunnel_create_error, error) Log.e(TAG, message, throwable) - if (binding != null) { - Snackbar.make(binding!!.mainContainer, message, Snackbar.LENGTH_LONG).show() + binding?.let { + Snackbar.make(it.mainContainer, message, Snackbar.LENGTH_LONG).show() } } } @@ -206,16 +203,14 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener { val error = ErrorMessages.get(throwable) message = getString(R.string.tunnel_rename_error, error) Log.e(TAG, message, throwable) - if (binding != null) { - Snackbar.make(binding!!.mainContainer, message, Snackbar.LENGTH_LONG).show() + binding?.let { + Snackbar.make(it.mainContainer, message, Snackbar.LENGTH_LONG).show() } } } override fun onViewStateRestored(savedInstanceState: Bundle?) { - if (binding == null) { - return - } + binding ?: return binding!!.fragment = this if (savedInstanceState == null) { onSelectedTunnelChanged(null, selectedTunnel) diff --git a/ui/src/main/java/com/wireguard/android/fragment/TunnelListFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/TunnelListFragment.kt index 051babb2..78c98161 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/TunnelListFragment.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/TunnelListFragment.kt @@ -23,7 +23,6 @@ import com.google.android.material.snackbar.Snackbar import com.google.zxing.integration.android.IntentIntegrator import com.wireguard.android.Application import com.wireguard.android.R -import com.wireguard.android.activity.TunnelCreatorActivity import com.wireguard.android.databinding.ObservableKeyedRecyclerViewAdapter.RowConfigurationHandler import com.wireguard.android.databinding.TunnelListFragmentBinding import com.wireguard.android.databinding.TunnelListItemBinding @@ -33,7 +32,6 @@ import com.wireguard.android.ui.EdgeToEdge.setUpFAB import com.wireguard.android.ui.EdgeToEdge.setUpRoot import com.wireguard.android.ui.EdgeToEdge.setUpScrollingContent import com.wireguard.android.util.ErrorMessages -import com.wireguard.android.util.ObservableSortedKeyedList import com.wireguard.android.widget.MultiselectableRelativeLayout import com.wireguard.config.BadConfigException import com.wireguard.config.Config @@ -63,10 +61,11 @@ class TunnelListFragment : BaseFragment() { // Config text is valid, now create the tunnel… newInstance(configText).show(parentFragmentManager, null) - } catch (e: BadConfigException) { - onTunnelImportFinished(emptyList(), listOf<Throwable>(e)) - } catch (e: IOException) { - onTunnelImportFinished(emptyList(), listOf<Throwable>(e)) + } catch (e: Exception) { + when(e) { + is BadConfigException, is IOException -> onTunnelImportFinished(emptyList(), listOf<Throwable>(e)) + else -> throw e + } } } @@ -86,28 +85,28 @@ class TunnelListFragment : BaseFragment() { if (cursor.moveToFirst() && !cursor.isNull(0)) { name = cursor.getString(0) } - cursor.close() } if (name.isEmpty()) { name = Uri.decode(uri.lastPathSegment) } var idx = name.lastIndexOf('/') if (idx >= 0) { - require(idx < name.length - 1) { "Illegal file name: $name" } + require(idx < name.length - 1) { resources.getString(R.string.illegal_filename_error, name) } name = name.substring(idx + 1) } val isZip = name.toLowerCase(Locale.ROOT).endsWith(".zip") if (name.toLowerCase(Locale.ROOT).endsWith(".conf")) { name = name.substring(0, name.length - ".conf".length) } else { - require(isZip) { "File must be .conf or .zip" } + require(isZip) { resources.getString(R.string.bad_extension_error) } } if (isZip) { ZipInputStream(contentResolver.openInputStream(uri)).use { zip -> val reader = BufferedReader(InputStreamReader(zip, StandardCharsets.UTF_8)) - var entry: ZipEntry - while (zip.nextEntry.also { entry = it } != null) { + var entry: ZipEntry? + while (true) { + entry = zip.nextEntry ?: break name = entry.name idx = name.lastIndexOf('/') if (idx >= 0) { @@ -121,15 +120,13 @@ class TunnelListFragment : BaseFragment() { } else { continue } - val config: Config? = try { + try { Config.parse(reader) } catch (e: Exception) { throwables.add(e) null - } - - if (config != null) { - futureTunnels.add(Application.getTunnelManager().create(name, config).toCompletableFuture()) + }?.let { + futureTunnels.add(Application.getTunnelManager().create(name, it).toCompletableFuture()) } } } @@ -146,7 +143,7 @@ class TunnelListFragment : BaseFragment() { if (throwables.size == 1) { throw throwables[0] } else { - require(throwables.isNotEmpty()) { "No configurations found" } + require(throwables.isNotEmpty()) { resources.getString(R.string.no_configs_error) } } } CompletableFuture.allOf(*futureTunnels.toTypedArray()) @@ -177,7 +174,7 @@ class TunnelListFragment : BaseFragment() { override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) if (savedInstanceState != null) { - val checkedItems: Collection<Int>? = savedInstanceState.getIntegerArrayList("CHECKED_ITEMS") + val checkedItems = savedInstanceState.getIntegerArrayList(CHECKED_ITEMS) if (checkedItems != null) { for (i in checkedItems) actionModeListener.setItemChecked(i, true) } @@ -225,18 +222,14 @@ class TunnelListFragment : BaseFragment() { super.onDestroyView() } - fun onRequestCreateConfig(view: View?) { - startActivity(Intent(activity, TunnelCreatorActivity::class.java)) - } - override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) - outState.putIntegerArrayList("CHECKED_ITEMS", actionModeListener.getCheckedItems()) + outState.putIntegerArrayList(CHECKED_ITEMS, actionModeListener.getCheckedItems()) } override fun onSelectedTunnelChanged(oldTunnel: ObservableTunnel?, newTunnel: ObservableTunnel?) { - if (binding == null) return - Application.getTunnelManager().tunnels.thenAccept { tunnels: ObservableSortedKeyedList<String?, ObservableTunnel?> -> + binding ?: return + Application.getTunnelManager().tunnels.thenAccept { tunnels -> if (newTunnel != null) viewForTunnel(newTunnel, tunnels).setSingleSelected(true) if (oldTunnel != null) viewForTunnel(oldTunnel, tunnels).setSingleSelected(false) } @@ -255,7 +248,7 @@ class TunnelListFragment : BaseFragment() { } private fun onTunnelImportFinished(tunnels: List<ObservableTunnel>, throwables: Collection<Throwable>) { - var message: String? = null + var message = "" for (throwable in throwables) { val error = ErrorMessages.get(throwable) message = getString(R.string.import_error, error) @@ -276,12 +269,10 @@ class TunnelListFragment : BaseFragment() { override fun onViewStateRestored(savedInstanceState: Bundle?) { super.onViewStateRestored(savedInstanceState) - if (binding == null) { - return - } + binding ?: return binding!!.fragment = this - Application.getTunnelManager().tunnels.thenAccept { tunnels: ObservableSortedKeyedList<String?, ObservableTunnel?>? -> binding!!.tunnels = tunnels } - binding!!.rowConfigurationHandler = RowConfigurationHandler { binding: TunnelListItemBinding, tunnel: ObservableTunnel, position: Int -> + Application.getTunnelManager().tunnels.thenAccept { tunnels -> binding!!.tunnels = tunnels } + binding!!.rowConfigurationHandler = RowConfigurationHandler { binding: TunnelListItemBinding, tunnel: ObservableTunnel, position -> binding.fragment = this binding.root.setOnClickListener { if (actionMode == null) { @@ -297,15 +288,15 @@ class TunnelListFragment : BaseFragment() { if (actionMode != null) (binding.root as MultiselectableRelativeLayout).setMultiSelected(actionModeListener.checkedItems.contains(position)) else - (binding.root as MultiselectableRelativeLayout).setSingleSelected(selectedTunnel === tunnel) + (binding.root as MultiselectableRelativeLayout).setSingleSelected(selectedTunnel == tunnel) } } - private fun showSnackbar(message: CharSequence?) { - if (binding != null) { - val snackbar = Snackbar.make(binding!!.mainContainer, message!!, Snackbar.LENGTH_LONG) - snackbar.anchorView = binding!!.createFab - snackbar.show() + private fun showSnackbar(message: CharSequence) { + binding?.let { + Snackbar.make(it.mainContainer, message, Snackbar.LENGTH_LONG) + .setAnchorView(it.createFab) + .show() } } @@ -316,6 +307,7 @@ class TunnelListFragment : BaseFragment() { private inner class ActionModeListener : ActionMode.Callback { val checkedItems: MutableCollection<Int> = HashSet() private var resources: Resources? = null + fun getCheckedItems(): ArrayList<Int> { return ArrayList(checkedItems) } @@ -323,8 +315,8 @@ class TunnelListFragment : BaseFragment() { override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { return when (item.itemId) { R.id.menu_action_delete -> { - val copyCheckedItems: Iterable<Int> = HashSet(checkedItems) - Application.getTunnelManager().tunnels.thenAccept { tunnels: ObservableSortedKeyedList<String, ObservableTunnel> -> + val copyCheckedItems = HashSet(checkedItems) + Application.getTunnelManager().tunnels.thenAccept { tunnels -> val tunnelsToDelete = ArrayList<ObservableTunnel>() for (position in copyCheckedItems) tunnelsToDelete.add(tunnels[position]) val futures = tunnelsToDelete @@ -332,18 +324,16 @@ class TunnelListFragment : BaseFragment() { .toTypedArray() CompletableFuture.allOf(*futures as Array<out CompletableFuture<*>>) .thenApply { futures.size } - .whenComplete { count: Int, throwable: Throwable? -> onTunnelDeletionFinished(count, throwable) } + .whenComplete(this@TunnelListFragment::onTunnelDeletionFinished) } checkedItems.clear() mode.finish() true } R.id.menu_action_select_all -> { - Application.getTunnelManager().tunnels.thenAccept { tunnels: ObservableSortedKeyedList<String?, ObservableTunnel?> -> - var i = 0 - while (i < tunnels.size) { + Application.getTunnelManager().tunnels.thenAccept { tunnels -> + for (i in 0 until tunnels.size) { setItemChecked(i, true) - ++i } } true @@ -410,6 +400,7 @@ class TunnelListFragment : BaseFragment() { companion object { const val REQUEST_IMPORT = 1 private const val REQUEST_TARGET_FRAGMENT = 2 + private const val CHECKED_ITEMS = "CHECKED_ITEMS" private val TAG = "WireGuard/" + TunnelListFragment::class.java.simpleName } } |