From 3b353c4037f3c52710287777a17110dad6b9d720 Mon Sep 17 00:00:00 2001
From: pacien
Date: Sat, 11 Aug 2018 01:54:04 +0200
Subject: Refactor part of Status activity
---
.../org/pacien/tincapp/activities/StartActivity.kt | 1 +
.../pacien/tincapp/activities/StatusActivity.kt | 197 ---------------------
.../activities/status/NetworkInfoFragment.kt | 45 +++++
.../tincapp/activities/status/StatusActivity.kt | 184 +++++++++++++++++++
.../status/VpnInterfaceConfigurationFormatter.kt | 41 +++++
.../java/org/pacien/tincapp/extensions/Android.kt | 7 -
6 files changed, 271 insertions(+), 204 deletions(-)
delete mode 100644 app/src/main/java/org/pacien/tincapp/activities/StatusActivity.kt
create mode 100644 app/src/main/java/org/pacien/tincapp/activities/status/NetworkInfoFragment.kt
create mode 100644 app/src/main/java/org/pacien/tincapp/activities/status/StatusActivity.kt
create mode 100644 app/src/main/java/org/pacien/tincapp/activities/status/VpnInterfaceConfigurationFormatter.kt
(limited to 'app/src/main/java')
diff --git a/app/src/main/java/org/pacien/tincapp/activities/StartActivity.kt b/app/src/main/java/org/pacien/tincapp/activities/StartActivity.kt
index 70302e5..84adc7f 100644
--- a/app/src/main/java/org/pacien/tincapp/activities/StartActivity.kt
+++ b/app/src/main/java/org/pacien/tincapp/activities/StartActivity.kt
@@ -37,6 +37,7 @@ import kotlinx.android.synthetic.main.fragment_network_list_header.*
import org.pacien.tincapp.R
import org.pacien.tincapp.activities.common.ProgressModal
import org.pacien.tincapp.activities.configure.ConfigureActivity
+import org.pacien.tincapp.activities.status.StatusActivity
import org.pacien.tincapp.context.AppPaths
import org.pacien.tincapp.extensions.Android.setElements
import org.pacien.tincapp.intent.Actions
diff --git a/app/src/main/java/org/pacien/tincapp/activities/StatusActivity.kt b/app/src/main/java/org/pacien/tincapp/activities/StatusActivity.kt
deleted file mode 100644
index 88ce222..0000000
--- a/app/src/main/java/org/pacien/tincapp/activities/StatusActivity.kt
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Tinc App, an Android binding and user interface for the tinc mesh VPN daemon
- * Copyright (C) 2017-2018 Pacien TRAN-GIRARD
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package org.pacien.tincapp.activities
-
-import android.content.Intent
-import android.os.Bundle
-import android.support.v4.widget.SwipeRefreshLayout
-import android.support.v7.app.AlertDialog
-import android.view.Menu
-import android.view.MenuItem
-import android.view.View
-import android.widget.AdapterView
-import android.widget.ArrayAdapter
-import android.widget.TextView
-import java8.util.concurrent.CompletableFuture
-import kotlinx.android.synthetic.main.base.*
-import kotlinx.android.synthetic.main.dialog_node_details.view.*
-import kotlinx.android.synthetic.main.fragment_list_view.*
-import kotlinx.android.synthetic.main.fragment_network_status_header.*
-import org.pacien.tincapp.R
-import org.pacien.tincapp.activities.common.ProgressModal
-import org.pacien.tincapp.commands.Executor
-import org.pacien.tincapp.commands.Tinc
-import org.pacien.tincapp.data.VpnInterfaceConfiguration
-import org.pacien.tincapp.extensions.Android.setElements
-import org.pacien.tincapp.extensions.Android.setText
-import org.pacien.tincapp.intent.Actions
-import org.pacien.tincapp.intent.BroadcastMapper
-import org.pacien.tincapp.service.TincVpnService
-import java.util.*
-import kotlin.concurrent.timerTask
-
-/**
- * @author pacien
- */
-class StatusActivity : BaseActivity(), AdapterView.OnItemClickListener, SwipeRefreshLayout.OnRefreshListener {
- private val broadcastMapper = BroadcastMapper(mapOf(Actions.EVENT_DISCONNECTED to this::onVpnShutdown))
- private var shutdownDialog: AlertDialog? = null
- private var nodeListAdapter: ArrayAdapter? = null
- private var refreshTimer: Timer? = null
- private var listNetworksAfterExit = true
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- nodeListAdapter = ArrayAdapter(this, R.layout.fragment_list_item)
-
- layoutInflater.inflate(R.layout.fragment_list_view, main_content)
- list_wrapper.setOnRefreshListener(this)
- list.addHeaderView(layoutInflater.inflate(R.layout.fragment_network_status_header, list, false), null, false)
- list.addFooterView(View(this), null, false)
- list.onItemClickListener = this
- list.adapter = nodeListAdapter
-
- if (intent.action == Actions.ACTION_DISCONNECT) {
- listNetworksAfterExit = false
- stopVpn()
- } else {
- listNetworksAfterExit = true
- }
- }
-
- override fun onCreateOptionsMenu(m: Menu): Boolean {
- menuInflater.inflate(R.menu.menu_status, m)
- return super.onCreateOptionsMenu(m)
- }
-
- override fun onDestroy() {
- super.onDestroy()
- nodeListAdapter = null
- refreshTimer = null
- }
-
- override fun onStart() {
- super.onStart()
- refreshTimer = Timer(true)
- refreshTimer?.schedule(timerTask { updateView() }, NOW, REFRESH_RATE)
- writeNetworkInfo(TincVpnService.getCurrentInterfaceCfg() ?: VpnInterfaceConfiguration())
- }
-
- override fun onStop() {
- refreshTimer?.cancel()
- super.onStop()
- }
-
- override fun onResume() {
- super.onResume()
- broadcastMapper.register()
- updateView()
- handleRecentCrash()
- }
-
- override fun onPause() {
- broadcastMapper.unregister()
- super.onPause()
- }
-
- override fun onRefresh() {
- refreshTimer?.schedule(timerTask { updateView() }, NOW)
- }
-
- override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) = when (view) {
- is TextView -> showNodeInfo(view.text.toString())
- else -> Unit
- }
-
- private fun onVpnShutdown() {
- shutdownDialog?.dismiss()
- if (listNetworksAfterExit) openStartActivity()
- finish()
- }
-
- fun stopVpn(@Suppress("UNUSED_PARAMETER") i: MenuItem? = null) {
- refreshTimer?.cancel()
- list_wrapper.isRefreshing = false
- shutdownDialog = ProgressModal.show(this, getString(R.string.message_disconnecting_vpn))
- TincVpnService.disconnect()
- }
-
- fun openLogViewer(@Suppress("UNUSED_PARAMETER") i: MenuItem) =
- startActivity(Intent(this, ViewLogActivity::class.java))
-
- private fun writeNetworkInfo(cfg: VpnInterfaceConfiguration) {
- text_network_name.text = TincVpnService.getCurrentNetName() ?: getString(R.string.value_none)
- text_network_ip_addresses.setText(cfg.addresses.map { it.toSlashSeparated() })
- text_network_routes.setText(cfg.routes.map { it.toSlashSeparated() })
- text_network_dns_servers.setText(cfg.dnsServers)
- text_network_search_domains.setText(cfg.searchDomains)
- text_network_allow_bypass.text = getString(if (cfg.allowBypass) R.string.value_yes else R.string.value_no)
- block_network_allowed_applications.visibility = if (cfg.allowedApplications.isNotEmpty()) View.VISIBLE else View.GONE
- text_network_allowed_applications.setText(cfg.allowedApplications)
- block_network_disallowed_applications.visibility = if (cfg.disallowedApplications.isNotEmpty()) View.VISIBLE else View.GONE
- text_network_disallowed_applications.setText(cfg.disallowedApplications)
- }
-
- private fun writeNodeList(nodeList: List) {
- nodeListAdapter?.setElements(nodeList)
- node_list_placeholder.visibility = View.GONE
- list_wrapper.isRefreshing = false
- }
-
- private fun updateNodeList() {
- getNodeNames().thenAccept { nodeList -> runOnUiThread { writeNodeList(nodeList) } }
- }
-
- private fun showNodeInfo(nodeName: String) {
- val dialogTextView = layoutInflater.inflate(R.layout.dialog_node_details, main_content, false)
-
- runOnUiThread {
- AlertDialog.Builder(this)
- .setTitle(R.string.title_node_info)
- .setView(dialogTextView)
- .setPositiveButton(R.string.action_close) { _, _ -> Unit }
- .show()
- }
-
- TincVpnService.getCurrentNetName()?.let { netName ->
- Tinc.info(netName, nodeName).thenAccept { nodeInfo ->
- runOnUiThread { dialogTextView.dialog_node_details.text = nodeInfo }
- }
- }
- }
-
- private fun updateView() = when {
- TincVpnService.isConnected() -> updateNodeList()
- else -> openStartActivity()
- }
-
- private fun openStartActivity() {
- startActivity(Intent(this, StartActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
- finish()
- }
-
- companion object {
- private const val REFRESH_RATE = 5000L
- private const val NOW = 0L
-
- fun getNodeNames(): CompletableFuture> = TincVpnService.getCurrentNetName()?.let { netName ->
- Tinc.dumpNodes(netName).thenApply> { list -> list.map { it.substringBefore(' ') } }
- } ?: Executor.supplyAsyncTask> { emptyList() }
- }
-}
diff --git a/app/src/main/java/org/pacien/tincapp/activities/status/NetworkInfoFragment.kt b/app/src/main/java/org/pacien/tincapp/activities/status/NetworkInfoFragment.kt
new file mode 100644
index 0000000..385f996
--- /dev/null
+++ b/app/src/main/java/org/pacien/tincapp/activities/status/NetworkInfoFragment.kt
@@ -0,0 +1,45 @@
+/*
+ * Tinc App, an Android binding and user interface for the tinc mesh VPN daemon
+ * Copyright (C) 2017-2018 Pacien TRAN-GIRARD
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.pacien.tincapp.activities.status
+
+import android.app.Fragment
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import org.pacien.tincapp.databinding.StatusNetworkInfoFragmentBinding
+import org.pacien.tincapp.service.TincVpnService
+
+/**
+ * @author pacien
+ */
+class NetworkInfoFragment : Fragment() {
+ private val vpnService by lazy { TincVpnService }
+ private val netName by lazy { vpnService.getCurrentNetName() }
+ private val interfaceConfiguration by lazy { vpnService.getCurrentInterfaceCfg() }
+ private val listFormatter = VpnInterfaceConfigurationFormatter
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ val binding = StatusNetworkInfoFragmentBinding.inflate(inflater, container, false)
+ binding.netName = netName
+ binding.vpnInterfaceConfiguration = interfaceConfiguration
+ binding.listFormatter = listFormatter
+ return binding.root
+ }
+}
diff --git a/app/src/main/java/org/pacien/tincapp/activities/status/StatusActivity.kt b/app/src/main/java/org/pacien/tincapp/activities/status/StatusActivity.kt
new file mode 100644
index 0000000..2bf42ce
--- /dev/null
+++ b/app/src/main/java/org/pacien/tincapp/activities/status/StatusActivity.kt
@@ -0,0 +1,184 @@
+/*
+ * Tinc App, an Android binding and user interface for the tinc mesh VPN daemon
+ * Copyright (C) 2017-2018 Pacien TRAN-GIRARD
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.pacien.tincapp.activities.status
+
+import android.content.Intent
+import android.os.Bundle
+import android.support.v4.widget.SwipeRefreshLayout
+import android.support.v7.app.AlertDialog
+import android.view.Menu
+import android.view.MenuItem
+import android.view.View
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import android.widget.TextView
+import java8.util.concurrent.CompletableFuture
+import kotlinx.android.synthetic.main.base.*
+import kotlinx.android.synthetic.main.fragment_list_view.*
+import kotlinx.android.synthetic.main.status_activity_list_header.*
+import kotlinx.android.synthetic.main.status_node_info_dialog.view.*
+import org.pacien.tincapp.R
+import org.pacien.tincapp.activities.BaseActivity
+import org.pacien.tincapp.activities.StartActivity
+import org.pacien.tincapp.activities.ViewLogActivity
+import org.pacien.tincapp.activities.common.ProgressModal
+import org.pacien.tincapp.commands.Executor
+import org.pacien.tincapp.commands.Tinc
+import org.pacien.tincapp.extensions.Android.setElements
+import org.pacien.tincapp.intent.Actions
+import org.pacien.tincapp.intent.BroadcastMapper
+import org.pacien.tincapp.service.TincVpnService
+import java.util.*
+import kotlin.concurrent.timerTask
+
+/**
+ * @author pacien
+ */
+class StatusActivity : BaseActivity(), AdapterView.OnItemClickListener, SwipeRefreshLayout.OnRefreshListener {
+ private val broadcastMapper = BroadcastMapper(mapOf(Actions.EVENT_DISCONNECTED to this::onVpnShutdown))
+ private var shutdownDialog: AlertDialog? = null
+ private var nodeListAdapter: ArrayAdapter? = null
+ private var refreshTimer: Timer? = null
+ private var listNetworksAfterExit = true
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ nodeListAdapter = ArrayAdapter(this, R.layout.fragment_list_item)
+
+ layoutInflater.inflate(R.layout.fragment_list_view, main_content)
+ list_wrapper.setOnRefreshListener(this)
+ list.addHeaderView(layoutInflater.inflate(R.layout.status_activity_list_header, list, false), null, false)
+ list.addFooterView(View(this), null, false)
+ list.onItemClickListener = this
+ list.adapter = nodeListAdapter
+
+ if (intent.action == Actions.ACTION_DISCONNECT) {
+ listNetworksAfterExit = false
+ stopVpn()
+ } else {
+ listNetworksAfterExit = true
+ }
+ }
+
+ override fun onCreateOptionsMenu(m: Menu): Boolean {
+ menuInflater.inflate(R.menu.menu_status, m)
+ return super.onCreateOptionsMenu(m)
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ nodeListAdapter = null
+ refreshTimer = null
+ }
+
+ override fun onStart() {
+ super.onStart()
+ refreshTimer = Timer(true)
+ refreshTimer?.schedule(timerTask { updateView() }, NOW, REFRESH_RATE)
+ }
+
+ override fun onStop() {
+ refreshTimer?.cancel()
+ super.onStop()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ broadcastMapper.register()
+ updateView()
+ handleRecentCrash()
+ }
+
+ override fun onPause() {
+ broadcastMapper.unregister()
+ super.onPause()
+ }
+
+ override fun onRefresh() {
+ refreshTimer?.schedule(timerTask { updateView() }, NOW)
+ }
+
+ override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) = when (view) {
+ is TextView -> showNodeInfo(view.text.toString())
+ else -> Unit
+ }
+
+ private fun onVpnShutdown() {
+ shutdownDialog?.dismiss()
+ if (listNetworksAfterExit) openStartActivity()
+ finish()
+ }
+
+ fun stopVpn(@Suppress("UNUSED_PARAMETER") i: MenuItem? = null) {
+ refreshTimer?.cancel()
+ list_wrapper.isRefreshing = false
+ shutdownDialog = ProgressModal.show(this, getString(R.string.message_disconnecting_vpn))
+ TincVpnService.disconnect()
+ }
+
+ fun openLogViewer(@Suppress("UNUSED_PARAMETER") i: MenuItem) =
+ startActivity(Intent(this, ViewLogActivity::class.java))
+
+ private fun writeNodeList(nodeList: List) {
+ nodeListAdapter?.setElements(nodeList)
+ status_activity_node_list_placeholder.visibility = View.GONE
+ list_wrapper.isRefreshing = false
+ }
+
+ private fun updateNodeList() {
+ getNodeNames().thenAccept { nodeList -> runOnUiThread { writeNodeList(nodeList) } }
+ }
+
+ private fun showNodeInfo(nodeName: String) {
+ val dialogTextView = layoutInflater.inflate(R.layout.status_node_info_dialog, main_content, false)
+
+ runOnUiThread {
+ AlertDialog.Builder(this)
+ .setTitle(R.string.status_node_info_dialog_title)
+ .setView(dialogTextView)
+ .setPositiveButton(R.string.status_node_info_dialog_close_action) { _, _ -> Unit }
+ .show()
+ }
+
+ TincVpnService.getCurrentNetName()?.let { netName ->
+ Tinc.info(netName, nodeName).thenAccept { nodeInfo ->
+ runOnUiThread { dialogTextView.dialog_node_details.text = nodeInfo }
+ }
+ }
+ }
+
+ private fun updateView() = when {
+ TincVpnService.isConnected() -> updateNodeList()
+ else -> openStartActivity()
+ }
+
+ private fun openStartActivity() {
+ startActivity(Intent(this, StartActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
+ finish()
+ }
+
+ companion object {
+ private const val REFRESH_RATE = 5000L
+ private const val NOW = 0L
+
+ fun getNodeNames(): CompletableFuture> = TincVpnService.getCurrentNetName()?.let { netName ->
+ Tinc.dumpNodes(netName).thenApply> { list -> list.map { it.substringBefore(' ') } }
+ } ?: Executor.supplyAsyncTask> { emptyList() }
+ }
+}
diff --git a/app/src/main/java/org/pacien/tincapp/activities/status/VpnInterfaceConfigurationFormatter.kt b/app/src/main/java/org/pacien/tincapp/activities/status/VpnInterfaceConfigurationFormatter.kt
new file mode 100644
index 0000000..0bcdff5
--- /dev/null
+++ b/app/src/main/java/org/pacien/tincapp/activities/status/VpnInterfaceConfigurationFormatter.kt
@@ -0,0 +1,41 @@
+/*
+ * Tinc App, an Android binding and user interface for the tinc mesh VPN daemon
+ * Copyright (C) 2017-2018 Pacien TRAN-GIRARD
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.pacien.tincapp.activities.status
+
+import org.pacien.tincapp.R
+import org.pacien.tincapp.context.App
+import org.pacien.tincapp.data.CidrAddress
+
+/**
+ * @author pacien
+ */
+object VpnInterfaceConfigurationFormatter {
+ private val resources by lazy { App.getResources() }
+
+ fun formatList(list: List) = when {
+ list.isNotEmpty() -> list.joinToString("\n", transform = this::formatListElement)
+ else -> resources.getString(R.string.status_network_info_none_value)!!
+ }
+
+ private fun formatListElement(element: Any) = when (element) {
+ is CidrAddress -> element.toSlashSeparated()
+ is String -> element
+ else -> element.toString()
+ }
+}
diff --git a/app/src/main/java/org/pacien/tincapp/extensions/Android.kt b/app/src/main/java/org/pacien/tincapp/extensions/Android.kt
index e954778..24a9c38 100644
--- a/app/src/main/java/org/pacien/tincapp/extensions/Android.kt
+++ b/app/src/main/java/org/pacien/tincapp/extensions/Android.kt
@@ -19,9 +19,6 @@
package org.pacien.tincapp.extensions
import android.widget.ArrayAdapter
-import android.widget.TextView
-import org.pacien.tincapp.R
-import org.pacien.tincapp.context.App
/**
* @author pacien
@@ -34,8 +31,4 @@ object Android {
notifyDataSetChanged()
setNotifyOnChange(true)
}
-
- fun TextView.setText(list: List) {
- text = if (list.isNotEmpty()) list.joinToString("\n") else App.getContext().getString(R.string.value_none)
- }
}
--
cgit v1.2.3