diff options
| author | Emīls <pinkisemils@mullvad.net> | 2020-02-11 17:25:27 +0000 |
|---|---|---|
| committer | Emīls <pinkisemils@mullvad.net> | 2020-02-11 17:25:27 +0000 |
| commit | 998932a4331310137d01991d6271b09c7c9c35e4 (patch) | |
| tree | 167d6d815af768eeb911245d23a121958c602ec5 /android/src | |
| parent | dc9f4c0c3178d61ef46d2ba784d1cefdd09626ed (diff) | |
| parent | 3b903818864a75971255b408baa01d6ee9686484 (diff) | |
| download | mullvadvpn-998932a4331310137d01991d6271b09c7c9c35e4.tar.xz mullvadvpn-998932a4331310137d01991d6271b09c7c9c35e4.zip | |
Merge branch 'android-add-account-history'
Diffstat (limited to 'android/src')
7 files changed, 131 insertions, 8 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt index e61567a0fe..a0dabf1a53 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt @@ -45,6 +45,10 @@ class MullvadDaemon(val vpnService: MullvadVpnService) { return getAccountData(daemonInterfaceAddress, accountToken) } + fun getAccountHistory(): ArrayList<String> { + return getAccountHistory(daemonInterfaceAddress) + } + fun getWwwAuthToken(): String { return getWwwAuthToken(daemonInterfaceAddress) } @@ -107,6 +111,7 @@ class MullvadDaemon(val vpnService: MullvadVpnService) { daemonInterfaceAddress: Long, accountToken: String ): GetAccountDataResult + private external fun getAccountHistory(daemonInterfaceAddress: Long): ArrayList<String> private external fun getWwwAuthToken(daemonInterfaceAddress: Long): String private external fun getCurrentLocation(daemonInterfaceAddress: Long): GeoIpLocation? private external fun getCurrentVersion(daemonInterfaceAddress: Long): String diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInput.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInput.kt index 9c8f71667f..0671e51b05 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInput.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInput.kt @@ -4,16 +4,22 @@ import android.content.res.Resources import android.text.Editable import android.text.TextWatcher import android.text.style.MetricAffectingSpan +import android.view.MotionEvent import android.view.View -import android.view.View.OnFocusChangeListener -import android.widget.EditText +import android.view.View.OnTouchListener +import android.widget.ArrayAdapter import android.widget.ImageButton +import android.widget.ListView +import android.widget.TextView import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.ui.AccountInputContainer.BorderState const val MIN_ACCOUNT_TOKEN_LENGTH = 10 -class AccountInput(val parentView: View, val resources: Resources) { +class AccountInput( + val parentView: View, + val resources: Resources +) { private val disabledBackgroundColor = resources.getColor(R.color.white20) private val disabledTextColor = resources.getColor(R.color.white) private val enabledBackgroundColor = resources.getColor(R.color.white) @@ -24,6 +30,9 @@ class AccountInput(val parentView: View, val resources: Resources) { set(value) { field = value updateBorder() + if (value == true) { + shouldShowAccountHistory = true + } } private var usingErrorColor = false set(value) { @@ -42,25 +51,49 @@ class AccountInput(val parentView: View, val resources: Resources) { } val container: AccountInputContainer = parentView.findViewById(R.id.account_input_container) - val input: EditText = parentView.findViewById(R.id.account_input) + val input: TextView = parentView.findViewById(R.id.account_input) val button: ImageButton = parentView.findViewById(R.id.login_button) + val accountHistoryList: ListView = parentView.findViewById(R.id.account_history_list) + + var accountHistory: ArrayList<String>? = null + set(value) { + synchronized(this) { + field = value + updateAccountHistory() + } + } + + private var shouldShowAccountHistory = false + set(value) { + synchronized(this) { + field = value + updateAccountHistory() + } + } var onLogin: ((String) -> Unit)? = null init { - button.setOnClickListener { onLogin?.invoke(input.text.toString()) } + button.setOnClickListener { + onLogin?.invoke(input.text.toString()) + } setButtonEnabled(false) input.apply { addTextChangedListener(InputWatcher()) - onFocusChangeListener = OnFocusChangeListener { view, hasFocus -> - inputHasFocus = hasFocus && view.isEnabled() - } + setOnTouchListener(OnTouchListener { + view, event -> + if (MotionEvent.ACTION_UP == event.getAction()) { + shouldShowAccountHistory = true + } + false + }) } container.apply { clipToOutline = true outlineProvider = AccountInputOutlineProvider(context) + setOnClickListener { shouldShowAccountHistory = true } } } @@ -85,12 +118,14 @@ class AccountInput(val parentView: View, val resources: Resources) { visibility = View.VISIBLE clearFocus() } + accountHistoryList.visibility = View.INVISIBLE } private fun successState() { setButtonEnabled(false) button.visibility = View.GONE input.visibility = View.GONE + container.visibility = View.GONE } private fun failureState() { @@ -117,6 +152,31 @@ class AccountInput(val parentView: View, val resources: Resources) { } } + private fun updateAccountHistory() { + accountHistory?.let { history -> + accountHistoryList.apply { + setAdapter(ArrayAdapter(context, + R.layout.account_history_entry, + R.id.account_history_entry_text_view, + history)) + + setOnItemClickListener { _, _, idx, _ -> + val accountNumber = history[idx] + + input.setText(accountNumber) + accountHistoryList.visibility = View.GONE + onLogin?.invoke(accountNumber) + } + } + + if (shouldShowAccountHistory && accountHistoryList.visibility != View.VISIBLE) { + accountHistoryList.visibility = View.VISIBLE + accountHistoryList.translationY = -accountHistoryList.height.toFloat() + accountHistoryList.animate().translationY(0.0F).setDuration(350).start() + } + } + } + private fun updateBorder() { if (usingErrorColor) { container.borderState = BorderState.ERROR diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt index 434584fb87..7b92118335 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt @@ -30,6 +30,7 @@ class LoginFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) { private var loginJob: Deferred<Boolean>? = null private var advanceToNextScreenJob: Job? = null + private var fetchHistoryJob: Job? = null override fun onSafelyCreateView( inflater: LayoutInflater, @@ -51,6 +52,8 @@ class LoginFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) { view.findViewById<View>(R.id.create_account).setOnClickListener { createAccount() } + fetchHistory() + return view } @@ -59,10 +62,12 @@ class LoginFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) { loggedIn.join() openConnectScreen() } + fetchHistory() } override fun onSafelyPause() { advanceToNextScreenJob?.cancel() + fetchHistoryJob?.cancel() } private fun createAccount() { @@ -85,6 +90,16 @@ class LoginFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) { performLogin(accountToken) } + private fun fetchHistory() { + fetchHistoryJob?.cancel() + fetchHistoryJob = GlobalScope.launch(Dispatchers.Main) { + val history = GlobalScope.async(Dispatchers.Default) { + daemon.getAccountHistory() + } + accountInput.accountHistory = history.await() + } + } + private fun performLogin(accountToken: String) = GlobalScope.launch(Dispatchers.Main) { loginJob?.cancel() loginJob = GlobalScope.async(Dispatchers.Default) { diff --git a/android/src/main/res/drawable/account_history_background.xml b/android/src/main/res/drawable/account_history_background.xml new file mode 100644 index 0000000000..b71d15464f --- /dev/null +++ b/android/src/main/res/drawable/account_history_background.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item> + <shape xmlns:android="http://schemas.android.com/apk/res/android"> + <corners android:radius="@dimen/account_input_corner_radius" /> + <solid android:color="@color/darkBlue" /> + </shape> + </item> + <item android:top="0dp" android:right="1dp" android:bottom="1dp" + android:left="1dp"> + <shape xmlns:android="http://schemas.android.com/apk/res/android"> + <corners android:radius="@dimen/account_input_corner_radius" /> + <solid android:color="@color/white" /> + </shape> + </item> +</layer-list> diff --git a/android/src/main/res/drawable/account_history_list_divider.xml b/android/src/main/res/drawable/account_history_list_divider.xml new file mode 100644 index 0000000000..d3b31cc0c3 --- /dev/null +++ b/android/src/main/res/drawable/account_history_list_divider.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> +<solid android:color="@color/darkBlue" /> +</shape> diff --git a/android/src/main/res/layout/account_history_entry.xml b/android/src/main/res/layout/account_history_entry.xml new file mode 100644 index 0000000000..f1d0b67bde --- /dev/null +++ b/android/src/main/res/layout/account_history_entry.xml @@ -0,0 +1,13 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <TextView android:id="@+id/account_history_entry_text_view" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:textColor="@color/blue" + android:padding="10dip" + android:textSize="16dip" + android:textStyle="bold"/> +</LinearLayout> diff --git a/android/src/main/res/layout/login.xml b/android/src/main/res/layout/login.xml index b0a53d87d6..46e844d5c6 100644 --- a/android/src/main/res/layout/login.xml +++ b/android/src/main/res/layout/login.xml @@ -138,6 +138,15 @@ android:src="@drawable/login_button_arrow" /> </net.mullvad.mullvadvpn.ui.AccountInputContainer> + + <ListView android:id="@+id/account_history_list" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:divider="@drawable/account_history_list_divider" + android:dividerHeight="1dp" + android:visibility="invisible" + android:background="@drawable/account_history_background" + /> <Space android:layout_width="match_parent" android:layout_height="0dp" |
