From b5884b3ad4964d6bdbbb92c160bed84cdbb059a1 Mon Sep 17 00:00:00 2001
From: pacien
Date: Mon, 20 Aug 2018 00:53:22 +0200
Subject: Split status activity into tabs
Refactoring the underlying code to use lifecycle-aware classes
---
.../org/pacien/tincapp/activities/StartActivity.kt | 2 +-
.../activities/status/NetworkInfoFragment.kt | 43 -------
.../tincapp/activities/status/StatusActivity.kt | 124 ++++-----------------
.../status/StatusFragmentPagerAdapter.kt | 41 +++++++
.../status/VpnInterfaceConfigurationFormatter.kt | 41 -------
.../status/networkinfo/NetworkInfoFragment.kt | 43 +++++++
.../VpnInterfaceConfigurationFormatter.kt | 41 +++++++
.../activities/status/nodes/NodeListFragment.kt | 89 +++++++++++++++
.../activities/status/nodes/NodeListLiveData.kt | 47 ++++++++
.../activities/status/nodes/NodeListViewModel.kt | 30 +++++
.../java/org/pacien/tincapp/extensions/Android.kt | 34 ------
.../tincapp/extensions/ListViewExtensions.kt | 47 ++++++++
12 files changed, 360 insertions(+), 222 deletions(-)
delete 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/StatusFragmentPagerAdapter.kt
delete mode 100644 app/src/main/java/org/pacien/tincapp/activities/status/VpnInterfaceConfigurationFormatter.kt
create mode 100644 app/src/main/java/org/pacien/tincapp/activities/status/networkinfo/NetworkInfoFragment.kt
create mode 100644 app/src/main/java/org/pacien/tincapp/activities/status/networkinfo/VpnInterfaceConfigurationFormatter.kt
create mode 100644 app/src/main/java/org/pacien/tincapp/activities/status/nodes/NodeListFragment.kt
create mode 100644 app/src/main/java/org/pacien/tincapp/activities/status/nodes/NodeListLiveData.kt
create mode 100644 app/src/main/java/org/pacien/tincapp/activities/status/nodes/NodeListViewModel.kt
delete mode 100644 app/src/main/java/org/pacien/tincapp/extensions/Android.kt
create mode 100644 app/src/main/java/org/pacien/tincapp/extensions/ListViewExtensions.kt
(limited to 'app/src/main/java/org')
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 84adc7f..7023316 100644
--- a/app/src/main/java/org/pacien/tincapp/activities/StartActivity.kt
+++ b/app/src/main/java/org/pacien/tincapp/activities/StartActivity.kt
@@ -39,7 +39,7 @@ 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.extensions.setElements
import org.pacien.tincapp.intent.Actions
import org.pacien.tincapp.intent.BroadcastMapper
import org.pacien.tincapp.service.TincVpnService
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
deleted file mode 100644
index de6f741..0000000
--- a/app/src/main/java/org/pacien/tincapp/activities/status/NetworkInfoFragment.kt
+++ /dev/null
@@ -1,43 +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.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 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.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
index e5ca307..1ac0e54 100644
--- a/app/src/main/java/org/pacien/tincapp/activities/status/StatusActivity.kt
+++ b/app/src/main/java/org/pacien/tincapp/activities/status/StatusActivity.kt
@@ -20,63 +20,36 @@ 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 kotlinx.android.synthetic.main.status_activity.*
import org.pacien.tincapp.R
import org.pacien.tincapp.activities.BaseActivity
import org.pacien.tincapp.activities.StartActivity
import org.pacien.tincapp.activities.common.ProgressModal
import org.pacien.tincapp.activities.viewlog.ViewLogActivity
-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 {
+class StatusActivity : BaseActivity() {
private val vpnService by lazy { TincVpnService }
private val netName by lazy { vpnService.getCurrentNetName() }
+ private val pagerAdapter by lazy { StatusFragmentPagerAdapter(supportFragmentManager) }
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)
+ setContentView(R.layout.status_activity)
+ status_activity_pager.adapter = pagerAdapter
supportActionBar.subtitle = getString(R.string.status_activity_state_connected_to_format, netName)
- 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
- }
+ handleStartIntentAction(intent.action)
}
override fun onCreateOptionsMenu(m: Menu): Boolean {
@@ -84,27 +57,11 @@ class StatusActivity : BaseActivity(), AdapterView.OnItemClickListener, SwipeRef
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()
+ if (!TincVpnService.isConnected()) openStartActivity()
+
broadcastMapper.register()
- updateView()
handleRecentCrash()
}
@@ -113,75 +70,36 @@ class StatusActivity : BaseActivity(), AdapterView.OnItemClickListener, SwipeRef
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()
- }
+ @Suppress("UNUSED_PARAMETER")
+ fun stopVpn(m: MenuItem) =
+ stopVpn()
- fun openLogViewer(@Suppress("UNUSED_PARAMETER") i: MenuItem) =
+ @Suppress("UNUSED_PARAMETER")
+ fun openLogViewer(m: 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()
+ private fun handleStartIntentAction(intentAction: String?) = when (intentAction) {
+ Actions.ACTION_DISCONNECT -> {
+ listNetworksAfterExit = false
+ stopVpn()
}
- TincVpnService.getCurrentNetName()?.let { netName ->
- Tinc.info(netName, nodeName).thenAccept { nodeInfo ->
- runOnUiThread { dialogTextView.dialog_node_details.text = nodeInfo }
- }
- }
+ else -> listNetworksAfterExit = true
}
- private fun updateView() = when {
- TincVpnService.isConnected() -> updateNodeList()
- else -> openStartActivity()
+ private fun stopVpn() {
+ shutdownDialog = ProgressModal.show(this, getString(R.string.message_disconnecting_vpn))
+ vpnService.disconnect()
}
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/StatusFragmentPagerAdapter.kt b/app/src/main/java/org/pacien/tincapp/activities/status/StatusFragmentPagerAdapter.kt
new file mode 100644
index 0000000..d44ac5c
--- /dev/null
+++ b/app/src/main/java/org/pacien/tincapp/activities/status/StatusFragmentPagerAdapter.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 android.support.v4.app.FragmentManager
+import android.support.v4.app.FragmentPagerAdapter
+import org.pacien.tincapp.R
+import org.pacien.tincapp.activities.status.networkinfo.NetworkInfoFragment
+import org.pacien.tincapp.activities.status.nodes.NodeListFragment
+import org.pacien.tincapp.context.App
+
+/**
+ * @author pacien
+ */
+class StatusFragmentPagerAdapter(fragmentManager: FragmentManager) : FragmentPagerAdapter(fragmentManager) {
+ private val resources by lazy { App.getResources() }
+ private val pages = listOf(
+ R.string.status_activity_title_network_info to NetworkInfoFragment(),
+ R.string.status_activity_title_node_list to NodeListFragment()
+ )
+
+ override fun getPageTitle(position: Int) = resources.getString(pages[position].first)!!
+ override fun getItem(position: Int) = pages[position].second
+ override fun getCount() = pages.size
+}
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
deleted file mode 100644
index 0bcdff5..0000000
--- a/app/src/main/java/org/pacien/tincapp/activities/status/VpnInterfaceConfigurationFormatter.kt
+++ /dev/null
@@ -1,41 +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.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/activities/status/networkinfo/NetworkInfoFragment.kt b/app/src/main/java/org/pacien/tincapp/activities/status/networkinfo/NetworkInfoFragment.kt
new file mode 100644
index 0000000..5aa37a8
--- /dev/null
+++ b/app/src/main/java/org/pacien/tincapp/activities/status/networkinfo/NetworkInfoFragment.kt
@@ -0,0 +1,43 @@
+/*
+ * 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.networkinfo
+
+import android.os.Bundle
+import android.support.v4.app.Fragment
+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 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.vpnInterfaceConfiguration = interfaceConfiguration
+ binding.listFormatter = listFormatter
+ return binding.root
+ }
+}
diff --git a/app/src/main/java/org/pacien/tincapp/activities/status/networkinfo/VpnInterfaceConfigurationFormatter.kt b/app/src/main/java/org/pacien/tincapp/activities/status/networkinfo/VpnInterfaceConfigurationFormatter.kt
new file mode 100644
index 0000000..a519d07
--- /dev/null
+++ b/app/src/main/java/org/pacien/tincapp/activities/status/networkinfo/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.networkinfo
+
+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/activities/status/nodes/NodeListFragment.kt b/app/src/main/java/org/pacien/tincapp/activities/status/nodes/NodeListFragment.kt
new file mode 100644
index 0000000..1cfc0f5
--- /dev/null
+++ b/app/src/main/java/org/pacien/tincapp/activities/status/nodes/NodeListFragment.kt
@@ -0,0 +1,89 @@
+/*
+ * 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.nodes
+
+import android.arch.lifecycle.Observer
+import android.arch.lifecycle.ViewModelProviders
+import android.os.Bundle
+import android.support.v4.app.Fragment
+import android.support.v7.app.AlertDialog
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import android.widget.TextView
+import kotlinx.android.synthetic.main.base.*
+import kotlinx.android.synthetic.main.status_node_info_dialog.view.*
+import kotlinx.android.synthetic.main.status_node_list.*
+import org.pacien.tincapp.R
+import org.pacien.tincapp.commands.Tinc
+import org.pacien.tincapp.extensions.hideBottomSeparator
+import org.pacien.tincapp.extensions.hideTopSeparator
+import org.pacien.tincapp.extensions.setElements
+import org.pacien.tincapp.service.TincVpnService
+
+/**
+ * @author pacien
+ */
+class NodeListFragment : Fragment() {
+ private val vpnService = TincVpnService
+ private val tincCtl = Tinc
+ private val netName by lazy { vpnService.getCurrentNetName()!! }
+ private val nodeListViewModel by lazy { ViewModelProviders.of(this).get(NodeListViewModel::class.java) }
+ private val nodeListAdapter by lazy { ArrayAdapter(context, R.layout.fragment_list_item) }
+ private val nodeListObserver by lazy { Observer> { nodeListAdapter.setElements(it) } }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ nodeListViewModel.nodeList.observe(this, nodeListObserver)
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ return inflater.inflate(R.layout.status_node_list, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ status_node_list.hideTopSeparator()
+ status_node_list.hideBottomSeparator()
+ status_node_list.emptyView = status_node_list_placeholder
+ status_node_list.onItemClickListener = AdapterView.OnItemClickListener(this::onItemClick)
+ status_node_list.adapter = nodeListAdapter
+ }
+
+ @Suppress("UNUSED_PARAMETER")
+ private fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) = when (view) {
+ is TextView -> showNodeInfo(view.text.toString())
+ else -> Unit
+ }
+
+ private fun showNodeInfo(nodeName: String) {
+ val dialogTextView = layoutInflater.inflate(R.layout.status_node_info_dialog, main_content, false)
+
+ AlertDialog.Builder(context!!)
+ .setTitle(R.string.status_node_info_dialog_title)
+ .setView(dialogTextView)
+ .setPositiveButton(R.string.status_node_info_dialog_close_action) { _, _ -> Unit }
+ .show()
+
+ tincCtl.info(netName, nodeName).thenAccept { nodeInfo ->
+ view?.post { dialogTextView.dialog_node_details.text = nodeInfo }
+ }
+ }
+}
diff --git a/app/src/main/java/org/pacien/tincapp/activities/status/nodes/NodeListLiveData.kt b/app/src/main/java/org/pacien/tincapp/activities/status/nodes/NodeListLiveData.kt
new file mode 100644
index 0000000..cdbdf0a
--- /dev/null
+++ b/app/src/main/java/org/pacien/tincapp/activities/status/nodes/NodeListLiveData.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.nodes
+
+import android.arch.lifecycle.LiveData
+import org.pacien.tincapp.commands.Tinc
+import java.util.*
+import kotlin.concurrent.timer
+
+/**
+ * @author pacien
+ */
+class NodeListLiveData(private val netName: String) : LiveData>() {
+ private val updateInterval = 2 * 1000L // in milliseconds
+ private val tincCtl = Tinc
+ private lateinit var updateTimer: Timer
+
+ override fun onActive() {
+ updateTimer = timer(period = updateInterval, action = { updateNodeList() })
+ }
+
+ override fun onInactive() {
+ updateTimer.apply { cancel() }.apply { purge() }
+ }
+
+ private fun updateNodeList() {
+ tincCtl.dumpNodes(netName)
+ .thenApply { list -> list.map { it.substringBefore(' ')} }
+ .thenAccept(this::postValue)
+ }
+}
diff --git a/app/src/main/java/org/pacien/tincapp/activities/status/nodes/NodeListViewModel.kt b/app/src/main/java/org/pacien/tincapp/activities/status/nodes/NodeListViewModel.kt
new file mode 100644
index 0000000..560f62a
--- /dev/null
+++ b/app/src/main/java/org/pacien/tincapp/activities/status/nodes/NodeListViewModel.kt
@@ -0,0 +1,30 @@
+/*
+ * 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.nodes
+
+import android.arch.lifecycle.ViewModel
+import org.pacien.tincapp.service.TincVpnService
+
+/**
+ * @author pacien
+ */
+class NodeListViewModel : ViewModel() {
+ private val netName by lazy { TincVpnService.getCurrentNetName()!! }
+ val nodeList by lazy { NodeListLiveData(netName) }
+}
diff --git a/app/src/main/java/org/pacien/tincapp/extensions/Android.kt b/app/src/main/java/org/pacien/tincapp/extensions/Android.kt
deleted file mode 100644
index 24a9c38..0000000
--- a/app/src/main/java/org/pacien/tincapp/extensions/Android.kt
+++ /dev/null
@@ -1,34 +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.extensions
-
-import android.widget.ArrayAdapter
-
-/**
- * @author pacien
- */
-object Android {
- fun ArrayAdapter.setElements(elements: Collection) {
- setNotifyOnChange(false)
- clear()
- addAll(elements)
- notifyDataSetChanged()
- setNotifyOnChange(true)
- }
-}
diff --git a/app/src/main/java/org/pacien/tincapp/extensions/ListViewExtensions.kt b/app/src/main/java/org/pacien/tincapp/extensions/ListViewExtensions.kt
new file mode 100644
index 0000000..3957fa5
--- /dev/null
+++ b/app/src/main/java/org/pacien/tincapp/extensions/ListViewExtensions.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.extensions
+
+import android.view.View
+import android.widget.ArrayAdapter
+import android.widget.ListView
+
+/**
+ * @author pacien
+ */
+
+fun ArrayAdapter.setElements(elements: Collection?) {
+ if (elements == null) return
+
+ synchronized(this) {
+ setNotifyOnChange(false)
+ clear()
+ addAll(elements)
+ notifyDataSetChanged()
+ setNotifyOnChange(true)
+ }
+}
+
+fun ListView.hideTopSeparator() {
+ addHeaderView(View(context), null, false)
+}
+
+fun ListView.hideBottomSeparator() {
+ addFooterView(View(context), null, false)
+}
--
cgit v1.2.3