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
-
86815386
by clairehurst at 2024-03-26T17:06:54-06:00
-
99f95c30
by clairehurst at 2024-03-26T17:06:54-06:00
12 changed files:
- fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistFragment.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistViewModel.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorController.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerGV.kt
- fenix/app/src/main/java/org/mozilla/fenix/tor/TorControllerTAS.kt
- + fenix/app/src/main/res/drawable/connect_broken.xml
- + fenix/app/src/main/res/drawable/globe_broken.xml
- fenix/app/src/main/res/drawable/tor_bootstrap_background_gradient.xml
- fenix/app/src/main/res/layout/fragment_tor_connection_assist.xml
- fenix/app/src/main/res/values/colors.xml
- fenix/app/src/main/res/values/styles.xml
Changes:
... | ... | @@ -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 | }
|
... | ... | @@ -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 | } |
... | ... | @@ -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 | } |
... | ... | @@ -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 |
... | ... | @@ -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 |
... | ... | @@ -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 | } |
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> |
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> |
... | ... | @@ -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>
|
... | ... | @@ -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"
|
... | ... | @@ -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> |
... | ... | @@ -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>
|