diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2020-09-03 07:15:41 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2020-09-03 07:15:41 -0300 |
| commit | bc13c536704710abda42aa6d5249a30a42c6ad93 (patch) | |
| tree | 9fe190877e8f26f09c9024e22cc0bde52a4797d6 /android | |
| parent | 8edecd78260795bd9eeaf620b8b02d35bd2c7130 (diff) | |
| parent | 1d83873e1739af94670453a6c3107f5a509cf35c (diff) | |
| download | mullvadvpn-bc13c536704710abda42aa6d5249a30a42c6ad93.tar.xz mullvadvpn-bc13c536704710abda42aa6d5249a30a42c6ad93.zip | |
Merge branch 'create-switch-location-widget'
Diffstat (limited to 'android')
7 files changed, 119 insertions, 133 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectFragment.kt index 30794f0eec..b1a4f6f2cb 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectFragment.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ConnectFragment.kt @@ -13,6 +13,7 @@ import net.mullvad.mullvadvpn.ui.notification.TunnelStateNotification import net.mullvad.mullvadvpn.ui.notification.VersionInfoNotification import net.mullvad.mullvadvpn.ui.widget.HeaderBar import net.mullvad.mullvadvpn.ui.widget.NotificationBanner +import net.mullvad.mullvadvpn.ui.widget.SwitchLocationButton import org.joda.time.DateTime val KEY_IS_TUNNEL_INFO_EXPANDED = "is_tunnel_info_expanded" @@ -68,8 +69,9 @@ class ConnectFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) { onDisconnect = { connectionProxy.disconnect() } } - switchLocationButton = SwitchLocationButton(view, resources) - switchLocationButton.onClick = { openSwitchLocationScreen() } + switchLocationButton = view.findViewById<SwitchLocationButton>(R.id.switch_location).apply { + onClick = { openSwitchLocationScreen() } + } return view } @@ -86,8 +88,10 @@ class ConnectFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) { } relayListListener.onRelayListChange = { _, selectedRelayItem -> - locationInfoCache.selectedRelay = selectedRelayItem - switchLocationButton.location = selectedRelayItem + jobTracker.newUiJob("updateSelectedRelayItem") { + locationInfoCache.selectedRelay = selectedRelayItem + switchLocationButton.location = selectedRelayItem + } } connectionProxy.onUiStateChange.subscribe(this) { uiState -> @@ -120,7 +124,6 @@ class ConnectFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) { override fun onSafelyDestroyView() { notificationBanner.onDestroy() - switchLocationButton.onDestroy() } override fun onSafelySaveInstanceState(state: Bundle) { @@ -134,7 +137,7 @@ class ConnectFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) { status.setState(realState) actionButton.tunnelState = uiState - switchLocationButton.state = uiState + switchLocationButton.tunnelState = uiState } private fun openSwitchLocationScreen() { diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/SwitchLocationButton.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/SwitchLocationButton.kt deleted file mode 100644 index 89eaf2cad8..0000000000 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/SwitchLocationButton.kt +++ /dev/null @@ -1,118 +0,0 @@ -package net.mullvad.mullvadvpn.ui - -import android.content.res.Resources -import android.graphics.drawable.Drawable -import android.text.TextUtils.TruncateAt -import android.view.View -import android.view.ViewGroup.MarginLayoutParams -import android.widget.Button -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.model.TunnelState -import net.mullvad.mullvadvpn.relaylist.RelayItem -import net.mullvad.talpid.tunnel.ActionAfterDisconnect - -class SwitchLocationButton(val parentView: View, val resources: Resources) { - private val button: Button = parentView.findViewById(R.id.switch_location) - private val chevron: Drawable = button.compoundDrawables[2] - - private val normalButtonHeight = resources.getDimensionPixelSize(R.dimen.normal_button_height) - private val tallButtonHeight = resources.getDimensionPixelSize(R.dimen.tall_button_height) - private val topMargin = tallButtonHeight - normalButtonHeight - - private var tall = false - private var updateJob: Job? = null - - var location: RelayItem? = null - set(value) { - field = value - update() - } - - var state: TunnelState = TunnelState.Disconnected() - set(value) { - field = value - update() - } - - var onClick: (() -> Unit)? = null - - init { - button.setOnClickListener { onClick?.invoke() } - button.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> resizeIfNecessary() } - } - - fun onDestroy() { - updateJob?.cancel() - } - - private fun update() { - updateJob?.cancel() - updateJob = GlobalScope.launch(Dispatchers.Main) { - val state = this@SwitchLocationButton.state - - when (state) { - is TunnelState.Disconnected -> showLocation() - is TunnelState.Disconnecting -> { - when (state.actionAfterDisconnect) { - ActionAfterDisconnect.Nothing -> showLocation() - ActionAfterDisconnect.Block -> showLocation() - ActionAfterDisconnect.Reconnect -> showLabel() - } - } - is TunnelState.Connecting -> showLabel() - is TunnelState.Connected -> showLabel() - is TunnelState.Error -> showLocation() - } - } - } - - private fun showLabel() { - button.setText(R.string.switch_location) - button.setCompoundDrawables(null, null, null, null) - resizeIfNecessary() - } - - private fun showLocation() { - val locationName = location?.locationName - - if (locationName == null) { - showLabel() - } else { - button.setText(locationName) - button.setCompoundDrawables(null, null, chevron, null) - resizeIfNecessary() - } - } - - private fun resizeIfNecessary() { - val layoutParams = button.layoutParams - - if (button.lineCount > 1 && !tall) { - tall = true - - if (layoutParams is MarginLayoutParams) { - layoutParams.height = tallButtonHeight - layoutParams.topMargin = 0 - } - - button.maxLines = 2 - button.ellipsize = TruncateAt.END - button.requestLayout() - } else if (button.lineCount <= 1 && tall) { - tall = false - - if (layoutParams is MarginLayoutParams) { - layoutParams.height = normalButtonHeight - layoutParams.topMargin = topMargin - } - - button.maxLines = -1 - button.ellipsize = null - button.requestLayout() - } - } -} diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/SwitchLocationButton.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/SwitchLocationButton.kt new file mode 100644 index 0000000000..9ca390b4e1 --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/SwitchLocationButton.kt @@ -0,0 +1,89 @@ +package net.mullvad.mullvadvpn.ui.widget + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.FrameLayout +import android.widget.TextView +import kotlin.properties.Delegates.observable +import net.mullvad.mullvadvpn.R +import net.mullvad.mullvadvpn.model.TunnelState +import net.mullvad.mullvadvpn.relaylist.RelayItem +import net.mullvad.talpid.tunnel.ActionAfterDisconnect + +class SwitchLocationButton : FrameLayout { + private val container = + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE).let { service -> + val inflater = service as LayoutInflater + + inflater.inflate(R.layout.switch_location_button, this) + } + + private val buttonWithLabel = container.findViewById<View>(R.id.button_with_label).apply { + setOnClickListener { onClick?.invoke() } + } + + private val buttonWithLocation = + container.findViewById<TextView>(R.id.button_with_location).apply { + setOnClickListener { onClick?.invoke() } + } + + var onClick: (() -> Unit)? = null + + var location by observable<RelayItem?>(null) { _, _, location -> + buttonWithLocation.text = location?.locationName ?: "" + } + + var tunnelState by observable<TunnelState>(TunnelState.Disconnected()) { _, _, state -> + when (state) { + is TunnelState.Disconnected -> showLocation() + is TunnelState.Disconnecting -> { + when (state.actionAfterDisconnect) { + ActionAfterDisconnect.Nothing -> showLocation() + ActionAfterDisconnect.Block -> showLocation() + ActionAfterDisconnect.Reconnect -> showLabel() + } + } + is TunnelState.Connecting -> showLabel() + is TunnelState.Connected -> showLabel() + is TunnelState.Error -> showLocation() + } + } + + constructor(context: Context) : super(context) {} + + constructor(context: Context, attributes: AttributeSet) : super(context, attributes) {} + + constructor(context: Context, attributes: AttributeSet, defaultStyleAttribute: Int) : + super(context, attributes, defaultStyleAttribute) {} + + constructor( + context: Context, + attributes: AttributeSet, + defaultStyleAttribute: Int, + defaultStyleResource: Int + ) : super(context, attributes, defaultStyleAttribute, defaultStyleResource) {} + + private fun showLabel() { + updateButton(buttonWithLabel, true) + updateButton(buttonWithLocation, false) + } + + private fun showLocation() { + updateButton(buttonWithLabel, false) + updateButton(buttonWithLocation, true) + } + + private fun updateButton(button: View, show: Boolean) { + button.apply { + setEnabled(show) + + visibility = if (show) { + View.VISIBLE + } else { + View.INVISIBLE + } + } + } +} diff --git a/android/src/main/res/layout/connect.xml b/android/src/main/res/layout/connect.xml index a7887e5076..7fd06fd4bc 100644 --- a/android/src/main/res/layout/connect.xml +++ b/android/src/main/res/layout/connect.xml @@ -121,12 +121,10 @@ android:paddingHorizontal="@dimen/side_margin" android:paddingTop="@dimen/button_separation" android:paddingBottom="@dimen/screen_vertical_margin"> - <Button android:id="@+id/switch_location" - android:layout_marginBottom="@dimen/button_separation" - android:paddingHorizontal="9dp" - android:text="@string/switch_location" - android:drawableRight="@drawable/icon_chevron" - style="@style/White20Button" /> + <net.mullvad.mullvadvpn.ui.widget.SwitchLocationButton android:id="@+id/switch_location" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/button_separation" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> diff --git a/android/src/main/res/layout/switch_location_button.xml b/android/src/main/res/layout/switch_location_button.xml new file mode 100644 index 0000000000..d9ed79956f --- /dev/null +++ b/android/src/main/res/layout/switch_location_button.xml @@ -0,0 +1,14 @@ +<merge xmlns:android="http://schemas.android.com/apk/res/android"> + <Button android:id="@+id/button_with_label" + android:layout_gravity="bottom" + android:paddingHorizontal="9dp" + android:text="@string/switch_location" + style="@style/White20Button" /> + <Button android:id="@+id/button_with_location" + android:layout_gravity="bottom" + android:paddingHorizontal="9dp" + android:text="@string/switch_location" + android:drawableRight="@drawable/icon_chevron" + android:visibility="invisible" + style="@style/White20Button" /> +</merge> diff --git a/android/src/main/res/values/dimensions.xml b/android/src/main/res/values/dimensions.xml index 1d87dc8350..0e4240ef36 100644 --- a/android/src/main/res/values/dimensions.xml +++ b/android/src/main/res/values/dimensions.xml @@ -7,8 +7,7 @@ <dimen name="account_input_corner_radius">4dp</dimen> <dimen name="account_input_border_width">2dp</dimen> <dimen name="edit_text_corner_radius">4dp</dimen> - <dimen name="normal_button_height">44dp</dimen> - <dimen name="tall_button_height">64dp</dimen> + <dimen name="button_height">44dp</dimen> <dimen name="cell_switch_border_radius">16dp</dimen> <dimen name="cell_switch_width">48dp</dimen> <dimen name="cell_switch_height">30dp</dimen> diff --git a/android/src/main/res/values/styles.xml b/android/src/main/res/values/styles.xml index e5f8ea91db..1fc47c0e6f 100644 --- a/android/src/main/res/values/styles.xml +++ b/android/src/main/res/values/styles.xml @@ -15,8 +15,9 @@ </style> <style name="Button" parent="Widget.AppCompat.Button.Borderless"> - <item name="android:layout_height">@dimen/normal_button_height</item> + <item name="android:layout_height">wrap_content</item> <item name="android:layout_width">match_parent</item> + <item name="android:minHeight">@dimen/button_height</item> <item name="android:paddingTop">0dp</item> <item name="android:paddingBottom">0dp</item> <item name="android:textAllCaps">false</item> |
