aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/org/pacien/tincapp/activities/StartActivity.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/org/pacien/tincapp/activities/StartActivity.kt')
-rw-r--r--app/src/main/java/org/pacien/tincapp/activities/StartActivity.kt152
1 files changed, 119 insertions, 33 deletions
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 719bbc1..9fa5e44 100644
--- a/app/src/main/java/org/pacien/tincapp/activities/StartActivity.kt
+++ b/app/src/main/java/org/pacien/tincapp/activities/StartActivity.kt
@@ -1,8 +1,13 @@
1package org.pacien.tincapp.activities 1package org.pacien.tincapp.activities
2 2
3import android.app.Activity
4import android.app.ProgressDialog
3import android.content.Intent 5import android.content.Intent
6import android.content.IntentFilter
7import android.net.VpnService
4import android.os.Bundle 8import android.os.Bundle
5import android.support.v4.widget.SwipeRefreshLayout 9import android.support.v4.widget.SwipeRefreshLayout
10import android.support.v7.app.AlertDialog
6import android.view.Menu 11import android.view.Menu
7import android.view.MenuItem 12import android.view.MenuItem
8import android.view.View 13import android.view.View
@@ -10,29 +15,117 @@ import android.widget.AdapterView
10import android.widget.ArrayAdapter 15import android.widget.ArrayAdapter
11import android.widget.TextView 16import android.widget.TextView
12import kotlinx.android.synthetic.main.base.* 17import kotlinx.android.synthetic.main.base.*
18import kotlinx.android.synthetic.main.dialog_decrypt_keys.view.*
13import kotlinx.android.synthetic.main.fragment_list_view.* 19import kotlinx.android.synthetic.main.fragment_list_view.*
14import kotlinx.android.synthetic.main.fragment_network_list_header.* 20import kotlinx.android.synthetic.main.fragment_network_list_header.*
15import org.pacien.tincapp.R 21import org.pacien.tincapp.R
16import org.pacien.tincapp.context.AppPaths 22import org.pacien.tincapp.context.AppPaths
17import org.pacien.tincapp.extensions.Android.setElements 23import org.pacien.tincapp.extensions.Android.setElements
24import org.pacien.tincapp.intent.Actions
25import org.pacien.tincapp.intent.SimpleBroadcastReceiver
18import org.pacien.tincapp.service.TincVpnService 26import org.pacien.tincapp.service.TincVpnService
27import org.pacien.tincapp.utils.TincKeyring
19 28
20/** 29/**
21 * @author pacien 30 * @author pacien
22 */ 31 */
23class StartActivity : BaseActivity(), AdapterView.OnItemClickListener, SwipeRefreshLayout.OnRefreshListener { 32class StartActivity : BaseActivity() {
33 companion object {
34 private const val PERMISSION_REQUEST = 0
35 }
36
37 private val networkList = object : AdapterView.OnItemClickListener, SwipeRefreshLayout.OnRefreshListener {
38 private var networkListAdapter: ArrayAdapter<String>? = null
39
40 fun init() {
41 networkListAdapter = ArrayAdapter(this@StartActivity, R.layout.fragment_list_item)
42 layoutInflater.inflate(R.layout.fragment_list_view, main_content)
43 list_wrapper.setOnRefreshListener(this)
44 list.addHeaderView(layoutInflater.inflate(R.layout.fragment_network_list_header, list, false), null, false)
45 list.addFooterView(View(this@StartActivity), null, false)
46 list.adapter = networkListAdapter
47 list.onItemClickListener = this
48 }
49
50 fun destroy() {
51 networkListAdapter = null
52 }
53
54 override fun onRefresh() {
55 val networks = AppPaths.confDir()?.list()?.toList() ?: emptyList()
56 runOnUiThread {
57 networkListAdapter?.setElements(networks)
58 setPlaceholderVisibility()
59 list_wrapper.isRefreshing = false
60 }
61 }
62
63 override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
64 connectionStarter.tryStart(netName = (view as TextView).text.toString(), displayStatus = true)
65 }
66
67 private fun setPlaceholderVisibility() = if (networkListAdapter?.isEmpty != false) {
68 network_list_placeholder.text = getListPlaceholderText()
69 network_list_placeholder.visibility = View.VISIBLE
70 } else {
71 network_list_placeholder.visibility = View.GONE
72 }
73
74 private fun getListPlaceholderText() = if (!AppPaths.storageAvailable()) {
75 getText(R.string.message_storage_unavailable)
76 } else {
77 getText(R.string.message_no_network_configuration_found)
78 }
79 }
80
81 private val connectionStarter = object {
82 private var netName: String? = null
83 private var passphrase: String? = null
84 private var displayStatus = false
85
86 fun displayStatus() = displayStatus
24 87
25 private var networkListAdapter: ArrayAdapter<String>? = null 88 fun tryStart(netName: String? = null, passphrase: String? = null, displayStatus: Boolean? = null) {
89 if (netName != null) this.netName = netName
90 if (passphrase != null) this.passphrase = passphrase
91 if (displayStatus != null) this.displayStatus = displayStatus
92
93 val permissionRequestIntent = VpnService.prepare(this@StartActivity)
94 if (permissionRequestIntent != null)
95 return startActivityForResult(permissionRequestIntent, PERMISSION_REQUEST)
96
97 if (TincKeyring.needsPassphrase(this.netName!!) && this.passphrase == null)
98 return askForPassphrase()
99
100 startVpn(this.netName!!, this.passphrase)
101 }
102
103 private fun askForPassphrase() {
104 layoutInflater.inflate(R.layout.dialog_decrypt_keys, main_content, false).let { dialog ->
105 AlertDialog.Builder(this@StartActivity)
106 .setTitle(R.string.title_unlock_private_keys).setView(dialog)
107 .setPositiveButton(R.string.action_unlock) { _, _ -> tryStart(passphrase = dialog.passphrase.text.toString()) }
108 .setNegativeButton(R.string.action_cancel, { _, _ -> Unit })
109 .show()
110 }
111 }
112
113 private fun startVpn(netName: String, passphrase: String? = null) {
114 connectDialog = showProgressDialog(R.string.message_starting_vpn)
115 TincVpnService.connect(netName, passphrase)
116 }
117 }
118
119 private val startupBroadcastReceiver = SimpleBroadcastReceiver(IntentFilter(Actions.EVENT_CONNECTED), this::onVpnStart)
120
121 private var connectDialog: ProgressDialog? = null
26 122
27 override fun onCreate(savedInstanceState: Bundle?) { 123 override fun onCreate(savedInstanceState: Bundle?) {
28 super.onCreate(savedInstanceState) 124 super.onCreate(savedInstanceState)
29 networkListAdapter = ArrayAdapter(this, R.layout.fragment_list_item) 125 networkList.init()
30 layoutInflater.inflate(R.layout.fragment_list_view, main_content) 126
31 list_wrapper.setOnRefreshListener(this) 127 if (intent.action == Actions.ACTION_CONNECT && intent.data?.schemeSpecificPart != null)
32 list.addHeaderView(layoutInflater.inflate(R.layout.fragment_network_list_header, list, false), null, false) 128 connectionStarter.tryStart(intent.data.schemeSpecificPart, intent.data.fragment, false)
33 list.addFooterView(View(this), null, false)
34 list.adapter = networkListAdapter
35 list.onItemClickListener = this
36 } 129 }
37 130
38 override fun onCreateOptionsMenu(m: Menu): Boolean { 131 override fun onCreateOptionsMenu(m: Menu): Boolean {
@@ -41,48 +134,41 @@ class StartActivity : BaseActivity(), AdapterView.OnItemClickListener, SwipeRefr
41 } 134 }
42 135
43 override fun onDestroy() { 136 override fun onDestroy() {
44 networkListAdapter = null 137 networkList.destroy()
138 connectDialog?.dismiss()
45 super.onDestroy() 139 super.onDestroy()
46 } 140 }
47 141
48 override fun onStart() { 142 override fun onStart() {
49 super.onStart() 143 super.onStart()
50 onRefresh() 144 networkList.onRefresh()
51 } 145 }
52 146
53 override fun onResume() { 147 override fun onResume() {
54 super.onResume() 148 super.onResume()
55 if (TincVpnService.isConnected()) openStatusActivity() 149 if (TincVpnService.isConnected()) openStatusActivity()
150 startupBroadcastReceiver.register()
56 } 151 }
57 152
58 override fun onRefresh() { 153 override fun onPause() {
59 val networks = AppPaths.confDir()?.list()?.toList() ?: emptyList() 154 startupBroadcastReceiver.unregister()
60 runOnUiThread { 155 super.onPause()
61 networkListAdapter?.setElements(networks)
62 setPlaceholderVisibility()
63 list_wrapper.isRefreshing = false
64 }
65 } 156 }
66 157
67 override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) = 158 override fun onActivityResult(request: Int, result: Int, data: Intent?): Unit = when (request) {
68 LaunchActivity.connect((view as TextView).text.toString()) 159 PERMISSION_REQUEST -> if (result == Activity.RESULT_OK) connectionStarter.tryStart() else Unit
160 else -> throw IllegalArgumentException("Result for unknown request received.")
161 }
69 162
70 fun openConfigureActivity(@Suppress("UNUSE