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