summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-03-15 16:20:36 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-03-15 16:20:36 -0300
commita34fc0c996adb86b8ada4bf734e95b9487136142 (patch)
treee8f04bee0b72b46d99ba238b33e08a82d0e0836f /android
parentd8c4ed04242cdc07fbed1a6b6c0d242d86bcc8ec (diff)
parent9f79c2e3a35ad0c44b300ca50a27feb19464e8d0 (diff)
downloadmullvadvpn-a34fc0c996adb86b8ada4bf734e95b9487136142.tar.xz
mullvadvpn-a34fc0c996adb86b8ada4bf734e95b9487136142.zip
Merge branch 'android-connect-screen'
Diffstat (limited to 'android')
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectActionButton.kt50
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt70
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionState.kt7
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionStatus.kt46
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/HeaderBar.kt30
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/LoginFragment.kt9
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/NotificationBanner.kt18
-rw-r--r--android/src/main/res/drawable/green_button_background.xml16
-rw-r--r--android/src/main/res/drawable/icon_chevron.xml14
-rw-r--r--android/src/main/res/drawable/icon_notification_error.xml8
-rw-r--r--android/src/main/res/drawable/transparent_red_button_background.xml16
-rw-r--r--android/src/main/res/drawable/white20_button_background.xml16
-rw-r--r--android/src/main/res/layout/connect.xml151
-rw-r--r--android/src/main/res/values/colors.xml4
-rw-r--r--android/src/main/res/values/strings.xml10
-rw-r--r--android/src/main/res/values/styles.xml17
16 files changed, 482 insertions, 0 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectActionButton.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectActionButton.kt
new file mode 100644
index 0000000000..4a577cd337
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectActionButton.kt
@@ -0,0 +1,50 @@
+package net.mullvad.mullvadvpn
+
+import android.view.View
+import android.widget.Button
+
+class ConnectActionButton(val parentView: View) {
+ private val button: Button = parentView.findViewById(R.id.action_button)
+
+ var state = ConnectionState.Disconnected
+ set(value) {
+ when (value) {
+ ConnectionState.Disconnected -> disconnected()
+ ConnectionState.Connecting -> connecting()
+ ConnectionState.Connected -> connected()
+ }
+
+ field = value
+ }
+
+ var onConnect: (() -> Unit)? = null
+ var onCancel: (() -> Unit)? = null
+ var onDisconnect: (() -> Unit)? = null
+
+ init {
+ button.setOnClickListener { action() }
+ }
+
+ private fun action() {
+ when (state) {
+ ConnectionState.Disconnected -> onConnect?.invoke()
+ ConnectionState.Connecting -> onCancel?.invoke()
+ ConnectionState.Connected -> onDisconnect?.invoke()
+ }
+ }
+
+ private fun disconnected() {
+ button.setBackgroundResource(R.drawable.green_button_background)
+ button.setText(R.string.connect)
+ }
+
+ private fun connecting() {
+ button.setBackgroundResource(R.drawable.transparent_red_button_background)
+ button.setText(R.string.cancel)
+ }
+
+ private fun connected() {
+ button.setBackgroundResource(R.drawable.transparent_red_button_background)
+ button.setText(R.string.disconnect)
+ }
+}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt
new file mode 100644
index 0000000000..c38321dfc9
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt
@@ -0,0 +1,70 @@
+package net.mullvad.mullvadvpn
+
+import android.os.Bundle
+import android.os.Handler
+import android.support.v4.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+
+class ConnectFragment : Fragment() {
+ private lateinit var actionButton: ConnectActionButton
+ private lateinit var headerBar: HeaderBar
+ private lateinit var notificationBanner: NotificationBanner
+ private lateinit var status: ConnectionStatus
+
+ private lateinit var connectHandler: Handler
+
+ private var state = ConnectionState.Disconnected
+ set(value) {
+ actionButton.state = value
+ headerBar.state = value
+ notificationBanner.state = value
+ status.state = value
+
+ field = value
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ connectHandler = Handler()
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ val view = inflater.inflate(R.layout.connect, container, false)
+
+ headerBar = HeaderBar(view, context!!)
+ notificationBanner = NotificationBanner(view)
+ status = ConnectionStatus(view, context!!)
+
+ actionButton = ConnectActionButton(view)
+ actionButton.apply {
+ onConnect = { connect() }
+ onCancel = { disconnect() }
+ onDisconnect = { disconnect() }
+ }
+
+ return view
+ }
+
+ private fun connect() {
+ state = ConnectionState.Connecting
+
+ connectHandler.postDelayed(Runnable { connected() }, 1000)
+ }
+
+ private fun disconnect() {
+ state = ConnectionState.Disconnected
+
+ connectHandler.removeCallbacksAndMessages(null)
+ }
+
+ private fun connected() {
+ state = ConnectionState.Connected
+ }
+}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionState.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionState.kt
new file mode 100644
index 0000000000..4764ce05fe
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionState.kt
@@ -0,0 +1,7 @@
+package net.mullvad.mullvadvpn
+
+enum class ConnectionState {
+ Disconnected,
+ Connecting,
+ Connected,
+}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionStatus.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionStatus.kt
new file mode 100644
index 0000000000..8090a8dd08
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionStatus.kt
@@ -0,0 +1,46 @@
+package net.mullvad.mullvadvpn
+
+import android.content.Context
+import android.view.View
+import android.widget.TextView
+
+class ConnectionStatus(val parentView: View, val context: Context) {
+ private val spinner: View = parentView.findViewById(R.id.connecting_spinner)
+ private val text: TextView = parentView.findViewById(R.id.connection_status)
+
+ private val disconnectedTextColor = context.getColor(R.color.red)
+ private val connectingTextColor = context.getColor(R.color.white)
+ private val connectedTextColor = context.getColor(R.color.green)
+
+ var state = ConnectionState.Disconnected
+ set(value) {
+ when (value) {
+ ConnectionState.Disconnected -> disconnected()
+ ConnectionState.Connecting -> connecting()
+ ConnectionState.Connected -> connected()
+ }
+
+ field = value
+ }
+
+ private fun disconnected() {
+ spinner.visibility = View.GONE
+
+ text.setTextColor(disconnectedTextColor)
+ text.setText(R.string.creating_secure_connection)
+ }
+
+ private fun connecting() {
+ spinner.visibility = View.VISIBLE
+
+ text.setTextColor(connectingTextColor)
+ text.setText(R.string.unsecured_connection)
+ }
+
+ private fun connected() {
+ spinner.visibility = View.GONE
+
+ text.setTextColor(connectedTextColor)
+ text.setText(R.string.secure_connection)
+ }
+}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/HeaderBar.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/HeaderBar.kt
new file mode 100644
index 0000000000..4c46174f51
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/HeaderBar.kt
@@ -0,0 +1,30 @@
+package net.mullvad.mullvadvpn
+
+import android.content.Context
+import android.view.View
+
+class HeaderBar(val parentView: View, val context: Context) {
+ private val headerBar: View = parentView.findViewById(R.id.header_bar)
+
+ private val securedColor = context.getColor(R.color.green)
+ private val unsecuredColor = context.getColor(R.color.red)
+
+ var state = ConnectionState.Disconnected
+ set(value) {
+ when (value) {
+ ConnectionState.Disconnected -> unsecured()
+ ConnectionState.Connecting -> secured()
+ ConnectionState.Connected -> secured()
+ }
+
+ field = value
+ }
+
+ private fun unsecured() {
+ headerBar.setBackgroundColor(unsecuredColor)
+ }
+
+ private fun secured() {
+ headerBar.setBackgroundColor(securedColor)
+ }
+}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/LoginFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/LoginFragment.kt
index d5a06a9d75..9159c93079 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/LoginFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/LoginFragment.kt
@@ -62,6 +62,15 @@ class LoginFragment : Fragment() {
loggedInStatus.visibility = View.VISIBLE
accountInput.state = LoginState.Success
+
+ Handler().postDelayed(Runnable { openConnectScreen() }, 1000)
+ }
+
+ private fun openConnectScreen() {
+ fragmentManager?.beginTransaction()?.apply {
+ replace(R.id.main_fragment, ConnectFragment())
+ commit()
+ }
}
private fun loginFailure() {
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/NotificationBanner.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/NotificationBanner.kt
new file mode 100644
index 0000000000..445df2d914
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/NotificationBanner.kt
@@ -0,0 +1,18 @@
+package net.mullvad.mullvadvpn
+
+import android.view.View
+
+class NotificationBanner(val parentView: View) {
+ private val banner: View = parentView.findViewById(R.id.notification_banner)
+
+ var state = ConnectionState.Disconnected
+ set(value) {
+ when (value) {
+ ConnectionState.Disconnected -> banner.visibility = View.GONE
+ ConnectionState.Connecting -> banner.visibility = View.VISIBLE
+ ConnectionState.Connected -> banner.visibility = View.GONE
+ }
+
+ field = value
+ }
+}
diff --git a/android/src/main/res/drawable/green_button_background.xml b/android/src/main/res/drawable/green_button_background.xml
new file mode 100644
index 0000000000..6b1252819d
--- /dev/null
+++ b/android/src/main/res/drawable/green_button_background.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="false">
+ <shape android:shape="rectangle">
+ <corners android:radius="4dp"/>
+ <solid android:color="@color/green"/>
+ </shape>
+ </item>
+
+ <item android:state_pressed="true">
+ <shape android:shape="rectangle">
+ <corners android:radius="4dp"/>
+ <solid android:color="@color/green90"/>
+ </shape>
+ </item>
+</selector>
diff --git a/android/src/main/res/drawable/icon_chevron.xml b/android/src/main/res/drawable/icon_chevron.xml
new file mode 100644
index 0000000000..f10c8d04c7
--- /dev/null
+++ b/android/src/main/res/drawable/icon_chevron.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<vector
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ >
+ <group android:translateX="8.5" android:translateY="6.0">
+ <path android:fillColor="#FFFFFF"
+ android:pathData="M0.335204989,1.95371785 L4.23669259,6 L0.335204989,10.0462822 C-0.111734996,10.4932221 -0.111734996,11.217855 0.335204989,11.664795 C0.782144974,12.111735 1.49826561,12.111735 1.9452056,11.664795 L6.66818642,6.80553188 C6.88657769,6.58714061 6.99779844,6.29559541 6.99881099,6.00303766 C6.99779844,5.70440459 6.88657769,5.41285939 6.66818642,5.19446812 L1.9452056,0.335204989 C1.49826561,-0.111734996 0.782144974,-0.111734996 0.335204989,0.335204989 C-0.111734996,0.782144974 -0.111734996,1.50677786 0.335204989,1.95371785 Z"
+ />
+ </group>
+</vector>
diff --git a/android/src/main/res/drawable/icon_notification_error.xml b/android/src/main/res/drawable/icon_notification_error.xml
new file mode 100644
index 0000000000..d285967fe6
--- /dev/null
+++ b/android/src/main/res/drawable/icon_notification_error.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval"
+ >
+ <solid android:color="@color/red"/>
+ <size android:width="10dp" android:height="10dp"/>
+</shape>
diff --git a/android/src/main/res/drawable/transparent_red_button_background.xml b/android/src/main/res/drawable/transparent_red_button_background.xml
new file mode 100644
index 0000000000..6f5a86b205
--- /dev/null
+++ b/android/src/main/res/drawable/transparent_red_button_background.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="false">
+ <shape android:shape="rectangle">
+ <corners android:radius="4dp"/>
+ <solid android:color="@color/red40"/>
+ </shape>
+ </item>
+
+ <item android:state_pressed="true">
+ <shape android:shape="rectangle">
+ <corners android:radius="4dp"/>
+ <solid android:color="@color/red45"/>
+ </shape>
+ </item>
+</selector>
diff --git a/android/src/main/res/drawable/white20_button_background.xml b/android/src/main/res/drawable/white20_button_background.xml
new file mode 100644
index 0000000000..ee5787d516
--- /dev/null
+++ b/android/src/main/res/drawable/white20_button_background.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="false">
+ <shape android:shape="rectangle">
+ <corners android:radius="4dp"/>
+ <solid android:color="@color/white20"/>
+ </shape>
+ </item>
+
+ <item android:state_pressed="true">
+ <shape android:shape="rectangle">
+ <corners android:radius="4dp"/>
+ <solid android:color="@color/white40"/>
+ </shape>
+ </item>
+</selector>
diff --git a/android/src/main/res/layout/connect.xml b/android/src/main/res/layout/connect.xml
new file mode 100644
index 0000000000..8163a9a297
--- /dev/null
+++ b/android/src/main/res/layout/connect.xml
@@ -0,0 +1,151 @@
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ >
+ <LinearLayout android:id="@+id/header_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:padding="12dp"
+ android:background="@color/red"
+ >
+ <ImageView
+ android:layout_width="49dp"
+ android:layout_height="50dp"
+ android:src="@drawable/logo_icon"
+ />
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginHorizontal="8dp"
+ android:textColor="@color/white60"
+ android:textSize="24sp"
+ android:textStyle="bold"
+ android:text="@string/app_name"
+ android:textAllCaps="true"
+ />
+ </LinearLayout>
+
+ <LinearLayout android:id="@+id/notification_banner"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingVertical="8dp"
+ android:background="@color/darkBlue"
+ android:orientation="horizontal"
+ android:gravity="center"
+ android:visibility="gone"
+ >
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:layout_marginLeft="19dp"
+ android:src="@drawable/icon_notification_error"
+ />
+ <TextView
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginLeft="7dp"
+ android:textSize="13sp"
+ android:textStyle="bold"
+ android:text="@string/blocking_internet"
+ android:textAllCaps="true"
+ />
+ </LinearLayout>
+
+ <Space
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ />
+
+ <ProgressBar android:id="@+id/connecting_spinner"
+ android:layout_width="60dp"
+ android:layout_height="60dp"
+ android:layout_gravity="center"
+ android:layout_marginBottom="14dp"
+ android:indeterminate="true"
+ android:indeterminateOnly="true"
+ android:indeterminateDuration="600"
+ android:indeterminateDrawable="@drawable/icon_spinner"
+ android:visibility="invisible"
+ />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:orientation="vertical"
+ android:padding="24dp"
+ android:gravity="start"
+ >
+ <TextView android:id="@+id/connection_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:textColor="@color/red"
+ android:textSize="16sp"
+ android:textStyle="bold"
+ android:text="@string/unsecured_connection"
+ android:textAllCaps="true"
+ />
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/white"
+ android:textSize="34sp"
+ android:textStyle="bold"
+ android:text="@string/country"
+ />
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/white"
+ android:textSize="34sp"
+ android:textStyle="bold"
+ android:text=""
+ android:visibility="invisible"
+ />
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/white"
+ android:textSize="16sp"
+ android:textStyle="bold"
+ android:text=""
+ android:visibility="invisible"
+ />
+ </LinearLayout>
+
+ <Space
+ android:layout_width="match_parent"
+ android:layout_height="32dp"
+ android:layout_weight="0"
+ />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="0"
+ android:orientation="vertical"
+ android:padding="24dp"
+ >
+ <Button
+ android:layout_marginVertical="16dp"
+ android:text="@string/switch_location"
+ android:drawableRight="@drawable/icon_chevron"
+ android:paddingRight="8dp"
+ style="@style/White20Button"
+ />
+ <Button android:id="@+id/action_button"
+ android:text="@string/connect"
+ style="@style/GreenButton"
+ />
+ </LinearLayout>
+</LinearLayout>
diff --git a/android/src/main/res/values/colors.xml b/android/src/main/res/values/colors.xml
index 22a7e4108d..905f1e497c 100644
--- a/android/src/main/res/values/colors.xml
+++ b/android/src/main/res/values/colors.xml
@@ -6,9 +6,13 @@
<color name="darkBlue">#192E45</color>
<color name="white">#FFFFFF</color>
<color name="white60">#99FFFFFF</color>
+ <color name="white40">#66FFFFFF</color>
<color name="white20">#33FFFFFF</color>
<color name="green">#44AD4D</color>
+ <color name="green90">#E644AD4D</color>
<color name="red">#D0021B</color>
+ <color name="red45">#73021B</color>
+ <color name="red40">#66021B</color>
<color name="textInputBorder">#234161</color>
</resources>
diff --git a/android/src/main/res/values/strings.xml b/android/src/main/res/values/strings.xml
index 59c207b71c..b8d1cdb654 100644
--- a/android/src/main/res/values/strings.xml
+++ b/android/src/main/res/values/strings.xml
@@ -9,4 +9,14 @@
<string name="logged_in_title">Login successful</string>
<string name="login_fail_title">Login failed</string>
<string name="login_fail_description">Invalid account number, try again</string>
+
+ <string name="unsecured_connection">Unsecured connection</string>
+ <string name="creating_secure_connection">Creating secure connection</string>
+ <string name="secure_connection">Secure connection</string>
+ <string name="blocking_internet">Blocking internet</string>
+ <string name="country">Country</string>
+ <string name="connect">Secure my connection</string>
+ <string name="cancel">Cancel</string>
+ <string name="disconnect">Disconnect</string>
+ <string name="switch_location">Switch location</string>
</resources>
diff --git a/android/src/main/res/values/styles.xml b/android/src/main/res/values/styles.xml
index 726847ab42..86401714f7 100644
--- a/android/src/main/res/values/styles.xml
+++ b/android/src/main/res/values/styles.xml
@@ -3,4 +3,21 @@
<item name="colorPrimary">@color/colorPrimary</item>
<item name="android:windowBackground">@color/blue</item>
</style>
+
+ <style name="Button" parent="Widget.AppCompat.Button.Borderless">
+ <item name="android:layout_height">44dp</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:textAllCaps">false</item>
+ <item name="android:textColor">@color/white</item>
+ <item name="android:textSize">20sp</item>
+ <item name="android:textStyle">bold</item>
+ </style>
+
+ <style name="GreenButton" parent="Button">
+ <item name="android:background">@drawable/green_button_background</item>
+ </style>
+
+ <style name="White20Button" parent="Button">
+ <item name="android:background">@drawable/white20_button_background</item>
+ </style>
</resources>