diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlUIView.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlUIView.kt index a8b70ce89..10870b027 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlUIView.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/SessionControlUIView.kt @@ -81,7 +81,6 @@ private fun onboardingAdapterItems(onboardingState: OnboardingState): List { listOf( - AdapterItem.OnboardingSectionHeader { it.getString(R.string.onboarding_fxa_section_header) }, AdapterItem.OnboardingFirefoxAccount(onboardingState) ) } diff --git a/app/src/main/java/org/mozilla/fenix/settings/PairFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/PairFragment.kt index 7307b320e..5a72a1de8 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/PairFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/PairFragment.kt @@ -22,7 +22,11 @@ import org.mozilla.fenix.ext.requireComponents class PairFragment : Fragment(), BackHandler { private val qrFeature = ViewBoundFeatureWrapper() - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { return inflater.inflate(R.layout.fragment_pair, container, false) } @@ -30,8 +34,12 @@ class PairFragment : Fragment(), BackHandler { super.onViewCreated(view, savedInstanceState) val instructionsText = view.findViewById(R.id.pair_instructions) as TextView - instructionsText.setText(HtmlCompat.fromHtml(getString(R.string.pair_instructions), - HtmlCompat.FROM_HTML_MODE_LEGACY)) + instructionsText.setText( + HtmlCompat.fromHtml( + getString(R.string.pair_instructions), + HtmlCompat.FROM_HTML_MODE_LEGACY + ) + ) qrFeature.set( QrFeature( @@ -59,7 +67,7 @@ class PairFragment : Fragment(), BackHandler { override fun onResume() { super.onResume() - (activity as AppCompatActivity).title = getString(R.string.preferences_sync) + (activity as AppCompatActivity).title = getString(R.string.sync_scan_code) (activity as AppCompatActivity).supportActionBar?.show() } @@ -74,7 +82,11 @@ class PairFragment : Fragment(), BackHandler { private const val REQUEST_CODE_CAMERA_PERMISSIONS = 1 } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { when (requestCode) { REQUEST_CODE_CAMERA_PERMISSIONS -> qrFeature.withFeature { it.onPermissionsResult(permissions, grantResults) diff --git a/app/src/main/java/org/mozilla/fenix/settings/PairInstructionsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/PairInstructionsFragment.kt deleted file mode 100644 index ac54fb478..000000000 --- a/app/src/main/java/org/mozilla/fenix/settings/PairInstructionsFragment.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.fenix.settings - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.Button -import android.widget.TextView -import androidx.appcompat.app.AppCompatActivity -import androidx.core.text.HtmlCompat -import androidx.fragment.app.DialogFragment -import androidx.navigation.fragment.NavHostFragment.findNavController -import com.google.android.material.bottomsheet.BottomSheetDialogFragment -import org.mozilla.fenix.R -import org.mozilla.fenix.ext.nav - -class PairInstructionsFragment : BottomSheetDialogFragment() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(DialogFragment.STYLE_NO_TITLE, R.style.FirefoxAccountsDialogStyle) - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.fragment_pair_instructions, container, false) - } - - override fun onResume() { - super.onResume() - (activity as AppCompatActivity).title = getString(R.string.preferences_sync) - (activity as AppCompatActivity).supportActionBar?.show() - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - val instructionsText = view.findViewById(R.id.pair_instructions_info) as TextView - instructionsText.text = HtmlCompat.fromHtml( - getString(R.string.pair_instructions), - HtmlCompat.FROM_HTML_MODE_LEGACY - ) - - val openCamera = view.findViewById(R.id.pair_open_camera) as Button - openCamera.setOnClickListener { - val directions = PairInstructionsFragmentDirections.actionPairInstructionsFragmentToPairFragment() - nav(R.id.pairInstructionsFragment, directions) - } - - val cancelCamera = view.findViewById(R.id.pair_cancel) as Button - cancelCamera.setOnClickListener { - findNavController(this@PairInstructionsFragment).navigateUp() - } - } -} diff --git a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt index b02b5f4af..1b11536e9 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -25,8 +25,10 @@ import kotlinx.coroutines.launch import mozilla.components.concept.sync.AccountObserver import mozilla.components.concept.sync.OAuthAccount import mozilla.components.concept.sync.Profile +import mozilla.components.support.ktx.android.content.hasCamera import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.Config +import org.mozilla.fenix.Experiments import org.mozilla.fenix.FenixApplication import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R @@ -54,6 +56,7 @@ import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.getPreferenceKey import org.mozilla.fenix.ext.requireComponents +import org.mozilla.fenix.isInExperiment import org.mozilla.fenix.utils.ItsNotBrokenSnack @SuppressWarnings("TooManyFunctions", "LargeClass") @@ -222,8 +225,21 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver { private fun getClickListenerForSignIn(): OnPreferenceClickListener { return OnPreferenceClickListener { - val directions = SettingsFragmentDirections.actionSettingsFragmentToTurnOnSyncFragment() - Navigation.findNavController(view!!).navigate(directions) + // Do not navigate to pairing UI if camera not available or pairing is disabled + if (context?.hasCamera() == true && + context?.isInExperiment(Experiments.asFeatureFxAPairingDisabled) == false + ) { + val directions = SettingsFragmentDirections.actionSettingsFragmentToTurnOnSyncFragment() + Navigation.findNavController(view!!).navigate(directions) + } else { + requireComponents.services.accountsAuthFeature.beginAuthentication(requireContext()) + // TODO The sign-in web content populates session history, + // so pressing "back" after signing in won't take us back into the settings screen, but rather up the + // session history stack. + // We could auto-close this tab once we get to the end of the authentication process? + // Via an interceptor, perhaps. + requireComponents.analytics.metrics.track(Event.SyncAuthSignIn) + } true } } @@ -388,7 +404,7 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver { preferenceFirefoxAccount?.displayName = profile?.displayName preferenceFirefoxAccount?.email = profile?.email - // Signed-in, need to re-authenticate. + // Signed-in, need to re-authenticate. } else if (account != null && accountManager.accountNeedsReauth()) { preferenceFirefoxAccount?.isVisible = false preferenceFirefoxAccountAuthError?.isVisible = true @@ -399,7 +415,7 @@ class SettingsFragment : PreferenceFragmentCompat(), AccountObserver { preferenceFirefoxAccountAuthError?.email = profile?.email - // Signed-out. + // Signed-out. } else { preferenceSignIn?.isVisible = true preferenceSignIn?.onPreferenceClickListener = getClickListenerForSignIn() diff --git a/app/src/main/java/org/mozilla/fenix/settings/TurnOnSyncFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/TurnOnSyncFragment.kt index 08b4e671d..f037814f1 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/TurnOnSyncFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/TurnOnSyncFragment.kt @@ -5,25 +5,25 @@ package org.mozilla.fenix.settings import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity +import androidx.core.text.HtmlCompat +import androidx.fragment.app.Fragment import androidx.navigation.Navigation import androidx.navigation.fragment.NavHostFragment.findNavController -import androidx.preference.Preference -import androidx.preference.PreferenceFragmentCompat +import kotlinx.android.synthetic.main.fragment_turn_on_sync.view.* import mozilla.components.concept.sync.AccountObserver import mozilla.components.concept.sync.OAuthAccount import mozilla.components.concept.sync.Profile -import mozilla.components.support.ktx.android.content.hasCamera -import org.mozilla.fenix.Experiments import org.mozilla.fenix.R import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.metrics.Event -import org.mozilla.fenix.ext.getPreferenceKey import org.mozilla.fenix.ext.requireComponents -import org.mozilla.fenix.isInExperiment @SuppressWarnings("TooManyFunctions") -class TurnOnSyncFragment : PreferenceFragmentCompat(), AccountObserver { +class TurnOnSyncFragment : Fragment(), AccountObserver { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) requireComponents.analytics.metrics.track(Event.SyncAuthOpened) @@ -46,25 +46,19 @@ class TurnOnSyncFragment : PreferenceFragmentCompat(), AccountObserver { (activity as AppCompatActivity).supportActionBar?.show() } - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - setPreferencesFromResource(R.xml.turn_on_sync_preferences, rootKey) - - val preferenceSignIn = - findPreference(context!!.getPreferenceKey(R.string.pref_key_sync_sign_in)) - val preferencePairSignIn = - findPreference(context!!.getPreferenceKey(R.string.pref_key_sync_pair)) - preferenceSignIn?.onPreferenceClickListener = getClickListenerForSignIn() - preferencePairSignIn?.onPreferenceClickListener = getClickListenerForPairing() - preferencePairSignIn?.isVisible = context?.hasCamera() ?: true - - // if FxA pairing has been turned off on the server - if (context?.isInExperiment(Experiments.asFeatureFxAPairingDisabled)!!) { - preferencePairSignIn?.isVisible = false - } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val view = inflater.inflate(R.layout.fragment_turn_on_sync, container, false) + view.sign_in_scan_button.setOnClickListener(getClickListenerForPairing()) + view.sign_in_email_button.setOnClickListener(getClickListenerForSignIn()) + view.sign_in_instructions.text = HtmlCompat.fromHtml( + getString(R.string.sign_in_instructions), + HtmlCompat.FROM_HTML_MODE_LEGACY + ) + return view } - private fun getClickListenerForSignIn(): Preference.OnPreferenceClickListener { - return Preference.OnPreferenceClickListener { + private fun getClickListenerForSignIn(): View.OnClickListener { + return View.OnClickListener { requireComponents.services.accountsAuthFeature.beginAuthentication(requireContext()) // TODO The sign-in web content populates session history, // so pressing "back" after signing in won't take us back into the settings screen, but rather up the @@ -76,9 +70,9 @@ class TurnOnSyncFragment : PreferenceFragmentCompat(), AccountObserver { } } - private fun getClickListenerForPairing(): Preference.OnPreferenceClickListener { - return Preference.OnPreferenceClickListener { - val directions = TurnOnSyncFragmentDirections.actionTurnOnSyncFragmentToPairInstructionsFragment() + private fun getClickListenerForPairing(): View.OnClickListener { + return View.OnClickListener { + val directions = TurnOnSyncFragmentDirections.actionTurnOnSyncFragmentToPairFragment() Navigation.findNavController(view!!).navigate(directions) requireComponents.analytics.metrics.track(Event.SyncAuthScanPairing) @@ -95,4 +89,5 @@ class TurnOnSyncFragment : PreferenceFragmentCompat(), AccountObserver { override fun onAuthenticationProblems() {} override fun onError(error: Exception) {} override fun onLoggedOut() {} - override fun onProfileUpdated(profile: Profile) {} } + override fun onProfileUpdated(profile: Profile) {} +} diff --git a/app/src/main/res/drawable/ic_scan.xml b/app/src/main/res/drawable/ic_scan.xml new file mode 100644 index 000000000..f3bd7d2cc --- /dev/null +++ b/app/src/main/res/drawable/ic_scan.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_pair_instructions.xml b/app/src/main/res/layout/fragment_pair_instructions.xml deleted file mode 100644 index fb42eb5ef..000000000 --- a/app/src/main/res/layout/fragment_pair_instructions.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - -