[tbb-commits] [Git][tpo/applications/firefox-android][firefox-android-115.2.1-13.5-1] fixup! Implement Android-native Connection Assist UI
Dan Ballard (@dan)
git at gitlab.torproject.org
Thu May 9 21:07:43 UTC 2024
Dan Ballard pushed to branch firefox-android-115.2.1-13.5-1 at The Tor Project / Applications / firefox-android
Commits:
a00861a6 by clairehurst at 2024-05-09T14:47:16-06:00
fixup! Implement Android-native Connection Assist UI
- - - - -
4 changed files:
- fenix/app/src/main/java/org/mozilla/fenix/tor/ConnectAssistUiState.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/res/layout/fragment_tor_connection_assist.xml
Changes:
=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/ConnectAssistUiState.kt
=====================================
@@ -31,7 +31,8 @@ enum class ConnectAssistUiState(
val torBootstrapButton2Visible: Boolean,
@StringRes val torBootstrapButton2TextStringResource: Int? = R.string.connection_assist_configure_connection_button,
val torBootstrapButton2ShouldOpenSettings: Boolean = true,
- val wordmarkLogoVisible: Boolean,
+ val wordmarkLogoVisible: Boolean = false,
+ val torBootstrapButton2ShouldRestartApp: Boolean = false,
) {
Splash(
progressBarVisible = false,
@@ -65,9 +66,8 @@ enum class ConnectAssistUiState(
torBootstrapButton2Visible = true,
torBootstrapButton2TextStringResource = R.string.connection_assist_configure_connection_button,
torBootstrapButton2ShouldOpenSettings = true,
- wordmarkLogoVisible = false,
),
- Bootstrapping(
+ Connecting(
progressBarVisible = true,
progress = 0,
backButtonVisible = false,
@@ -85,7 +85,6 @@ enum class ConnectAssistUiState(
torBootstrapButton2Visible = true,
torBootstrapButton2TextStringResource = R.string.btn_cancel,
torBootstrapButton2ShouldOpenSettings = false,
- wordmarkLogoVisible = false,
),
InternetError(
progressBarVisible = true,
@@ -109,7 +108,6 @@ enum class ConnectAssistUiState(
torBootstrapButton2Visible = true,
torBootstrapButton2TextStringResource = R.string.connection_assist_configure_connection_button,
torBootstrapButton2ShouldOpenSettings = true,
- wordmarkLogoVisible = false,
),
TryingAgain(
progressBarVisible = true,
@@ -132,9 +130,8 @@ enum class ConnectAssistUiState(
torBootstrapButton2Visible = true,
torBootstrapButton2TextStringResource = R.string.btn_cancel,
torBootstrapButton2ShouldOpenSettings = false,
- wordmarkLogoVisible = false,
),
- TryABridge(
+ ConnectionAssist(
progressBarVisible = true,
progress = 100,
progressTintColorResource = R.color.warning_yellow,
@@ -157,7 +154,6 @@ enum class ConnectAssistUiState(
torBootstrapButton2Visible = false,
torBootstrapButton2TextStringResource = null,
torBootstrapButton2ShouldOpenSettings = true,
- wordmarkLogoVisible = false,
),
TryingABridge(
progressBarVisible = true,
@@ -180,7 +176,6 @@ enum class ConnectAssistUiState(
torBootstrapButton2Visible = true,
torBootstrapButton2TextStringResource = R.string.btn_cancel,
torBootstrapButton2ShouldOpenSettings = false,
- wordmarkLogoVisible = false,
),
LocationError(
progressBarVisible = true,
@@ -207,7 +202,6 @@ enum class ConnectAssistUiState(
torBootstrapButton2Visible = false,
torBootstrapButton2TextStringResource = null,
torBootstrapButton2ShouldOpenSettings = true,
- wordmarkLogoVisible = false,
),
LocationCheck(
progressBarVisible = true,
@@ -234,7 +228,6 @@ enum class ConnectAssistUiState(
torBootstrapButton2Visible = false,
torBootstrapButton2TextStringResource = null,
torBootstrapButton2ShouldOpenSettings = true,
- wordmarkLogoVisible = false,
),
LastTry(
progressBarVisible = true,
@@ -258,7 +251,6 @@ enum class ConnectAssistUiState(
torBootstrapButton2Visible = true,
torBootstrapButton2TextStringResource = R.string.btn_cancel,
torBootstrapButton2ShouldOpenSettings = false,
- wordmarkLogoVisible = false,
),
FinalError(
progressBarVisible = true,
@@ -279,10 +271,10 @@ enum class ConnectAssistUiState(
unblockTheInternetInCountryDescriptionVisible = false,
countryDropDownVisible = false,
torBootstrapButton1Visible = true,
- torBootstrapButton1TextStringResource = R.string.connection_assist_internet_error_try_again,
+ torBootstrapButton1TextStringResource = R.string.connection_assist_configure_connection_button,
torBootstrapButton2Visible = true,
- torBootstrapButton2TextStringResource = R.string.connection_assist_configure_connection_button,
- torBootstrapButton2ShouldOpenSettings = true,
- wordmarkLogoVisible = false,
+ torBootstrapButton2TextStringResource = R.string.mozac_lib_crash_dialog_button_restart,
+ torBootstrapButton2ShouldOpenSettings = false,
+ torBootstrapButton2ShouldRestartApp = true,
)
}
=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistFragment.kt
=====================================
@@ -4,6 +4,7 @@
package org.mozilla.fenix.tor
+import android.content.Intent
import android.graphics.Color
import android.os.Build
import android.os.Bundle
@@ -25,6 +26,7 @@ import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController
import kotlinx.coroutines.launch
import mozilla.components.support.base.feature.UserInteractionHandler
+import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.databinding.FragmentTorConnectionAssistBinding
import org.mozilla.fenix.ext.hideToolbar
@@ -33,14 +35,15 @@ class TorConnectionAssistFragment : Fragment(), UserInteractionHandler {
private val TAG = "TorConnectionAssistFrag"
private val viewModel: TorConnectionAssistViewModel by viewModels()
- private lateinit var binding: FragmentTorConnectionAssistBinding
+ private var _binding: FragmentTorConnectionAssistBinding? = null
+ private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
- binding = FragmentTorConnectionAssistBinding.inflate(
+ _binding = FragmentTorConnectionAssistBinding.inflate(
inflater, container, false,
)
@@ -90,96 +93,148 @@ class TorConnectionAssistFragment : Fragment(), UserInteractionHandler {
}
- override fun onDestroyView() {
- super.onDestroyView()
- }
-
private fun showScreen(screen: ConnectAssistUiState) {
- binding.apply {
- torBootstrapProgressBar.visibility = if (screen.progressBarVisible) View.VISIBLE else View.GONE
- torBootstrapProgressBar.progress = screen.progress
- torBootstrapProgressBar.progressTintList =
- screen.progressTintColorResource?.let {
- AppCompatResources.getColorStateList(requireContext(),
- it
- )
- }
-
- settingsButton.visibility = if (screen.settingsButtonVisible) View.VISIBLE else View.GONE
- settingsButton.setOnClickListener {
- viewModel.cancelTorBootstrap()
- openSettings()
- }
+ setProgressBar(screen)
+ setSettingsButton(screen)
+ setBackButton(screen)
+ setTorConnectImage(screen)
+ setTitle(screen)
+ setQuickStart(screen)
+ setCountryDropDown(screen)
+ setButton1(screen)
+ setButton2(screen)
+ setSplashLogo(screen)
+ }
- backButton.visibility = if (screen.backButtonVisible) View.VISIBLE else View.INVISIBLE
- backButton.setOnClickListener {
- viewModel.handleBackButtonPressed()
+ private fun setProgressBar(screen: ConnectAssistUiState) {
+ binding.torBootstrapProgressBar.visibility =
+ if (screen.progressBarVisible) View.VISIBLE else View.GONE
+ binding.torBootstrapProgressBar.progress = screen.progress
+ binding.torBootstrapProgressBar.progressTintList =
+ screen.progressTintColorResource?.let {
+ AppCompatResources.getColorStateList(
+ requireContext(),
+ it,
+ )
}
+ }
- torConnectImage.visibility = if (screen.torConnectImageVisible) View.VISIBLE else View.GONE
- torConnectImage.setImageResource(screen.torConnectImageResource)
-
- titleLargeTextView.visibility = if (screen.titleLargeTextViewVisible) View.VISIBLE else View.GONE
- titleLargeTextView.text = getString(screen.titleLargeTextViewTextStringResource)
- titleDescription.visibility = if (screen.titleDescriptionVisible) View.VISIBLE else View.GONE
- if (screen.learnMoreStringResource != null && screen.internetErrorDescription != null) {
- val learnMore: String = getString(screen.learnMoreStringResource)
- val internetErrorDescription: String =
- if (screen.internetErrorDescription1 == null) {
- getString(
- screen.internetErrorDescription,
- learnMore,
- )
- } else if (screen.internetErrorDescription2 == null) {
- getString(
- screen.internetErrorDescription,
- getString(screen.internetErrorDescription1),
- learnMore,
- )
- } else {
- getString(
- screen.internetErrorDescription,
- getString(screen.internetErrorDescription1),
- getString(screen.internetErrorDescription2),
- learnMore,
- )
- }
- handleDescriptionWithClickable(internetErrorDescription, learnMore)
- } else if (screen.titleDescriptionTextStringResource != null) {
- titleDescription.text = getString(screen.titleDescriptionTextStringResource)
- }
- quickstartSwitch.visibility = if (screen.quickstartSwitchVisible) View.VISIBLE else View.GONE
- quickstartSwitch.isChecked = viewModel.quickstartToggle().value == true
- quickstartSwitch.setOnCheckedChangeListener { _, isChecked ->
- viewModel.handleQuickstartChecked(isChecked)
- }
+ private fun setSettingsButton(screen: ConnectAssistUiState) {
+ binding.settingsButton.visibility = if (screen.settingsButtonVisible) View.VISIBLE else View.GONE
+ binding.settingsButton.setOnClickListener {
+ viewModel.cancelTorBootstrap()
+ openSettings()
+ }
+ }
- unblockTheInternetInCountryDescription.visibility = if (screen.unblockTheInternetInCountryDescriptionVisible) View.VISIBLE else View.GONE
- countryDropDown.visibility = if (screen.countryDropDownVisible) View.VISIBLE else View.GONE
+ private fun setBackButton(screen: ConnectAssistUiState) {
+ binding.backButton.visibility = if (screen.backButtonVisible) View.VISIBLE else View.INVISIBLE
+ binding.backButton.setOnClickListener {
+ viewModel.handleBackButtonPressed()
+ }
+ }
- torBootstrapButton1.visibility = if (screen.torBootstrapButton1Visible) View.VISIBLE else View.GONE
- torBootstrapButton1.text = getString(screen.torBootstrapButton1TextStringResource)
- torBootstrapButton1.setOnClickListener { viewModel.handleButton1Pressed(screen, lifecycleScope) }
+ private fun setTorConnectImage(screen: ConnectAssistUiState) {
+ binding.torConnectImage.visibility = if (screen.torConnectImageVisible) View.VISIBLE else View.GONE
+ binding.torConnectImage.setImageResource(screen.torConnectImageResource)
+ }
- torBootstrapButton2.visibility = if (screen.torBootstrapButton2Visible) View.VISIBLE else View.GONE
- torBootstrapButton2.text = screen.torBootstrapButton2TextStringResource?.let {
- getString(
- it
- )
- }
- torBootstrapButton2.setOnClickListener {
- viewModel.cancelTorBootstrap()
- if (screen.torBootstrapButton2ShouldOpenSettings){
- openTorConnectionSettings()
+ private fun setTitle(screen: ConnectAssistUiState) {
+ binding.titleLargeTextView.visibility =
+ if (screen.titleLargeTextViewVisible) View.VISIBLE else View.GONE
+ binding.titleLargeTextView.text = getString(screen.titleLargeTextViewTextStringResource)
+ binding.titleDescription.visibility =
+ if (screen.titleDescriptionVisible) View.VISIBLE else View.GONE
+ if (screen.learnMoreStringResource != null && screen.internetErrorDescription != null) {
+ val learnMore: String = getString(screen.learnMoreStringResource)
+ val internetErrorDescription: String =
+ if (screen.internetErrorDescription1 == null) {
+ getString(
+ screen.internetErrorDescription,
+ learnMore,
+ )
+ } else if (screen.internetErrorDescription2 == null) {
+ getString(
+ screen.internetErrorDescription,
+ getString(screen.internetErrorDescription1),
+ learnMore,
+ )
} else {
- showScreen(ConnectAssistUiState.Configuring)
+ getString(
+ screen.internetErrorDescription,
+ getString(screen.internetErrorDescription1),
+ getString(screen.internetErrorDescription2),
+ learnMore,
+ )
}
- }
+ handleDescriptionWithClickable(internetErrorDescription, learnMore)
+ } else if (screen.titleDescriptionTextStringResource != null) {
+ binding.titleDescription.text = getString(screen.titleDescriptionTextStringResource)
+ }
+ }
+
+ private fun setQuickStart(screen: ConnectAssistUiState) {
+ binding.quickstartSwitch.visibility =
+ if (screen.quickstartSwitchVisible) View.VISIBLE else View.GONE
+ binding.quickstartSwitch.isChecked = viewModel.quickstartToggle().value == true
+ binding.quickstartSwitch.setOnCheckedChangeListener { _, isChecked ->
+ viewModel.handleQuickstartChecked(isChecked)
+ }
+ }
+
+ private fun setCountryDropDown(screen: ConnectAssistUiState) {
+ binding.unblockTheInternetInCountryDescription.visibility =
+ if (screen.unblockTheInternetInCountryDescriptionVisible) View.VISIBLE else View.GONE
+ binding.countryDropDown.visibility = if (screen.countryDropDownVisible) View.VISIBLE else View.GONE
+ }
- wordmarkLogo.visibility = if(screen.wordmarkLogoVisible) View.VISIBLE else View.GONE
+ private fun setButton1(screen: ConnectAssistUiState) {
+ binding.torBootstrapButton1.visibility =
+ if (screen.torBootstrapButton1Visible) View.VISIBLE else View.GONE
+ binding.torBootstrapButton1.text = getString(screen.torBootstrapButton1TextStringResource)
+ binding.torBootstrapButton1.setOnClickListener {
+ viewModel.handleButton1Pressed(
+ screen,
+ lifecycleScope,
+ )
+ }
+ }
+
+ private fun setButton2(screen: ConnectAssistUiState) {
+ binding.torBootstrapButton2.visibility =
+ if (screen.torBootstrapButton2Visible) View.VISIBLE else View.GONE
+ if (screen.torBootstrapButton2ShouldRestartApp) {
+ binding.torBootstrapButton2.text =
+ screen.torBootstrapButton2TextStringResource?.let {
+ getString(
+ it,
+ getString(R.string.app_name),
+ )
+ }
+ } else {
+ binding.torBootstrapButton2.text =
+ screen.torBootstrapButton2TextStringResource?.let {
+ getString(
+ it,
+ )
+ }
+ }
+ binding.torBootstrapButton2.setOnClickListener {
+ viewModel.cancelTorBootstrap()
+ if (screen.torBootstrapButton2ShouldOpenSettings) {
+ openTorConnectionSettings()
+ } else if (screen.torBootstrapButton2ShouldRestartApp) {
+ restartApplication()
+ } else {
+ showScreen(ConnectAssistUiState.Configuring)
+ }
}
}
+ private fun setSplashLogo(screen: ConnectAssistUiState) {
+ binding.wordmarkLogo.visibility = if (screen.wordmarkLogoVisible) View.VISIBLE else View.GONE
+ }
+
/**
* from https://stackoverflow.com/questions/10696986/how-to-set-the-part-of-the-text-view-is-clickable
*/
@@ -207,6 +262,7 @@ class TorConnectionAssistFragment : Fragment(), UserInteractionHandler {
}
private fun showLearnMore() {
+ Log.d(TAG, "showLearnMore() tapped")
//TODO("Not yet implemented")
}
@@ -231,6 +287,15 @@ class TorConnectionAssistFragment : Fragment(), UserInteractionHandler {
)
}
+ private fun restartApplication() {
+ startActivity(
+ Intent(requireContext(), HomeActivity::class.java).addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK,
+ ),
+ )
+ Runtime.getRuntime().exit(0)
+ }
+
override fun onBackPressed(): Boolean {
return viewModel.handleBackButtonPressed()
}
=====================================
fenix/app/src/main/java/org/mozilla/fenix/tor/TorConnectionAssistViewModel.kt
=====================================
@@ -124,7 +124,7 @@ class TorConnectionAssistViewModel(
/** stay here */
}
- ConnectAssistUiState.TryABridge -> {
+ ConnectAssistUiState.ConnectionAssist -> {
_torConnectScreen.value = ConnectAssistUiState.TryingABridge
}
@@ -144,7 +144,7 @@ class TorConnectionAssistViewModel(
/** stay here */
}
- else -> _torConnectScreen.value = ConnectAssistUiState.Bootstrapping
+ else -> _torConnectScreen.value = ConnectAssistUiState.Connecting
}
}
@@ -155,28 +155,58 @@ class TorConnectionAssistViewModel(
"TorError(message = $message, details = $details, phase = $phase, reason = $reason",
)
// TODO better error handling
- _torConnectScreen.value = ConnectAssistUiState.InternetError
+ when (reason) {
+// "noroute" -> handleNoRoute() TODO re-add when working better
+ else -> handleUnknownError()
+ }
+ }
+ }
+
+ private fun handleNoRoute() {
+ Log.d(TAG, "handleNoRoute(), _torConnectScreen.value = ${_torConnectScreen.value}")
+ when (_torConnectScreen.value) {
+ ConnectAssistUiState.Connecting -> _torConnectScreen.value = ConnectAssistUiState.ConnectionAssist
+ ConnectAssistUiState.ConnectionAssist -> {/** no op, likely a duplicate error */}
+ ConnectAssistUiState.TryingABridge -> _torConnectScreen.value = ConnectAssistUiState.LocationCheck
+ ConnectAssistUiState.LocationCheck -> {/** no op, likely a duplicate error */}
+ ConnectAssistUiState.LastTry -> _torConnectScreen.value = ConnectAssistUiState.FinalError
+ ConnectAssistUiState.FinalError -> {/** no op, likely a duplicate error */}
+ else -> _torConnectScreen.value = ConnectAssistUiState.InternetError
}
}
+ private fun handleUnknownError() {
+ // TODO should we have a dedicated screen for unknown errors?
+ _torConnectScreen.value = ConnectAssistUiState.InternetError
+ }
+
override fun onTorStopped() {
Log.d(TAG, "onTorStopped()")
}
private fun tryABridge() {
+ if (!locationFound()) {
+ _torConnectScreen.value = ConnectAssistUiState.LocationError
+ return
+ }
if (!_torController.bridgesEnabled) {
_torController.bridgesEnabled = true
_torController.bridgeTransport =
- TorBridgeTransportConfig.BUILTIN_OBFS4 // TODO select based on country
+ TorBridgeTransportConfig.BUILTIN_SNOWFLAKE // TODO select based on country
}
handleConnect(withDebugLogging = true)
}
+ private fun locationFound(): Boolean {
+ // TODO try to find location
+ return true
+ }
+
fun handleBackButtonPressed(): Boolean {
when (torConnectScreen.value) {
ConnectAssistUiState.Splash -> return false
ConnectAssistUiState.Configuring -> return false
- ConnectAssistUiState.Bootstrapping -> cancelTorBootstrap()
+ ConnectAssistUiState.Connecting -> cancelTorBootstrap()
ConnectAssistUiState.InternetError -> {
_torController.lastKnownError = null
_torConnectScreen.value = ConnectAssistUiState.Configuring
@@ -186,18 +216,18 @@ class TorConnectionAssistViewModel(
cancelTorBootstrap()
}
- ConnectAssistUiState.TryABridge -> {
+ ConnectAssistUiState.ConnectionAssist -> {
_torController.lastKnownError = null
_torConnectScreen.value = ConnectAssistUiState.Configuring
}
ConnectAssistUiState.TryingABridge -> {
_torController.stopTor()
- _torConnectScreen.value = ConnectAssistUiState.TryABridge
+ _torConnectScreen.value = ConnectAssistUiState.ConnectionAssist
}
ConnectAssistUiState.LocationError -> {
- _torConnectScreen.value = ConnectAssistUiState.TryABridge
+ _torConnectScreen.value = ConnectAssistUiState.ConnectionAssist
}
ConnectAssistUiState.LocationCheck -> {
=====================================
fenix/app/src/main/res/layout/fragment_tor_connection_assist.xml
=====================================
@@ -126,7 +126,6 @@
android:layout_marginTop="8dp"
android:layout_marginEnd="24dp"
android:textColor="@color/photonLightGrey05"
- android:tooltipText="@string/connection_assist_share_my_location_country_or_region"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
View it on GitLab: https://gitlab.torproject.org/tpo/applications/firefox-android/-/commit/a00861a6231a712389ae1776c00e1ef1a9a313c9
--
This project does not include diff previews in email notifications.
View it on GitLab: https://gitlab.torproject.org/tpo/applications/firefox-android/-/commit/a00861a6231a712389ae1776c00e1ef1a9a313c9
You're receiving this email because of your account on gitlab.torproject.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.torproject.org/pipermail/tbb-commits/attachments/20240509/b20ee9c2/attachment-0001.htm>
More information about the tbb-commits
mailing list