Skip to content
Snippets Groups Projects
Commit 333d9284 authored by clairehurst's avatar clairehurst
Browse files

fixup! Implement Android-native Connection Assist UI

parent 5ab6ae0a
Branches
No related tags found
1 merge request!69Bug_41188: Improve Connection Assist
......@@ -168,6 +168,7 @@ import java.util.Locale
import androidx.navigation.fragment.findNavController
import mozilla.components.browser.engine.gecko.GeckoEngine
import mozilla.components.browser.state.selector.findCustomTab
import org.mozilla.fenix.home.HomeFragment
import org.mozilla.geckoview.TorIntegrationAndroid
/**
......@@ -815,6 +816,10 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, TorIn
final override fun onBackPressed() {
supportFragmentManager.primaryNavigationFragment?.childFragmentManager?.fragments?.forEach {
if (it is HomeFragment){
finish()
return
}
if (it is UserInteractionHandler && it.onBackPressed()) {
return
}
......
......
......@@ -4,11 +4,19 @@
package org.mozilla.fenix.tor
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.text.SpannableString
import android.text.Spanned
import android.text.TextPaint
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.content.res.AppCompatResources
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
......@@ -22,6 +30,7 @@ import org.mozilla.fenix.ext.hideToolbar
class TorConnectionAssistFragment : Fragment() {
private val TAG = "TorConnectionAssistFrag"
private var _binding: FragmentTorConnectionAssistBinding? = null
private val binding get() = _binding!!
......@@ -49,13 +58,14 @@ class TorConnectionAssistFragment : Fragment() {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.torConnectState.collect {
when (it) {
TorConnectState.Initial -> showConfiguring()
viewModel.torConnectState.collect { torConnectState ->
Log.d(TAG, "torConnectState is ${torConnectState.state}")
when (torConnectState) {
TorConnectState.Initial -> showSplash()
TorConnectState.Configuring -> showConfiguring()
TorConnectState.AutoBootstrapping -> showBootstrapping()
TorConnectState.Bootstrapping -> showBootstrapping()
TorConnectState.Error -> TODO()
TorConnectState.Error -> showError()
TorConnectState.Bootstrapped -> openHome()
TorConnectState.Disabled -> openHome()
}
......@@ -73,59 +83,302 @@ class TorConnectionAssistFragment : Fragment() {
}
}
viewModel.quickconnectToggle().observe(
viewLifecycleOwner
viewModel.quickstartToggle().observe(
viewLifecycleOwner,
) {
binding.quickstartSwitch.isChecked = it
binding.quickstartSwitch.isChecked = it == true
}
binding.quickstartSwitch.setOnCheckedChangeListener { _, isChecked ->
viewModel.handleQuickstartChecked(isChecked)
}
}
private fun showSplash() {
binding.torBootstrapProgressBar.visibility = View.GONE
binding.settingsButton.visibility = View.GONE
binding.backButton.visibility = View.GONE
binding.torConnectImage.visibility = View.GONE
binding.titleLargeTextView.visibility = View.GONE
binding.titleDescription.visibility = View.GONE
binding.quickStartDescription.visibility = View.GONE
binding.quickstartSwitch.visibility = View.GONE
binding.torBootstrapButton1.visibility = View.GONE
binding.torBootstrapButton2.visibility = View.GONE
binding.wordmarkLogo.visibility = View.VISIBLE
}
private fun showConfiguring() {
binding.wordmarkLogo.visibility = View.GONE
binding.torBootstrapProgressBar.visibility = View.INVISIBLE
binding.torBootstrapProgressBar.progress = 0
binding.backButton.visibility = View.INVISIBLE
binding.settingsButton.visibility = View.VISIBLE
binding.settingsButton.setOnClickListener {
viewModel.cancelTorBootstrap()
openSettings()
}
binding.torConnectImage.visibility = View.VISIBLE
binding.torConnectImage.setImageResource(R.drawable.connect)
binding.titleLargeTextView.visibility = View.VISIBLE
binding.titleLargeTextView.text = getString(R.string.connection_assist_tor_connect_title)
binding.titleDescription.visibility = View.VISIBLE
binding.titleDescription.text =
getString(R.string.preferences_tor_network_settings_explanation)
binding.quickStartDescription.visibility = View.VISIBLE
binding.quickstartSwitch.visibility = View.VISIBLE
binding.quickstartSwitch.isChecked = viewModel.quickstartToggle().value == true
binding.unblockTheInternetInCountryDescription.visibility = View.GONE
binding.countryDropDown.visibility = View.GONE
binding.torBootstrapConnectButton.setOnClickListener {
binding.torBootstrapButton1.visibility = View.VISIBLE
binding.torBootstrapButton1.text = getString(R.string.tor_bootstrap_connect)
binding.torBootstrapButton1.setOnClickListener {
viewModel.handleConnect(lifecycleScope = lifecycleScope)
showBootstrapping()
}
binding.quickstartSwitch.setOnCheckedChangeListener { _, isChecked ->
viewModel.handleQuickstartChecked(isChecked)
binding.torBootstrapButton2.visibility = View.VISIBLE
binding.torBootstrapButton2.text =
getString(R.string.connection_assist_configure_connection_button)
binding.torBootstrapButton2.setOnClickListener {
viewModel.cancelTorBootstrap()
openTorNetworkSettings()
}
}
private fun showConfiguring() {
binding.torBootstrapConnectButton.visibility = View.VISIBLE
binding.torBootstrapNetworkSettingsButton.text =
private fun showBootstrapping() {
binding.wordmarkLogo.visibility = View.GONE
binding.torBootstrapProgressBar.visibility = View.VISIBLE
binding.torBootstrapProgressBar.progress = 0
binding.backButton.visibility = View.INVISIBLE
binding.settingsButton.visibility = View.VISIBLE
binding.settingsButton.setOnClickListener {
viewModel.cancelTorBootstrap()
openSettings()
}
binding.torConnectImage.visibility = View.VISIBLE
binding.torConnectImage.setImageResource(R.drawable.connect)
binding.titleLargeTextView.visibility = View.VISIBLE
binding.titleLargeTextView.text = getString(R.string.connection_assist_connecting_title)
binding.titleDescription.visibility = View.VISIBLE
binding.titleDescription.text =
getString(R.string.preferences_tor_network_settings_explanation)
binding.quickstartSwitch.visibility = View.VISIBLE
binding.quickstartSwitch.isChecked = viewModel.quickstartToggle().value == true
binding.quickstartSwitch.jumpDrawablesToCurrentState()
binding.quickStartDescription.visibility = View.VISIBLE
binding.torBootstrapButton1.visibility = View.INVISIBLE
binding.torBootstrapButton2.visibility = View.VISIBLE
binding.torBootstrapButton2.text = getString(R.string.btn_cancel)
binding.torBootstrapButton2.setOnClickListener { viewModel.cancelTorBootstrap() }
}
private suspend fun showError() {
viewModel.torError.collect {
Log.d(
TAG,
"TorError: details = ${it?.details ?: "null details"}, message = ${it?.message ?: "null message"}",
)
when (viewModel.handleError(it)) {
ErrorScreen.CantConnectToInternet -> showCantConnectToInternet()
ErrorScreen.CantConnectToTorDirectly -> showCantConnectToTorDirectly()
ErrorScreen.WeCouldntFindYourLocation -> showWeCouldntFindYourLocation()
ErrorScreen.WereStillHavingTroubleConnecting -> showWereStillHavingTroubleConnecting()
ErrorScreen.WeWerentAbleToConnectAutomatically -> showWeWerentAbleToConnectAutomatically()
null -> {
// no op
Log.d(TAG, "ErrorScreen: null, nothing shown")
}
}
}
}
private fun showCantConnectToInternet() {
Log.d(TAG, "showCantConnectToInternet()")
binding.torBootstrapProgressBar.visibility = View.VISIBLE
binding.torBootstrapProgressBar.progressTintList =
AppCompatResources.getColorStateList(requireContext(), R.color.warning_yellow)
binding.torBootstrapProgressBar.progress = 100
binding.backButton.visibility = View.VISIBLE
binding.backButton.setOnClickListener {
showConfiguring()
}
binding.torConnectImage.setImageResource(R.drawable.globe_broken)
binding.titleLargeTextView.text = getString(R.string.connection_assist_internet_error_title)
val learnMore: String = getString(R.string.connection_assist_internet_error_learn_more)
val internetErrorDescription: String = getString(
R.string.connection_assist_internet_error_description,
learnMore,
)
handleDescriptionWithClickable(internetErrorDescription, learnMore)
binding.quickStartDescription.visibility = View.GONE
binding.quickstartSwitch.visibility = View.GONE
binding.torBootstrapButton1.visibility = View.VISIBLE
binding.torBootstrapButton1.text =
getString(R.string.connection_assist_internet_error_try_again)
binding.torBootstrapButton1.setOnClickListener {
showTryingAgain()
viewModel.handleConnect(lifecycleScope = lifecycleScope)
}
binding.torBootstrapButton2.text =
getString(R.string.connection_assist_configure_connection_button)
binding.torBootstrapNetworkSettingsButton.setOnClickListener {
binding.torBootstrapButton2.setOnClickListener {
openTorNetworkSettings()
}
}
private fun showBootstrapping() {
binding.torBootstrapConnectButton.visibility = View.INVISIBLE
binding.torBootstrapNetworkSettingsButton.text = getString(R.string.btn_cancel)
binding.torBootstrapNetworkSettingsButton.setOnClickListener {
private fun showTryingAgain() {
Log.d(TAG, "showTryingAgain()")
binding.torBootstrapProgressBar.progress = 0
binding.torBootstrapProgressBar.visibility = View.VISIBLE
binding.torBootstrapProgressBar.progressTintList = null
binding.torConnectImage.setImageResource(R.drawable.connect)
binding.titleLargeTextView.text =
getString(R.string.connection_assist_trying_again_waiting_title)
binding.quickstartSwitch.visibility = View.GONE
binding.quickStartDescription.visibility = View.GONE
binding.torBootstrapButton1.visibility = View.INVISIBLE
binding.torBootstrapButton2.visibility = View.VISIBLE
binding.torBootstrapButton2.text = getString(R.string.btn_cancel)
binding.torBootstrapButton2.setOnClickListener {
viewModel.cancelTorBootstrap()
showConfiguring()
}
}
private fun openSettings(preferenceToScrollTo: String? = null) {
findNavController().navigate(
TorConnectionAssistFragmentDirections
.actionTorConnectionAssistFragmentToSettingsFragment(preferenceToScrollTo),
private fun showCantConnectToTorDirectly() {
Log.d(TAG, "showCantConnectToTorDirectly()")
binding.torBootstrapProgressBar.visibility = View.VISIBLE
binding.torBootstrapProgressBar.progressTintList =
AppCompatResources.getColorStateList(requireContext(), R.color.warning_yellow)
binding.torBootstrapProgressBar.progress = 100
binding.backButton.visibility = View.VISIBLE
binding.backButton.setOnClickListener {
showConfiguring()
}
binding.torConnectImage.setImageResource(R.drawable.globe_broken)
binding.titleLargeTextView.text =
getString(R.string.connection_assist_cant_connect_to_tor_title)
val learnMore: String = getString(R.string.connection_assist_internet_error_learn_more)
val tryABridge: String = getString(
R.string.connection_assist_try_a_bridge_description,
learnMore,
)
handleDescriptionWithClickable(tryABridge, learnMore)
binding.quickStartDescription.visibility = View.GONE
binding.quickstartSwitch.visibility = View.GONE
binding.unblockTheInternetInCountryDescription.visibility = View.VISIBLE
binding.countryDropDown.visibility = View.VISIBLE
// TODO implement countryDropDown
binding.torBootstrapButton1.visibility = View.VISIBLE
binding.torBootstrapButton1.text = getString(R.string.connection_assist_try_a_bridge_button)
binding.torBootstrapButton1.setOnClickListener {
viewModel.tryABridge()
showTryingABridge()
}
binding.torBootstrapButton2.visibility = View.GONE
}
private fun openTorNetworkSettings() {
findNavController().navigate(
TorConnectionAssistFragmentDirections
.actionTorConnectionAssistFragmentToTorNetworkSettings(),
private fun showTryingABridge() {
Log.d(TAG, "showTryingABridge()")
// TODO(Not implemented)
binding.torBootstrapButton2.setOnClickListener {
showTryingABridge()
}
}
private fun showWeCouldntFindYourLocation() {
Log.d(TAG, "showWeCouldntFindYourLocation()")
// TODO(Not implemented)
binding.torBootstrapButton2.setOnClickListener {
showTryingABridge()
}
}
private fun showWereStillHavingTroubleConnecting() {
Log.d(TAG, "showWereStillHavingTroubleConnecting()")
TODO("Not yet implemented")
}
private fun showTryingOneMoreTime() {
Log.d(TAG, "showTryingOneMoreTime()")
TODO("Not yet implemented")
}
private fun showWeWerentAbleToConnectAutomatically() {
Log.d(TAG, "showWeWerentAbleToConnectAutomatically()")
TODO("Not yet implemented")
}
private fun showUnknownError() {
Log.d(TAG, "showUnknownError()")
TODO("Not yet implemented")
}
/**
* from https://stackoverflow.com/questions/10696986/how-to-set-the-part-of-the-text-view-is-clickable
*/
private fun handleDescriptionWithClickable(errorDescription: String, learnMore: String) {
val errorDescriptionSpannableString = SpannableString(errorDescription)
val clickableSpan: ClickableSpan = object : ClickableSpan() {
override fun onClick(textView: View) {
showLearnMore()
}
override fun updateDrawState(drawState: TextPaint) {
super.updateDrawState(drawState)
drawState.isUnderlineText = true
}
}
errorDescriptionSpannableString.setSpan(
clickableSpan,
errorDescription.length - learnMore.length,
errorDescription.length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE,
)
binding.titleDescription.text = errorDescriptionSpannableString
binding.titleDescription.movementMethod = LinkMovementMethod.getInstance()
binding.titleDescription.highlightColor = Color.TRANSPARENT
}
private fun showLearnMore() {
//TODO("Not yet implemented")
}
private fun openHome() {
Log.d(TAG, "openHome()") //This doesn't seem to be ever called
findNavController().navigate(TorConnectionAssistFragmentDirections.actionStartupHome())
}
private fun openSettings(preferenceToScrollTo: String? = null) {
findNavController().navigate(
TorConnectionAssistFragmentDirections.actionTorConnectionAssistFragmentToSettingsFragment(
preferenceToScrollTo,
),
)
}
private fun openTorNetworkSettings() {
findNavController().navigate(
TorConnectionAssistFragmentDirections.actionTorConnectionAssistFragmentToTorNetworkSettings(),
)
}
}
......@@ -26,24 +26,30 @@ class TorConnectionAssistViewModel(
private val _torConnectState = MutableStateFlow(TorConnectState.Initial)
internal val torConnectState: StateFlow<TorConnectState> = _torConnectState
init {
_torController.registerTorListener(this)
}
private val _torError = MutableStateFlow(_torController.getLastErrorState())
internal val torError: StateFlow<TorError?> = _torError
private val _progress = MutableLiveData(0)
fun progress(): LiveData<Int> {
return _progress
}
private val _quickconnectToggle = MutableLiveData(_torController.quickstart)
fun quickconnectToggle(): LiveData<Boolean> {
return _quickconnectToggle
private val _quickStartToggle = MutableLiveData<Boolean>() // don't initialize with quickstart off the bat
fun quickstartToggle(): LiveData<Boolean?> {
_quickStartToggle.value = _torController.quickstart // quickstart isn't ready until torSettings is ready
return _quickStartToggle
}
init {
Log.d(TAG, "initiating TorConnectionAssistViewModel")
_torController.registerTorListener(this)
}
fun handleConnect(
withDebugLogging: Boolean = false,
lifecycleScope: LifecycleCoroutineScope? = null,
) {
Log.d(TAG, "handleConnect initiatingTorBootstrap with lifecycleScope = $lifecycleScope")
_torController.initiateTorBootstrap(
withDebugLogging = withDebugLogging,
lifecycleScope = lifecycleScope,
......@@ -52,6 +58,7 @@ class TorConnectionAssistViewModel(
fun handleQuickstartChecked(checked: Boolean) {
_torController.quickstart = checked
_quickStartToggle.value = checked
}
fun cancelTorBootstrap() {
......@@ -66,7 +73,6 @@ class TorConnectionAssistViewModel(
override fun onTorConnected() {
Log.d(TAG, "onTorConnected()")
_torController.unregisterTorListener(this)
_torConnectState.value = _torController.lastKnownStatus
}
override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) {
......@@ -75,12 +81,32 @@ class TorConnectionAssistViewModel(
_progress.value = progress.toInt()
}
_torConnectState.value = _torController.lastKnownStatus
_torError.value = _torController.getLastErrorState()
}
override fun onTorStopped() {
Log.d(TAG, "onTorStopped()")
_progress.value = 0
_torConnectState.value = _torController.lastKnownStatus
}
internal fun handleError(it: TorError?): ErrorScreen? {
// TODO(Only partly implemented)
if (it?.message == null){
return null
}
return ErrorScreen.CantConnectToInternet
}
fun tryABridge() {
// TODO("Try a bridge not enabled")
// connect to bridge based on country
// try connecting
}
}
internal enum class ErrorScreen {
CantConnectToInternet,
CantConnectToTorDirectly,
WeCouldntFindYourLocation,
WereStillHavingTroubleConnecting,
WeWerentAbleToConnectAutomatically,
}
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<group>
<clip-path
android:pathData="M0,0h40v40h-40z"/>
<path
android:pathData="M8.317,5.337C11.521,2.781 15.582,1.253 19.999,1.253C30.352,1.253 38.745,9.647 38.745,20C38.745,24.418 37.218,28.478 34.662,31.681L32.577,29.597C34.611,26.937 35.819,23.611 35.819,20C35.819,11.26 28.739,4.18 19.999,4.18C16.389,4.18 13.063,5.388 10.401,7.421L8.317,5.337Z"
android:fillColor="#FBFBFE"/>
<path
android:pathData="M5.89,7.656C3.002,10.954 1.252,15.273 1.252,20C1.252,28.967 7.545,36.46 15.959,38.307C16.839,38.5 17.732,38.633 18.652,38.693V24.373C16.785,23.8 15.425,22.06 15.425,20C15.425,19.19 15.635,18.43 16.004,17.771L13.887,15.653C13.013,16.88 12.499,18.38 12.499,20C12.499,22.653 13.879,24.987 15.959,26.32V35.293C9.179,33.513 4.179,27.347 4.179,20C4.179,16.08 5.603,12.493 7.963,9.73L5.89,7.656Z"
android:fillColor="#FBFBFE"/>
<path
android:pathData="M16.399,13.419L18.618,15.638C19.054,15.501 19.517,15.427 19.998,15.427C22.525,15.427 24.572,17.473 24.572,20C24.572,20.481 24.498,20.945 24.36,21.38L26.579,23.599C27.165,22.531 27.498,21.304 27.498,20C27.498,15.86 24.138,12.5 19.998,12.5C18.694,12.5 17.468,12.833 16.399,13.419Z"
android:fillColor="#FBFBFE"/>
<path
android:pathData="M24.349,26.112L22.232,23.995C21.954,24.151 21.658,24.278 21.349,24.373V38.693C22.269,38.633 23.162,38.5 24.042,38.307C27.176,37.619 30.015,36.147 32.345,34.109L30.271,32.034C28.492,33.552 26.372,34.681 24.042,35.293V26.32C24.146,26.253 24.249,26.184 24.349,26.112Z"
android:fillColor="#FBFBFE"/>
<path
android:pathData="M30.653,27.67C32.21,25.514 33.127,22.864 33.127,20C33.127,12.753 27.247,6.873 20,6.873C17.138,6.873 14.488,7.791 12.33,9.348L14.437,11.455C16.037,10.412 17.947,9.807 20,9.807C25.634,9.807 30.194,14.367 30.194,20C30.194,22.051 29.587,23.962 28.544,25.562L30.653,27.67Z"
android:fillColor="#FBFBFE"/>
<path
android:pathData="M26.272,28.037L28.357,30.121C27.095,31.163 25.635,31.973 24.041,32.487V29.36C24.844,29.014 25.593,28.568 26.272,28.037Z"
android:fillColor="#FBFBFE"/>
<path
android:pathData="M11.962,13.727L9.878,11.643C8.001,13.914 6.873,16.826 6.873,20C6.873,25.84 10.686,30.787 15.96,32.487V29.36C12.34,27.8 9.806,24.193 9.806,20C9.806,17.633 10.611,15.457 11.962,13.727Z"
android:fillColor="#FBFBFE"/>
<path
android:pathData="M17.922,19.688L20.311,22.077C20.21,22.092 20.105,22.1 19.999,22.1C18.84,22.1 17.899,21.16 17.899,20C17.899,19.894 17.907,19.79 17.922,19.688Z"
android:fillColor="#FBFBFE"/>
<path
android:pathData="M2.89,4.642L35.228,36.98C35.879,37.632 35.879,38.688 35.228,39.339L35.228,39.339C34.576,39.991 33.52,39.991 32.868,39.339L0.53,7.001C-0.121,6.35 -0.121,5.294 0.53,4.642C1.182,3.991 2.238,3.991 2.89,4.642Z"
android:fillColor="#FBFBFE"/>
</group>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:pathData="M4.209,1.999L37.355,35.145L35.145,37.355L1.999,4.209L4.209,1.999Z"
android:fillColor="#FBFBFE"
android:fillType="evenOdd"/>
<path
android:pathData="M7.869,5.703C3.82,9.142 1.25,14.271 1.25,20C1.25,30.03 9.126,38.221 19.031,38.725L19.041,38.733L19.047,38.726C19.363,38.742 19.681,38.75 20,38.75C20.32,38.75 20.638,38.742 20.954,38.726L20.96,38.733L20.97,38.725C26.306,38.453 31.053,35.951 34.297,32.132L32.079,29.913C30.228,32.166 27.759,33.891 24.931,34.831C26.854,32.438 28.243,29.75 29.097,26.931L26.534,24.368C25.642,28.517 23.465,32.438 20,35.474C15.763,31.76 13.451,26.722 13.063,21.563H23.728L20.603,18.438H13.063C13.22,16.35 13.692,14.282 14.479,12.313L12.102,9.936C10.844,12.632 10.12,15.52 9.93,18.438H4.453C4.872,14.209 6.978,10.477 10.087,7.922L7.869,5.703ZM15.069,34.831C11.952,30.951 10.239,26.295 9.93,21.563H4.453C5.07,27.779 9.331,32.924 15.069,34.831Z"
android:fillColor="#FBFBFE"
android:fillType="evenOdd"/>
<path
android:pathData="M13.678,7.093C14.106,6.433 14.569,5.791 15.069,5.169C14.263,5.437 13.486,5.769 12.744,6.159L10.448,3.863C12.985,2.358 15.907,1.434 19.031,1.275L19.041,1.267L19.047,1.274C19.363,1.258 19.681,1.25 20,1.25C20.32,1.25 20.638,1.258 20.954,1.274L20.96,1.267L20.97,1.275C30.875,1.779 38.75,9.97 38.75,20C38.75,23.489 37.798,26.755 36.138,29.553L33.842,27.257C34.752,25.525 35.346,23.601 35.548,21.563H30.071C30.033,22.146 29.974,22.728 29.893,23.308L25.023,18.438H26.938C26.55,13.278 24.238,8.24 20,4.526C18.361,5.963 17.01,7.598 15.947,9.361L13.678,7.093ZM30.071,18.438H35.548C34.931,12.221 30.67,7.076 24.931,5.169C28.049,9.049 29.762,13.705 30.071,18.438Z"
android:fillColor="#FBFBFE"
android:fillType="evenOdd"/>
</vector>
......@@ -3,29 +3,63 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/tor_bootstrap_background_gradient">
android:background="@drawable/tor_bootstrap_background_gradient"
android:paddingBottom="16dp">
<ProgressBar
android:id="@+id/tor_bootstrap_progress_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="6dp"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/settings_button"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginTop="26dp"
android:layout_marginEnd="20dp"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/settings"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/mozac_ic_settings" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/back_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:visibility="invisible"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/settings"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/mozac_ic_back" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/tor_connect_image"
......@@ -45,99 +79,139 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:text="@string/connection_assist_tor_connect_title"
android:textColor="#FBFBFE"
android:textFontWeight="400"
android:textSize="22sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tor_connect_image" />
app:layout_constraintTop_toBottomOf="@id/tor_connect_image"
app:layout_constraintVertical_bias="0.03" />
<TextView
android:id="@+id/connect_to_tor_description"
android:id="@+id/title_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="24dp"
android:lineSpacingExtra="6dp"
android:text="@string/preferences_tor_network_settings_explanation"
android:textColor="#FBFBFE"
android:textFontWeight="400"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title_large_text_view" />
app:layout_constraintTop_toBottomOf="@id/title_large_text_view"
app:layout_constraintVertical_bias="0.03" />
<TextView
android:id="@+id/connect_automatically"
android:layout_width="wrap_content"
android:id="@+id/quick_start_description"
android:layout_width="230dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:text="@string/connection_assist_always_connect_automatically_toggle_description"
android:textColor="#80FBFBFE"
android:textColor="#FBFBFE"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="@+id/quickstart_switch"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/quickstart_switch"
app:layout_constraintVertical_bias="1.25" />
app:layout_constraintTop_toBottomOf="@+id/title_description"
app:layout_constraintVertical_bias=".03" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/quickstart_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginStart="100dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="24dp"
android:enabled="false"
android:gravity="center"
app:thumbTint="#7D6298"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/connect_to_tor_description"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@+id/quick_start_description"
app:layout_constraintTop_toBottomOf="@id/title_description"
app:layout_constraintVertical_bias=".023"
app:layout_goneMarginEnd="6dp"
app:layout_goneMarginTop="9dp" />
<Button
android:id="@+id/tor_bootstrap_connect_button"
<TextView
android:id="@+id/unblock_the_internet_in_country_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="24dp"
android:text="@string/connection_assist_unblock_the_internet_in_country_or_region"
android:textColor="#FBFBFE"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/title_description" />
<androidx.appcompat.widget.AppCompatSpinner
android:id="@+id/country_drop_down"
style="@style/Widget.AppCompat.Spinner.Underlined"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="24dp"
android:textColor="#FBFBFE"
android:tooltipText="@string/connection_assist_share_my_location_country_or_region"
android:visibility="invisible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/unblock_the_internet_in_country_description" />
<ImageView
android:id="@+id/wordmarkLogo"
android:layout_width="160dp"
android:layout_height="160dp"
android:src="@mipmap/ic_launcher_round"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:contentDescription="" />
<Button
android:id="@+id/tor_bootstrap_button_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="8dp"
android:background="@drawable/rounded_corners"
android:backgroundTint="@color/connect_button_purple"
android:maxWidth="312dp"
android:minWidth="360dp"
android:text="@string/tor_bootstrap_connect"
android:textAllCaps="false"
android:textColor="#FBFBFE"
android:textFontWeight="500"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@id/tor_bootstrap_network_settings_button"
app:layout_constraintBottom_toTopOf="@id/tor_bootstrap_button_2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/quickstart_switch"
app:layout_constraintVertical_bias="1" />
<Button
android:id="@+id/tor_bootstrap_network_settings_button"
android:layout_width="match_parent"
android:id="@+id/tor_bootstrap_button_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="24dp"
android:layout_marginBottom="8dp"
android:background="@drawable/rounded_corners"
android:backgroundTint="@color/configure_connection_button_white"
android:maxWidth="312dp"
android:minWidth="360dp"
android:text="@string/connection_assist_configure_connection_button"
android:textAllCaps="false"
android:textColor="#15141A"
android:textFontWeight="500"
android:textSize="14sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
......
......
......@@ -344,5 +344,6 @@
<!-- Connection Assist -->
<color name="connect_button_purple">#9059FF</color>
<color name="configure_connection_button_white">#E1E0E7</color>
<color name="warning_yellow">#FFA436</color>
</resources>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment