[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [Git][tpo/applications/firefox-android][firefox-android-115.2.1-13.5-1] 3 commits: fixup! Implement Android-native Connection Assist UI



Title: GitLab

Dan Ballard pushed to branch firefox-android-115.2.1-13.5-1 at The Tor Project / Applications / firefox-android

Commits:

  • 333d9284
    by clairehurst at 2024-03-26T17:06:53-06:00
    fixup! Implement Android-native Connection Assist UI
    
  • 86815386
    by clairehurst at 2024-03-26T17:06:54-06:00
    fixup! Bug 41878: Add standalone Tor Bootstrap
    
  • 99f95c30
    by clairehurst at 2024-03-26T17:06:54-06:00
    fixup! Add Tor integration and UI
    

12 changed files:

Changes:

  • fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt
    ... ... @@ -168,6 +168,7 @@ import java.util.Locale
    168 168
     import androidx.navigation.fragment.findNavController
    
    169 169
     import mozilla.components.browser.engine.gecko.GeckoEngine
    
    170 170
     import mozilla.components.browser.state.selector.findCustomTab
    
    171
    +import org.mozilla.fenix.home.HomeFragment
    
    171 172
     import org.mozilla.geckoview.TorIntegrationAndroid
    
    172 173
     
    
    173 174
     /**
    
    ... ... @@ -815,6 +816,10 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, TorIn
    815 816
     
    
    816 817
         final override fun onBackPressed() {
    
    817 818
             supportFragmentManager.primaryNavigationFragment?.childFragmentManager?.fragments?.forEach {
    
    819
    +            if (it is HomeFragment){
    
    820
    +                finish()
    
    821
    +                return
    
    822
    +            }
    
    818 823
                 if (it is UserInteractionHandler && it.onBackPressed()) {
    
    819 824
                     return
    
    820 825
                 }
    

  • fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistFragment.kt
    ... ... @@ -4,11 +4,19 @@
    4 4
     
    
    5 5
     package org.mozilla.fenix.tor
    
    6 6
     
    
    7
    +import android.graphics.Color
    
    7 8
     import android.os.Build
    
    8 9
     import android.os.Bundle
    
    10
    +import android.text.SpannableString
    
    11
    +import android.text.Spanned
    
    12
    +import android.text.TextPaint
    
    13
    +import android.text.method.LinkMovementMethod
    
    14
    +import android.text.style.ClickableSpan
    
    15
    +import android.util.Log
    
    9 16
     import android.view.LayoutInflater
    
    10 17
     import android.view.View
    
    11 18
     import android.view.ViewGroup
    
    19
    +import androidx.appcompat.content.res.AppCompatResources
    
    12 20
     import androidx.fragment.app.Fragment
    
    13 21
     import androidx.fragment.app.viewModels
    
    14 22
     import androidx.lifecycle.Lifecycle
    
    ... ... @@ -22,6 +30,7 @@ import org.mozilla.fenix.ext.hideToolbar
    22 30
     
    
    23 31
     class TorConnectionAssistFragment : Fragment() {
    
    24 32
     
    
    33
    +    private val TAG = "TorConnectionAssistFrag"
    
    25 34
         private var _binding: FragmentTorConnectionAssistBinding? = null
    
    26 35
         private val binding get() = _binding!!
    
    27 36
     
    
    ... ... @@ -49,13 +58,14 @@ class TorConnectionAssistFragment : Fragment() {
    49 58
     
    
    50 59
             lifecycleScope.launch {
    
    51 60
                 repeatOnLifecycle(Lifecycle.State.STARTED) {
    
    52
    -                viewModel.torConnectState.collect {
    
    53
    -                    when (it) {
    
    54
    -                        TorConnectState.Initial -> showConfiguring()
    
    61
    +                viewModel.torConnectState.collect { torConnectState ->
    
    62
    +                    Log.d(TAG, "torConnectState is ${torConnectState.state}")
    
    63
    +                    when (torConnectState) {
    
    64
    +                        TorConnectState.Initial -> showSplash()
    
    55 65
                             TorConnectState.Configuring -> showConfiguring()
    
    56 66
                             TorConnectState.AutoBootstrapping -> showBootstrapping()
    
    57 67
                             TorConnectState.Bootstrapping -> showBootstrapping()
    
    58
    -                        TorConnectState.Error -> TODO()
    
    68
    +                        TorConnectState.Error -> showError()
    
    59 69
                             TorConnectState.Bootstrapped -> openHome()
    
    60 70
                             TorConnectState.Disabled -> openHome()
    
    61 71
                         }
    
    ... ... @@ -73,59 +83,302 @@ class TorConnectionAssistFragment : Fragment() {
    73 83
                 }
    
    74 84
             }
    
    75 85
     
    
    76
    -        viewModel.quickconnectToggle().observe(
    
    77
    -            viewLifecycleOwner
    
    86
    +        viewModel.quickstartToggle().observe(
    
    87
    +            viewLifecycleOwner,
    
    78 88
             ) {
    
    79
    -            binding.quickstartSwitch.isChecked = it
    
    89
    +            binding.quickstartSwitch.isChecked = it == true
    
    90
    +        }
    
    91
    +
    
    92
    +        binding.quickstartSwitch.setOnCheckedChangeListener { _, isChecked ->
    
    93
    +            viewModel.handleQuickstartChecked(isChecked)
    
    80 94
             }
    
    95
    +    }
    
    81 96
     
    
    97
    +
    
    98
    +    private fun showSplash() {
    
    99
    +        binding.torBootstrapProgressBar.visibility = View.GONE
    
    100
    +        binding.settingsButton.visibility = View.GONE
    
    101
    +        binding.backButton.visibility = View.GONE
    
    102
    +        binding.torConnectImage.visibility = View.GONE
    
    103
    +        binding.titleLargeTextView.visibility = View.GONE
    
    104
    +        binding.titleDescription.visibility = View.GONE
    
    105
    +        binding.quickStartDescription.visibility = View.GONE
    
    106
    +        binding.quickstartSwitch.visibility = View.GONE
    
    107
    +        binding.torBootstrapButton1.visibility = View.GONE
    
    108
    +        binding.torBootstrapButton2.visibility = View.GONE
    
    109
    +        binding.wordmarkLogo.visibility = View.VISIBLE
    
    110
    +    }
    
    111
    +
    
    112
    +
    
    113
    +    private fun showConfiguring() {
    
    114
    +        binding.wordmarkLogo.visibility = View.GONE
    
    115
    +
    
    116
    +        binding.torBootstrapProgressBar.visibility = View.INVISIBLE
    
    117
    +        binding.torBootstrapProgressBar.progress = 0
    
    118
    +        binding.backButton.visibility = View.INVISIBLE
    
    119
    +        binding.settingsButton.visibility = View.VISIBLE
    
    82 120
             binding.settingsButton.setOnClickListener {
    
    83 121
                 viewModel.cancelTorBootstrap()
    
    84 122
                 openSettings()
    
    85 123
             }
    
    124
    +        binding.torConnectImage.visibility = View.VISIBLE
    
    125
    +        binding.torConnectImage.setImageResource(R.drawable.connect)
    
    126
    +        binding.titleLargeTextView.visibility = View.VISIBLE
    
    127
    +        binding.titleLargeTextView.text = getString(R.string.connection_assist_tor_connect_title)
    
    128
    +        binding.titleDescription.visibility = View.VISIBLE
    
    129
    +        binding.titleDescription.text =
    
    130
    +            getString(R.string.preferences_tor_network_settings_explanation)
    
    131
    +        binding.quickStartDescription.visibility = View.VISIBLE
    
    132
    +        binding.quickstartSwitch.visibility = View.VISIBLE
    
    133
    +        binding.quickstartSwitch.isChecked = viewModel.quickstartToggle().value == true
    
    134
    +
    
    135
    +        binding.unblockTheInternetInCountryDescription.visibility = View.GONE
    
    136
    +        binding.countryDropDown.visibility = View.GONE
    
    86 137
     
    
    87
    -        binding.torBootstrapConnectButton.setOnClickListener {
    
    138
    +        binding.torBootstrapButton1.visibility = View.VISIBLE
    
    139
    +        binding.torBootstrapButton1.text = getString(R.string.tor_bootstrap_connect)
    
    140
    +        binding.torBootstrapButton1.setOnClickListener {
    
    88 141
                 viewModel.handleConnect(lifecycleScope = lifecycleScope)
    
    142
    +            showBootstrapping()
    
    89 143
             }
    
    90 144
     
    
    91
    -        binding.quickstartSwitch.setOnCheckedChangeListener { _, isChecked ->
    
    92
    -            viewModel.handleQuickstartChecked(isChecked)
    
    145
    +        binding.torBootstrapButton2.visibility = View.VISIBLE
    
    146
    +        binding.torBootstrapButton2.text =
    
    147
    +            getString(R.string.connection_assist_configure_connection_button)
    
    148
    +        binding.torBootstrapButton2.setOnClickListener {
    
    149
    +            viewModel.cancelTorBootstrap()
    
    150
    +            openTorNetworkSettings()
    
    93 151
             }
    
    94 152
         }
    
    95 153
     
    
    96
    -    private fun showConfiguring() {
    
    97
    -        binding.torBootstrapConnectButton.visibility = View.VISIBLE
    
    98
    -        binding.torBootstrapNetworkSettingsButton.text =
    
    154
    +    private fun showBootstrapping() {
    
    155
    +        binding.wordmarkLogo.visibility = View.GONE
    
    156
    +
    
    157
    +        binding.torBootstrapProgressBar.visibility = View.VISIBLE
    
    158
    +        binding.torBootstrapProgressBar.progress = 0
    
    159
    +        binding.backButton.visibility = View.INVISIBLE
    
    160
    +        binding.settingsButton.visibility = View.VISIBLE
    
    161
    +        binding.settingsButton.setOnClickListener {
    
    162
    +            viewModel.cancelTorBootstrap()
    
    163
    +            openSettings()
    
    164
    +        }
    
    165
    +        binding.torConnectImage.visibility = View.VISIBLE
    
    166
    +        binding.torConnectImage.setImageResource(R.drawable.connect)
    
    167
    +        binding.titleLargeTextView.visibility = View.VISIBLE
    
    168
    +        binding.titleLargeTextView.text = getString(R.string.connection_assist_connecting_title)
    
    169
    +        binding.titleDescription.visibility = View.VISIBLE
    
    170
    +        binding.titleDescription.text =
    
    171
    +            getString(R.string.preferences_tor_network_settings_explanation)
    
    172
    +        binding.quickstartSwitch.visibility = View.VISIBLE
    
    173
    +        binding.quickstartSwitch.isChecked = viewModel.quickstartToggle().value == true
    
    174
    +        binding.quickstartSwitch.jumpDrawablesToCurrentState()
    
    175
    +        binding.quickStartDescription.visibility = View.VISIBLE
    
    176
    +        binding.torBootstrapButton1.visibility = View.INVISIBLE
    
    177
    +        binding.torBootstrapButton2.visibility = View.VISIBLE
    
    178
    +        binding.torBootstrapButton2.text = getString(R.string.btn_cancel)
    
    179
    +        binding.torBootstrapButton2.setOnClickListener { viewModel.cancelTorBootstrap() }
    
    180
    +    }
    
    181
    +
    
    182
    +    private suspend fun showError() {
    
    183
    +        viewModel.torError.collect {
    
    184
    +            Log.d(
    
    185
    +                TAG,
    
    186
    +                "TorError: details = ${it?.details ?: "null details"}, message = ${it?.message ?: "null message"}",
    
    187
    +            )
    
    188
    +            when (viewModel.handleError(it)) {
    
    189
    +                ErrorScreen.CantConnectToInternet -> showCantConnectToInternet()
    
    190
    +                ErrorScreen.CantConnectToTorDirectly -> showCantConnectToTorDirectly()
    
    191
    +                ErrorScreen.WeCouldntFindYourLocation -> showWeCouldntFindYourLocation()
    
    192
    +                ErrorScreen.WereStillHavingTroubleConnecting -> showWereStillHavingTroubleConnecting()
    
    193
    +                ErrorScreen.WeWerentAbleToConnectAutomatically -> showWeWerentAbleToConnectAutomatically()
    
    194
    +                null -> {
    
    195
    +                    // no op
    
    196
    +                    Log.d(TAG, "ErrorScreen: null, nothing shown")
    
    197
    +                }
    
    198
    +            }
    
    199
    +        }
    
    200
    +    }
    
    201
    +
    
    202
    +    private fun showCantConnectToInternet() {
    
    203
    +        Log.d(TAG, "showCantConnectToInternet()")
    
    204
    +        binding.torBootstrapProgressBar.visibility = View.VISIBLE
    
    205
    +        binding.torBootstrapProgressBar.progressTintList =
    
    206
    +            AppCompatResources.getColorStateList(requireContext(), R.color.warning_yellow)
    
    207
    +        binding.torBootstrapProgressBar.progress = 100
    
    208
    +
    
    209
    +        binding.backButton.visibility = View.VISIBLE
    
    210
    +        binding.backButton.setOnClickListener {
    
    211
    +            showConfiguring()
    
    212
    +        }
    
    213
    +
    
    214
    +        binding.torConnectImage.setImageResource(R.drawable.globe_broken)
    
    215
    +        binding.titleLargeTextView.text = getString(R.string.connection_assist_internet_error_title)
    
    216
    +
    
    217
    +        val learnMore: String = getString(R.string.connection_assist_internet_error_learn_more)
    
    218
    +        val internetErrorDescription: String = getString(
    
    219
    +            R.string.connection_assist_internet_error_description,
    
    220
    +            learnMore,
    
    221
    +        )
    
    222
    +        handleDescriptionWithClickable(internetErrorDescription, learnMore)
    
    223
    +
    
    224
    +        binding.quickStartDescription.visibility = View.GONE
    
    225
    +        binding.quickstartSwitch.visibility = View.GONE
    
    226
    +
    
    227
    +        binding.torBootstrapButton1.visibility = View.VISIBLE
    
    228
    +        binding.torBootstrapButton1.text =
    
    229
    +            getString(R.string.connection_assist_internet_error_try_again)
    
    230
    +        binding.torBootstrapButton1.setOnClickListener {
    
    231
    +            showTryingAgain()
    
    232
    +            viewModel.handleConnect(lifecycleScope = lifecycleScope)
    
    233
    +        }
    
    234
    +
    
    235
    +        binding.torBootstrapButton2.text =
    
    99 236
                 getString(R.string.connection_assist_configure_connection_button)
    
    100
    -        binding.torBootstrapNetworkSettingsButton.setOnClickListener {
    
    237
    +        binding.torBootstrapButton2.setOnClickListener {
    
    101 238
                 openTorNetworkSettings()
    
    102 239
             }
    
    103 240
         }
    
    104 241
     
    
    105
    -    private fun showBootstrapping() {
    
    106
    -        binding.torBootstrapConnectButton.visibility = View.INVISIBLE
    
    107
    -        binding.torBootstrapNetworkSettingsButton.text = getString(R.string.btn_cancel)
    
    108
    -        binding.torBootstrapNetworkSettingsButton.setOnClickListener {
    
    242
    +    private fun showTryingAgain() {
    
    243
    +        Log.d(TAG, "showTryingAgain()")
    
    244
    +        binding.torBootstrapProgressBar.progress = 0
    
    245
    +        binding.torBootstrapProgressBar.visibility = View.VISIBLE
    
    246
    +        binding.torBootstrapProgressBar.progressTintList = null
    
    247
    +        binding.torConnectImage.setImageResource(R.drawable.connect)
    
    248
    +        binding.titleLargeTextView.text =
    
    249
    +            getString(R.string.connection_assist_trying_again_waiting_title)
    
    250
    +
    
    251
    +        binding.quickstartSwitch.visibility = View.GONE
    
    252
    +        binding.quickStartDescription.visibility = View.GONE
    
    253
    +        binding.torBootstrapButton1.visibility = View.INVISIBLE
    
    254
    +        binding.torBootstrapButton2.visibility = View.VISIBLE
    
    255
    +        binding.torBootstrapButton2.text = getString(R.string.btn_cancel)
    
    256
    +        binding.torBootstrapButton2.setOnClickListener {
    
    109 257
                 viewModel.cancelTorBootstrap()
    
    258
    +            showConfiguring()
    
    110 259
             }
    
    111 260
         }
    
    112 261
     
    
    113
    -    private fun openSettings(preferenceToScrollTo: String? = null) {
    
    114
    -        findNavController().navigate(
    
    115
    -            TorConnectionAssistFragmentDirections
    
    116
    -                .actionTorConnectionAssistFragmentToSettingsFragment(preferenceToScrollTo),
    
    262
    +    private fun showCantConnectToTorDirectly() {
    
    263
    +        Log.d(TAG, "showCantConnectToTorDirectly()")
    
    264
    +        binding.torBootstrapProgressBar.visibility = View.VISIBLE
    
    265
    +        binding.torBootstrapProgressBar.progressTintList =
    
    266
    +            AppCompatResources.getColorStateList(requireContext(), R.color.warning_yellow)
    
    267
    +        binding.torBootstrapProgressBar.progress = 100
    
    268
    +
    
    269
    +        binding.backButton.visibility = View.VISIBLE
    
    270
    +        binding.backButton.setOnClickListener {
    
    271
    +            showConfiguring()
    
    272
    +        }
    
    273
    +
    
    274
    +        binding.torConnectImage.setImageResource(R.drawable.globe_broken)
    
    275
    +        binding.titleLargeTextView.text =
    
    276
    +            getString(R.string.connection_assist_cant_connect_to_tor_title)
    
    277
    +
    
    278
    +        val learnMore: String = getString(R.string.connection_assist_internet_error_learn_more)
    
    279
    +        val tryABridge: String = getString(
    
    280
    +            R.string.connection_assist_try_a_bridge_description,
    
    281
    +            learnMore,
    
    117 282
             )
    
    283
    +        handleDescriptionWithClickable(tryABridge, learnMore)
    
    284
    +
    
    285
    +        binding.quickStartDescription.visibility = View.GONE
    
    286
    +        binding.quickstartSwitch.visibility = View.GONE
    
    287
    +        binding.unblockTheInternetInCountryDescription.visibility = View.VISIBLE
    
    288
    +        binding.countryDropDown.visibility = View.VISIBLE
    
    289
    +        // TODO implement countryDropDown
    
    290
    +
    
    291
    +        binding.torBootstrapButton1.visibility = View.VISIBLE
    
    292
    +        binding.torBootstrapButton1.text = getString(R.string.connection_assist_try_a_bridge_button)
    
    293
    +        binding.torBootstrapButton1.setOnClickListener {
    
    294
    +            viewModel.tryABridge()
    
    295
    +            showTryingABridge()
    
    296
    +        }
    
    297
    +        binding.torBootstrapButton2.visibility = View.GONE
    
    118 298
         }
    
    119 299
     
    
    120
    -    private fun openTorNetworkSettings() {
    
    121
    -        findNavController().navigate(
    
    122
    -            TorConnectionAssistFragmentDirections
    
    123
    -                .actionTorConnectionAssistFragmentToTorNetworkSettings(),
    
    300
    +    private fun showTryingABridge() {
    
    301
    +        Log.d(TAG, "showTryingABridge()")
    
    302
    +        // TODO(Not implemented)
    
    303
    +        binding.torBootstrapButton2.setOnClickListener {
    
    304
    +            showTryingABridge()
    
    305
    +        }
    
    306
    +    }
    
    307
    +
    
    308
    +    private fun showWeCouldntFindYourLocation() {
    
    309
    +        Log.d(TAG, "showWeCouldntFindYourLocation()")
    
    310
    +        // TODO(Not implemented)
    
    311
    +        binding.torBootstrapButton2.setOnClickListener {
    
    312
    +            showTryingABridge()
    
    313
    +        }
    
    314
    +    }
    
    315
    +
    
    316
    +    private fun showWereStillHavingTroubleConnecting() {
    
    317
    +        Log.d(TAG, "showWereStillHavingTroubleConnecting()")
    
    318
    +        TODO("Not yet implemented")
    
    319
    +    }
    
    320
    +
    
    321
    +    private fun showTryingOneMoreTime() {
    
    322
    +        Log.d(TAG, "showTryingOneMoreTime()")
    
    323
    +        TODO("Not yet implemented")
    
    324
    +    }
    
    325
    +
    
    326
    +    private fun showWeWerentAbleToConnectAutomatically() {
    
    327
    +        Log.d(TAG, "showWeWerentAbleToConnectAutomatically()")
    
    328
    +        TODO("Not yet implemented")
    
    329
    +    }
    
    330
    +
    
    331
    +    private fun showUnknownError() {
    
    332
    +        Log.d(TAG, "showUnknownError()")
    
    333
    +        TODO("Not yet implemented")
    
    334
    +    }
    
    335
    +
    
    336
    +    /**
    
    337
    +     * from https://stackoverflow.com/questions/10696986/how-to-set-the-part-of-the-text-view-is-clickable
    
    338
    +     */
    
    339
    +    private fun handleDescriptionWithClickable(errorDescription: String, learnMore: String) {
    
    340
    +        val errorDescriptionSpannableString = SpannableString(errorDescription)
    
    341
    +        val clickableSpan: ClickableSpan = object : ClickableSpan() {
    
    342
    +            override fun onClick(textView: View) {
    
    343
    +                showLearnMore()
    
    344
    +            }
    
    345
    +
    
    346
    +            override fun updateDrawState(drawState: TextPaint) {
    
    347
    +                super.updateDrawState(drawState)
    
    348
    +                drawState.isUnderlineText = true
    
    349
    +            }
    
    350
    +        }
    
    351
    +        errorDescriptionSpannableString.setSpan(
    
    352
    +            clickableSpan,
    
    353
    +            errorDescription.length - learnMore.length,
    
    354
    +            errorDescription.length,
    
    355
    +            Spanned.SPAN_EXCLUSIVE_EXCLUSIVE,
    
    124 356
             )
    
    357
    +        binding.titleDescription.text = errorDescriptionSpannableString
    
    358
    +        binding.titleDescription.movementMethod = LinkMovementMethod.getInstance()
    
    359
    +        binding.titleDescription.highlightColor = Color.TRANSPARENT
    
    360
    +    }
    
    361
    +
    
    362
    +    private fun showLearnMore() {
    
    363
    +        //TODO("Not yet implemented")
    
    125 364
         }
    
    126 365
     
    
    127 366
         private fun openHome() {
    
    367
    +        Log.d(TAG, "openHome()") //This doesn't seem to be ever called
    
    128 368
             findNavController().navigate(TorConnectionAssistFragmentDirections.actionStartupHome())
    
    129 369
         }
    
    130 370
     
    
    371
    +    private fun openSettings(preferenceToScrollTo: String? = null) {
    
    372
    +        findNavController().navigate(
    
    373
    +            TorConnectionAssistFragmentDirections.actionTorConnectionAssistFragmentToSettingsFragment(
    
    374
    +                preferenceToScrollTo,
    
    375
    +            ),
    
    376
    +        )
    
    377
    +    }
    
    378
    +
    
    379
    +    private fun openTorNetworkSettings() {
    
    380
    +        findNavController().navigate(
    
    381
    +            TorConnectionAssistFragmentDirections.actionTorConnectionAssistFragmentToTorNetworkSettings(),
    
    382
    +        )
    
    383
    +    }
    
    131 384
     }

  • fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistViewModel.kt
    ... ... @@ -26,24 +26,30 @@ class TorConnectionAssistViewModel(
    26 26
         private val _torConnectState = MutableStateFlow(TorConnectState.Initial)
    
    27 27
         internal val torConnectState: StateFlow<TorConnectState> = _torConnectState
    
    28 28
     
    
    29
    -    init {
    
    30
    -        _torController.registerTorListener(this)
    
    31
    -    }
    
    29
    +    private val _torError = MutableStateFlow(_torController.getLastErrorState())
    
    30
    +    internal val torError: StateFlow<TorError?> = _torError
    
    32 31
     
    
    33 32
         private val _progress = MutableLiveData(0)
    
    34 33
         fun progress(): LiveData<Int> {
    
    35 34
             return _progress
    
    36 35
         }
    
    37 36
     
    
    38
    -    private val _quickconnectToggle = MutableLiveData(_torController.quickstart)
    
    39
    -    fun quickconnectToggle(): LiveData<Boolean> {
    
    40
    -        return _quickconnectToggle
    
    37
    +    private val _quickStartToggle = MutableLiveData<Boolean>() // don't initialize with quickstart off the bat
    
    38
    +    fun quickstartToggle(): LiveData<Boolean?> {
    
    39
    +        _quickStartToggle.value = _torController.quickstart // quickstart isn't ready until torSettings is ready
    
    40
    +        return _quickStartToggle
    
    41
    +    }
    
    42
    +
    
    43
    +    init {
    
    44
    +        Log.d(TAG, "initiating TorConnectionAssistViewModel")
    
    45
    +        _torController.registerTorListener(this)
    
    41 46
         }
    
    42 47
     
    
    43 48
         fun handleConnect(
    
    44 49
             withDebugLogging: Boolean = false,
    
    45 50
             lifecycleScope: LifecycleCoroutineScope? = null,
    
    46 51
         ) {
    
    52
    +        Log.d(TAG, "handleConnect initiatingTorBootstrap with lifecycleScope = $lifecycleScope")
    
    47 53
             _torController.initiateTorBootstrap(
    
    48 54
                 withDebugLogging = withDebugLogging,
    
    49 55
                 lifecycleScope = lifecycleScope,
    
    ... ... @@ -52,6 +58,7 @@ class TorConnectionAssistViewModel(
    52 58
     
    
    53 59
         fun handleQuickstartChecked(checked: Boolean) {
    
    54 60
             _torController.quickstart = checked
    
    61
    +        _quickStartToggle.value = checked
    
    55 62
         }
    
    56 63
     
    
    57 64
         fun cancelTorBootstrap() {
    
    ... ... @@ -66,7 +73,6 @@ class TorConnectionAssistViewModel(
    66 73
         override fun onTorConnected() {
    
    67 74
             Log.d(TAG, "onTorConnected()")
    
    68 75
             _torController.unregisterTorListener(this)
    
    69
    -        _torConnectState.value = _torController.lastKnownStatus
    
    70 76
         }
    
    71 77
     
    
    72 78
         override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?) {
    
    ... ... @@ -75,12 +81,32 @@ class TorConnectionAssistViewModel(
    75 81
                 _progress.value = progress.toInt()
    
    76 82
             }
    
    77 83
             _torConnectState.value = _torController.lastKnownStatus
    
    84
    +        _torError.value = _torController.getLastErrorState()
    
    78 85
         }
    
    79 86
     
    
    80 87
         override fun onTorStopped() {
    
    81 88
             Log.d(TAG, "onTorStopped()")
    
    82
    -        _progress.value = 0
    
    83
    -        _torConnectState.value = _torController.lastKnownStatus
    
    84 89
         }
    
    85 90
     
    
    91
    +    internal fun handleError(it: TorError?): ErrorScreen? {
    
    92
    +        // TODO(Only partly implemented)
    
    93
    +        if (it?.message == null){
    
    94
    +            return null
    
    95
    +        }
    
    96
    +        return ErrorScreen.CantConnectToInternet
    
    97
    +    }
    
    98
    +
    
    99
    +    fun tryABridge() {
    
    100
    +        // TODO("Try a bridge not enabled")
    
    101
    +        // connect to bridge based on country
    
    102
    +        // try connecting
    
    103
    +    }
    
    104
    +}
    
    105
    +
    
    106
    +internal enum class ErrorScreen {
    
    107
    +    CantConnectToInternet,
    
    108
    +    CantConnectToTorDirectly,
    
    109
    +    WeCouldntFindYourLocation,
    
    110
    +    WereStillHavingTroubleConnecting,
    
    111
    +    WeWerentAbleToConnectAutomatically,
    
    86 112
     }

  • fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt
    ... ... @@ -12,6 +12,10 @@ interface TorEvents {
    12 12
         fun onTorStatusUpdate(entry: String?, status: String?, progress: Double? = 0.0)
    
    13 13
         fun onTorStopped()
    
    14 14
     }
    
    15
    +class TorError(
    
    16
    +    var message: String,
    
    17
    +    var details: String
    
    18
    +) { }
    
    15 19
     
    
    16 20
     internal enum class TorStatus(val status: String) {
    
    17 21
         OFF("OFF"),
    
    ... ... @@ -59,6 +63,8 @@ interface TorController: TorEvents {
    59 63
         override fun onTorStatusUpdate(entry: String?, status: String?, progress: Double?)
    
    60 64
         override fun onTorStopped()
    
    61 65
     
    
    66
    +    fun getLastErrorState() : TorError?
    
    67
    +
    
    62 68
         fun registerTorListener(l: TorEvents)
    
    63 69
         fun unregisterTorListener(l: TorEvents)
    
    64 70
     
    

  • fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt
    ... ... @@ -53,6 +53,7 @@ class TorControllerGV(
    53 53
         private var torListeners = mutableListOf<TorEvents>()
    
    54 54
     
    
    55 55
         internal var lastKnownStatus = TorConnectState.Initial
    
    56
    +    internal var lastKnownError: TorError? = null
    
    56 57
         private var wasTorBootstrapped = false
    
    57 58
         private var isTorRestarting = false
    
    58 59
     
    
    ... ... @@ -210,6 +211,7 @@ class TorControllerGV(
    210 211
     
    
    211 212
         override fun setTorStopped() {
    
    212 213
             lastKnownStatus = TorConnectState.Configuring
    
    214
    +        onTorStatusUpdate(null, lastKnownStatus.toString(), 0.0)
    
    213 215
             onTorStopped()
    
    214 216
         }
    
    215 217
     
    
    ... ... @@ -227,6 +229,10 @@ class TorControllerGV(
    227 229
             }
    
    228 230
         }
    
    229 231
     
    
    232
    +    override fun getLastErrorState() : TorError? {
    
    233
    +        return lastKnownError
    
    234
    +    }
    
    235
    +
    
    230 236
         // TorEventsBootstrapStateChangeListener -> (lastKnowStatus, TorEvents)
    
    231 237
         // Handle events from GeckoView TorAndroidIntegration and map to TorEvents based events
    
    232 238
         // and state for firefox-android (designed for tor-android-service)
    
    ... ... @@ -263,7 +269,7 @@ class TorControllerGV(
    263 269
             }
    
    264 270
     
    
    265 271
             lastKnownStatus = newState
    
    266
    -
    
    272
    +        onTorStatusUpdate(null, newStateVal, null)
    
    267 273
         }
    
    268 274
     
    
    269 275
         // TorEventsBootstrapStateChangeListener
    
    ... ... @@ -290,7 +296,7 @@ class TorControllerGV(
    290 296
     
    
    291 297
         // TorEventsBootstrapStateChangeListener
    
    292 298
         override fun onBootstrapError(message: String?, details: String?) {
    
    293
    -        lastKnownStatus = TorConnectState.Error
    
    299
    +        lastKnownError = TorError(message ?: "", details ?: "")
    
    294 300
             onBootstrapStateChange(TorConnectState.Error.state)
    
    295 301
         }
    
    296 302
     
    

  • fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerTAS.kt
    ... ... @@ -330,4 +330,10 @@ class TorControllerTAS (private val context: Context): TorController {
    330 330
         companion object {
    
    331 331
             const val torServiceResponseTimeout = 5000L
    
    332 332
         }
    
    333
    +
    
    334
    +    // Compat with TorControlGV Stubs
    
    335
    +
    
    336
    +    override fun getLastErrorState() : TorError? {
    
    337
    +        return null;
    
    338
    +    }
    
    333 339
     }

  • fenix/app/src/main/res/drawable/connect_broken.xml
    1
    +<vector xmlns:android="http://schemas.android.com/apk/res/android"
    
    2
    +    android:width="40dp"
    
    3
    +    android:height="40dp"
    
    4
    +    android:viewportWidth="40"
    
    5
    +    android:viewportHeight="40">
    
    6
    +  <group>
    
    7
    +    <clip-path
    
    8
    +        android:pathData="M0,0h40v40h-40z"/>
    
    9
    +    <path
    
    10
    +        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"
    
    11
    +        android:fillColor="#FBFBFE"/>
    
    12
    +    <path
    
    13
    +        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"
    
    14
    +        android:fillColor="#FBFBFE"/>
    
    15
    +    <path
    
    16
    +        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"
    
    17
    +        android:fillColor="#FBFBFE"/>
    
    18
    +    <path
    
    19
    +        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"
    
    20
    +        android:fillColor="#FBFBFE"/>
    
    21
    +    <path
    
    22
    +        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"
    
    23
    +        android:fillColor="#FBFBFE"/>
    
    24
    +    <path
    
    25
    +        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"
    
    26
    +        android:fillColor="#FBFBFE"/>
    
    27
    +    <path
    
    28
    +        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"
    
    29
    +        android:fillColor="#FBFBFE"/>
    
    30
    +    <path
    
    31
    +        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"
    
    32
    +        android:fillColor="#FBFBFE"/>
    
    33
    +    <path
    
    34
    +        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"
    
    35
    +        android:fillColor="#FBFBFE"/>
    
    36
    +  </group>
    
    37
    +</vector>

  • fenix/app/src/main/res/drawable/globe_broken.xml
    1
    +<vector xmlns:android="http://schemas.android.com/apk/res/android"
    
    2
    +    android:width="40dp"
    
    3
    +    android:height="40dp"
    
    4
    +    android:viewportWidth="40"
    
    5
    +    android:viewportHeight="40">
    
    6
    +  <path
    
    7
    +      android:pathData="M4.209,1.999L37.355,35.145L35.145,37.355L1.999,4.209L4.209,1.999Z"
    
    8
    +      android:fillColor="#FBFBFE"
    
    9
    +      android:fillType="evenOdd"/>
    
    10
    +  <path
    
    11
    +      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"
    
    12
    +      android:fillColor="#FBFBFE"
    
    13
    +      android:fillType="evenOdd"/>
    
    14
    +  <path
    
    15
    +      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"
    
    16
    +      android:fillColor="#FBFBFE"
    
    17
    +      android:fillType="evenOdd"/>
    
    18
    +</vector>

  • fenix/app/src/main/res/drawable/tor_bootstrap_background_gradient.xml
    ... ... @@ -7,9 +7,9 @@
    7 7
             <shape>
    
    8 8
                 <gradient
    
    9 9
                         android:angle="225"
    
    10
    -                    android:startColor="#FF7329A4"
    
    11
    -                    android:centerColor="#FF3A3274"
    
    12
    -                    android:endColor="#FF3A3274"
    
    10
    +                    android:startColor="@color/backgroundGradientLight"
    
    11
    +                    android:centerColor="@color/backgroundGradientDark"
    
    12
    +                    android:endColor="@color/backgroundGradientDark"
    
    13 13
                         android:type="linear" />
    
    14 14
             </shape>
    
    15 15
         </item>
    

  • fenix/app/src/main/res/layout/fragment_tor_connection_assist.xml
    ... ... @@ -3,29 +3,63 @@
    3 3
        - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
    
    4 4
     <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    
    5 5
         xmlns:app="http://schemas.android.com/apk/res-auto"
    
    6
    +    xmlns:tools="http://schemas.android.com/tools"
    
    6 7
         android:layout_width="match_parent"
    
    7 8
         android:layout_height="match_parent"
    
    8
    -    android:background="">"@drawable/tor_bootstrap_background_gradient">
    
    9
    +    android:background="">"@drawable/tor_bootstrap_background_gradient"
    
    10
    +    android:paddingBottom="16dp">
    
    9 11
     
    
    10 12
         <ProgressBar
    
    11 13
             android:id="@+id/tor_bootstrap_progress_bar"
    
    12 14
             style="?android:attr/progressBarStyleHorizontal"
    
    13 15
             android:layout_width="match_parent"
    
    14 16
             android:layout_height="6dp"
    
    17
    +        android:visibility="invisible"
    
    15 18
             app:layout_constraintEnd_toEndOf="parent"
    
    16 19
             app:layout_constraintStart_toStartOf="parent"
    
    17 20
             app:layout_constraintTop_toTopOf="parent" />
    
    18 21
     
    
    19
    -    <ImageView
    
    22
    +    <androidx.constraintlayout.widget.ConstraintLayout
    
    20 23
             android:id="@+id/settings_button"
    
    21
    -        android:layout_width="24dp"
    
    22
    -        android:layout_height="24dp"
    
    23
    -        android:layout_marginTop="26dp"
    
    24
    -        android:layout_marginEnd="20dp"
    
    25
    -        android:contentDescription="@string/settings"
    
    24
    +        android:layout_width="48dp"
    
    25
    +        android:layout_height="48dp"
    
    26
    +        android:layout_marginTop="8dp"
    
    27
    +        android:layout_marginEnd="8dp"
    
    26 28
             app:layout_constraintEnd_toEndOf="parent"
    
    27
    -        app:layout_constraintTop_toTopOf="parent"
    
    28
    -        app:srcCompat="@drawable/mozac_ic_settings" />
    
    29
    +        app:layout_constraintTop_toTopOf="parent">
    
    30
    +
    
    31
    +        <ImageView
    
    32
    +            android:layout_width="wrap_content"
    
    33
    +            android:layout_height="wrap_content"
    
    34
    +            android:contentDescription="@string/settings"
    
    35
    +            app:layout_constraintBottom_toBottomOf="parent"
    
    36
    +            app:layout_constraintEnd_toEndOf="parent"
    
    37
    +            app:layout_constraintStart_toStartOf="parent"
    
    38
    +            app:layout_constraintTop_toTopOf="parent"
    
    39
    +            app:srcCompat="@drawable/mozac_ic_settings" />
    
    40
    +    </androidx.constraintlayout.widget.ConstraintLayout>
    
    41
    +
    
    42
    +    <androidx.constraintlayout.widget.ConstraintLayout
    
    43
    +        android:id="@+id/back_button"
    
    44
    +        android:layout_width="48dp"
    
    45
    +        android:layout_height="48dp"
    
    46
    +        android:layout_marginStart="8dp"
    
    47
    +        android:layout_marginTop="8dp"
    
    48
    +        android:visibility="invisible"
    
    49
    +        app:layout_constraintStart_toStartOf="parent"
    
    50
    +        app:layout_constraintTop_toTopOf="parent">
    
    51
    +
    
    52
    +        <ImageView
    
    53
    +            android:layout_width="wrap_content"
    
    54
    +            android:layout_height="wrap_content"
    
    55
    +            android:contentDescription="@string/settings"
    
    56
    +            app:layout_constraintBottom_toBottomOf="parent"
    
    57
    +            app:layout_constraintEnd_toEndOf="parent"
    
    58
    +            app:layout_constraintStart_toStartOf="parent"
    
    59
    +            app:layout_constraintTop_toTopOf="parent"
    
    60
    +            app:srcCompat="@drawable/mozac_ic_back" />
    
    61
    +    </androidx.constraintlayout.widget.ConstraintLayout>
    
    62
    +
    
    29 63
     
    
    30 64
         <ImageView
    
    31 65
             android:id="@+id/tor_connect_image"
    
    ... ... @@ -45,99 +79,139 @@
    45 79
             android:layout_width="match_parent"
    
    46 80
             android:layout_height="wrap_content"
    
    47 81
             android:layout_marginStart="24dp"
    
    48
    -        android:layout_marginTop="24dp"
    
    49 82
             android:layout_marginEnd="24dp"
    
    50 83
             android:text="@string/connection_assist_tor_connect_title"
    
    51 84
             android:textColor="#FBFBFE"
    
    52
    -        android:textFontWeight="400"
    
    53 85
             android:textSize="22sp"
    
    86
    +        app:layout_constraintBottom_toBottomOf="parent"
    
    54 87
             app:layout_constraintEnd_toEndOf="parent"
    
    55 88
             app:layout_constraintStart_toStartOf="parent"
    
    56
    -        app:layout_constraintTop_toBottomOf="@id/tor_connect_image" />
    
    89
    +        app:layout_constraintTop_toBottomOf="@id/tor_connect_image"
    
    90
    +        app:layout_constraintVertical_bias="0.03" />
    
    57 91
     
    
    58 92
         <TextView
    
    59
    -        android:id="@+id/connect_to_tor_description"
    
    93
    +        android:id="@+id/title_description"
    
    60 94
             android:layout_width="match_parent"
    
    61 95
             android:layout_height="wrap_content"
    
    62 96
             android:layout_marginStart="24dp"
    
    63
    -        android:layout_marginTop="16dp"
    
    64 97
             android:layout_marginEnd="24dp"
    
    98
    +        android:lineSpacingExtra="6dp"
    
    65 99
             android:text="@string/preferences_tor_network_settings_explanation"
    
    66 100
             android:textColor="#FBFBFE"
    
    67
    -        android:textFontWeight="400"
    
    68 101
             android:textSize="14sp"
    
    102
    +        app:layout_constraintBottom_toBottomOf="parent"
    
    69 103
             app:layout_constraintEnd_toEndOf="parent"
    
    70 104
             app:layout_constraintHorizontal_bias="0.0"
    
    71 105
             app:layout_constraintStart_toStartOf="parent"
    
    72
    -        app:layout_constraintTop_toBottomOf="@id/title_large_text_view" />
    
    106
    +        app:layout_constraintTop_toBottomOf="@id/title_large_text_view"
    
    107
    +        app:layout_constraintVertical_bias="0.03" />
    
    108
    +
    
    73 109
     
    
    74 110
         <TextView
    
    75
    -        android:id="@+id/connect_automatically"
    
    76
    -        android:layout_width="wrap_content"
    
    111
    +        android:id="@+id/quick_start_description"
    
    112
    +        android:layout_width="230dp"
    
    77 113
             android:layout_height="wrap_content"
    
    78 114
             android:layout_marginStart="24dp"
    
    79
    -        android:layout_marginTop="24dp"
    
    80 115
             android:text="@string/connection_assist_always_connect_automatically_toggle_description"
    
    81
    -        android:textColor="#80FBFBFE"
    
    116
    +        android:textColor="#FBFBFE"
    
    82 117
             android:textSize="14sp"
    
    83
    -        app:layout_constraintBottom_toBottomOf="@+id/quickstart_switch"
    
    118
    +        app:layout_constraintBottom_toBottomOf="parent"
    
    84 119
             app:layout_constraintStart_toStartOf="parent"
    
    85
    -        app:layout_constraintTop_toTopOf="@+id/quickstart_switch"
    
    86
    -        app:layout_constraintVertical_bias="1.25" />
    
    120
    +        app:layout_constraintTop_toBottomOf="@+id/title_description"
    
    121
    +        app:layout_constraintVertical_bias=".03" />
    
    87 122
     
    
    88 123
         <androidx.appcompat.widget.SwitchCompat
    
    89 124
             android:id="@+id/quickstart_switch"
    
    90 125
             android:layout_width="wrap_content"
    
    91 126
             android:layout_height="wrap_content"
    
    92
    -        android:layout_marginTop="24dp"
    
    127
    +        android:layout_marginStart="100dp"
    
    93 128
             android:layout_marginEnd="24dp"
    
    94 129
             android:layout_marginBottom="24dp"
    
    95
    -        android:enabled="false"
    
    96 130
             android:gravity="center"
    
    97
    -        app:thumbTint="#7D6298"
    
    131
    +        app:layout_constraintBottom_toBottomOf="parent"
    
    98 132
             app:layout_constraintEnd_toEndOf="parent"
    
    99
    -        app:layout_constraintTop_toBottomOf="@id/connect_to_tor_description"
    
    133
    +        app:layout_constraintHorizontal_bias="0"
    
    134
    +        app:layout_constraintStart_toEndOf="@+id/quick_start_description"
    
    135
    +        app:layout_constraintTop_toBottomOf="@id/title_description"
    
    136
    +        app:layout_constraintVertical_bias=".023"
    
    100 137
             app:layout_goneMarginEnd="6dp"
    
    101 138
             app:layout_goneMarginTop="9dp" />
    
    102 139
     
    
    103
    -    <Button
    
    104
    -        android:id="@+id/tor_bootstrap_connect_button"
    
    140
    +    <TextView
    
    141
    +        android:id="@+id/unblock_the_internet_in_country_description"
    
    142
    +        android:layout_width="match_parent"
    
    143
    +        android:layout_height="wrap_content"
    
    144
    +        android:layout_marginStart="24dp"
    
    145
    +        android:layout_marginTop="24dp"
    
    146
    +        android:layout_marginEnd="24dp"
    
    147
    +        android:text="@string/connection_assist_unblock_the_internet_in_country_or_region"
    
    148
    +        android:textColor="#FBFBFE"
    
    149
    +        android:visibility="invisible"
    
    150
    +        app:layout_constraintEnd_toEndOf="parent"
    
    151
    +        app:layout_constraintStart_toStartOf="parent"
    
    152
    +        app:layout_constraintTop_toBottomOf="@id/title_description" />
    
    153
    +
    
    154
    +    <androidx.appcompat.widget.AppCompatSpinner
    
    155
    +        android:id="@+id/country_drop_down"
    
    156
    +        style="@style/Widget.AppCompat.Spinner.Underlined"
    
    105 157
             android:layout_width="match_parent"
    
    106 158
             android:layout_height="wrap_content"
    
    107 159
             android:layout_marginStart="24dp"
    
    160
    +        android:layout_marginTop="8dp"
    
    161
    +        android:layout_marginEnd="24dp"
    
    162
    +        android:textColor="#FBFBFE"
    
    163
    +        android:tooltipText="@string/connection_assist_share_my_location_country_or_region"
    
    164
    +        android:visibility="invisible"
    
    165
    +        app:layout_constraintEnd_toEndOf="parent"
    
    166
    +        app:layout_constraintStart_toStartOf="parent"
    
    167
    +        app:layout_constraintTop_toBottomOf="@id/unblock_the_internet_in_country_description" />
    
    168
    +
    
    169
    +    <ImageView
    
    170
    +        android:id="@+id/wordmarkLogo"
    
    171
    +        android:layout_width="160dp"
    
    172
    +        android:layout_height="160dp"
    
    173
    +        android:src="">"@mipmap/ic_launcher_round"
    
    174
    +
    
    175
    +        app:layout_constraintBottom_toBottomOf="parent"
    
    176
    +        app:layout_constraintEnd_toEndOf="parent"
    
    177
    +        app:layout_constraintStart_toStartOf="parent"
    
    178
    +        app:layout_constraintTop_toTopOf="parent"
    
    179
    +        android:contentDescription="" />
    
    180
    +
    
    181
    +    <Button
    
    182
    +        android:id="@+id/tor_bootstrap_button_1"
    
    183
    +        android:layout_width="wrap_content"
    
    184
    +        android:layout_height="wrap_content"
    
    185
    +        android:layout_marginStart="24dp"
    
    108 186
             android:layout_marginEnd="24dp"
    
    109 187
             android:layout_marginBottom="8dp"
    
    110 188
             android:background="">"@drawable/rounded_corners"
    
    111 189
             android:backgroundTint="@color/connect_button_purple"
    
    112
    -        android:maxWidth="312dp"
    
    190
    +        android:minWidth="360dp"
    
    113 191
             android:text="@string/tor_bootstrap_connect"
    
    114 192
             android:textAllCaps="false"
    
    115 193
             android:textColor="#FBFBFE"
    
    116
    -        android:textFontWeight="500"
    
    117 194
             android:textSize="14sp"
    
    118 195
             android:textStyle="bold"
    
    119
    -        app:layout_constraintBottom_toTopOf="@id/tor_bootstrap_network_settings_button"
    
    196
    +        app:layout_constraintBottom_toTopOf="@id/tor_bootstrap_button_2"
    
    120 197
             app:layout_constraintEnd_toEndOf="parent"
    
    121
    -        app:layout_constraintHorizontal_bias="0.0"
    
    122 198
             app:layout_constraintStart_toStartOf="parent"
    
    123 199
             app:layout_constraintTop_toBottomOf="@+id/quickstart_switch"
    
    124 200
             app:layout_constraintVertical_bias="1" />
    
    125 201
     
    
    126
    -
    
    127 202
         <Button
    
    128
    -        android:id="@+id/tor_bootstrap_network_settings_button"
    
    129
    -        android:layout_width="match_parent"
    
    203
    +        android:id="@+id/tor_bootstrap_button_2"
    
    204
    +        android:layout_width="wrap_content"
    
    130 205
             android:layout_height="wrap_content"
    
    131 206
             android:layout_marginStart="24dp"
    
    132 207
             android:layout_marginEnd="24dp"
    
    133
    -        android:layout_marginBottom="24dp"
    
    208
    +        android:layout_marginBottom="8dp"
    
    134 209
             android:background="">"@drawable/rounded_corners"
    
    135 210
             android:backgroundTint="@color/configure_connection_button_white"
    
    136
    -        android:maxWidth="312dp"
    
    211
    +        android:minWidth="360dp"
    
    137 212
             android:text="@string/connection_assist_configure_connection_button"
    
    138 213
             android:textAllCaps="false"
    
    139 214
             android:textColor="#15141A"
    
    140
    -        android:textFontWeight="500"
    
    141 215
             android:textSize="14sp"
    
    142 216
             android:textStyle="bold"
    
    143 217
             app:layout_constraintBottom_toBottomOf="parent"
    

  • fenix/app/src/main/res/values/colors.xml
    ... ... @@ -273,6 +273,8 @@
    273 273
         <color name="sync_disconnected_background_private_theme">#5B5846</color>
    
    274 274
         <color name="onboarding_illustration_deselected_private_theme">#99FBFBFE</color>
    
    275 275
         <color name="prompt_login_edit_text_cursor_color_private_theme">@color/photonViolet50</color>
    
    276
    +    <color name="backgroundGradientDark">#FF3A3274</color>
    
    277
    +    <color name="backgroundGradientLight">#FF7329A4</color>
    
    276 278
     
    
    277 279
         <!-- Normal theme colors for light mode -->
    
    278 280
         <color name="accent_normal_theme">@color/photonInk20</color>
    
    ... ... @@ -344,5 +346,6 @@
    344 346
         <!-- Connection Assist -->
    
    345 347
         <color name="connect_button_purple">#9059FF</color>
    
    346 348
         <color name="configure_connection_button_white">#E1E0E7</color>
    
    349
    +    <color name="warning_yellow">#FFA436</color>
    
    347 350
     
    
    348 351
     </resources>

  • fenix/app/src/main/res/values/styles.xml
    ... ... @@ -12,7 +12,7 @@
    12 12
             <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
    
    13 13
             <item name="android:progressBarStyleHorizontal">@style/progressBarStyleHorizontal</item>
    
    14 14
             <item name="android:statusBarColor">@android:color/transparent</item>
    
    15
    -        <item name="android:windowBackground">@color/fx_mobile_layer_color_1</item>
    
    15
    +        <item name="android:windowBackground">@color/backgroundGradientDark</item>
    
    16 16
             <item name="android:colorEdgeEffect">@color/accent_normal_theme</item>
    
    17 17
             <item name="android:colorAccent">@color/fx_mobile_text_color_primary</item>
    
    18 18
             <item name="android:textColorPrimary">@color/state_list_text_color</item>
    

  • _______________________________________________
    tor-commits mailing list
    tor-commits@xxxxxxxxxxxxxxxxxxxx
    https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits