1
0
Fork 0

Add FxA Pairing feature to "Turn On Sync"

master
Vlad Filippov 2019-05-06 16:51:56 -04:00 committed by Emily Kager
parent a078f9e48b
commit 66a0cd5f9c
11 changed files with 281 additions and 8 deletions

View File

@ -47,6 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- #1874 - Added TOP info panel dialog for custom tabs.
- #1411 - Added disabled style for disabled permissions items in site info panel.
- #1735 - Adds API to see the release channel
- #2318 - Added Firefox Accounts Pairing feature to "Turn On Sync" options
### Changed
- #1429 - Updated site permissions ui for MVP

View File

@ -0,0 +1,83 @@
/* 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.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.text.HtmlCompat
import androidx.fragment.app.Fragment
import mozilla.components.feature.qr.QrFeature
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.requireComponents
class PairFragment : Fragment(), BackHandler {
private val qrFeature = ViewBoundFeatureWrapper<QrFeature>()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_pair, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
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))
qrFeature.set(
QrFeature(
requireContext(),
fragmentManager = requireFragmentManager(),
onNeedToRequestPermissions = { permissions ->
requestPermissions(permissions, REQUEST_CODE_CAMERA_PERMISSIONS)
},
onScanResult = { pairingUrl ->
requireComponents.services.accountsAuthFeature.beginPairingAuthentication(pairingUrl)
view?.let {
(activity as HomeActivity).openToBrowser(BrowserDirection.FromSettings)
}
}),
owner = this,
view = view
)
qrFeature.withFeature {
it.scan(R.id.pair_layout)
}
}
override fun onResume() {
super.onResume()
(activity as AppCompatActivity).title = getString(R.string.preferences_sync)
(activity as AppCompatActivity).supportActionBar?.show()
}
override fun onBackPressed(): Boolean {
return when {
qrFeature.onBackPressed() -> true
else -> false
}
}
companion object {
private const val REQUEST_CODE_CAMERA_PERMISSIONS = 1
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
REQUEST_CODE_CAMERA_PERMISSIONS -> qrFeature.withFeature {
it.onPermissionsResult(permissions, grantResults)
}
}
}
}

View File

@ -0,0 +1,58 @@
/* 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.navigation.Navigation
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import mozilla.components.support.base.feature.BackHandler
import org.mozilla.fenix.R
class PairInstructionsFragment : BottomSheetDialogFragment(), BackHandler {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
(activity as AppCompatActivity).title = getString(R.string.preferences_sync)
}
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.setText(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(View.OnClickListener {
val directions = PairInstructionsFragmentDirections.actionPairInstructionsFragmentToPairFragment()
Navigation.findNavController(view!!).navigate(directions)
})
val cancelCamera = view.findViewById(R.id.pair_cancel) as Button
cancelCamera.setOnClickListener(View.OnClickListener {
onBackPressed()
})
}
override fun onBackPressed(): Boolean {
return true
}
}

View File

@ -188,7 +188,7 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
private fun getClickListenerForSignIn(): OnPreferenceClickListener {
return OnPreferenceClickListener {
val directions = SettingsFragmentDirections.actionSettingsFragmentToSyncFragment()
val directions = SettingsFragmentDirections.actionSettingsFragmentToTurnOnSyncFragment()
Navigation.findNavController(view!!).navigate(directions)
true
}

View File

@ -6,6 +6,7 @@ package org.mozilla.fenix.settings
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.Navigation
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import org.mozilla.fenix.BrowserDirection
@ -16,8 +17,8 @@ import org.mozilla.fenix.ext.requireComponents
class TurnOnSyncFragment : PreferenceFragmentCompat() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
override fun onResume() {
super.onResume()
(activity as AppCompatActivity).title = getString(R.string.preferences_sync)
(activity as AppCompatActivity).supportActionBar?.show()
}
@ -29,8 +30,11 @@ class TurnOnSyncFragment : PreferenceFragmentCompat() {
findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sync_sign_in))
val preferenceNewAccount =
findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sync_create_account))
val preferencePairSignIn =
findPreference<Preference>(context!!.getPreferenceKey(R.string.pref_key_sync_pair))
preferenceSignIn?.onPreferenceClickListener = getClickListenerForSignIn()
preferenceNewAccount?.onPreferenceClickListener = getClickListenerForSignIn()
preferencePairSignIn?.onPreferenceClickListener = getClickListenerForPairing()
}
private fun getClickListenerForSignIn(): Preference.OnPreferenceClickListener {
@ -47,4 +51,13 @@ class TurnOnSyncFragment : PreferenceFragmentCompat() {
true
}
}
private fun getClickListenerForPairing(): Preference.OnPreferenceClickListener {
return Preference.OnPreferenceClickListener {
val directions = TurnOnSyncFragmentDirections.actionTurnOnSyncFragmentToPairInstructionsFragment()
Navigation.findNavController(view!!).navigate(directions)
true
}
}
}

View File

@ -0,0 +1,23 @@
<!-- 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/. -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/pair_layout"/>
<TextView
android:id="@+id/pair_instructions"
android:background="#8000"
android:layout_marginTop="10dp"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/pair_instructions"
android:textSize="20sp"
android:gravity="center"
android:textColor="@color/photonWhite"/>
</RelativeLayout>

View File

@ -0,0 +1,58 @@
<!-- 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/. -->
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/pair_instructions_fragment"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?foundation">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"/>
<TextView
android:id="@+id/pair_instructions_info"
style="@style/QuickSettingsText.Icon"
android:layout_height="@dimen/quicksettings_item_height"
android:layout_width="wrap_content"
android:drawableStart="@drawable/ic_qr"
android:text="@string/pair_instructions"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="24dp"/>
<Button
android:id="@+id/pair_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
style="@style/SitePermissionButton"
android:text="@string/pair_cancel"
app:layout_constraintEnd_toStartOf="@+id/pair_open_camera"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@+id/pair_instructions_info"
/>
<Button
android:id="@+id/pair_open_camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/SitePermissionButton"
android:text="@string/pair_open_camera"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@+id/pair_cancel"
app:layout_constraintTop_toTopOf="@+id/pair_cancel"
android:backgroundTint="?accent"
android:textColor="?contrastText"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -237,8 +237,8 @@
android:id="@+id/action_settingsFragment_to_searchEngineFragment"
app:destination="@id/searchEngineFragment" />
<action
android:id="@+id/action_settingsFragment_to_syncFragment"
app:destination="@id/syncFragment" />
android:id="@+id/action_settingsFragment_to_turnOnSyncFragment"
app:destination="@id/turnOnSyncFragment" />
<action
android:id="@+id/action_settingsFragment_to_aboutFragment"
app:destination="@id/aboutFragment" />
@ -275,11 +275,33 @@
android:label="SearchEngineFragment" />
<fragment
android:id="@+id/syncFragment"
android:id="@+id/turnOnSyncFragment"
android:name="org.mozilla.fenix.settings.TurnOnSyncFragment"
android:label="SyncFragment">
android:label="TurnOnSyncFragment">
<action
android:id="@+id/action_settingsFragment_to_browserFragment"
android:id="@+id/action_turnOnSyncFragment_to_browserFragment"
app:destination="@id/browserFragment"
app:popUpTo="@+id/settingsFragment" />
<action
android:id="@+id/action_turnOnSyncFragment_to_pairInstructionsFragment"
app:destination="@id/pairInstructionsFragment" />
</fragment>
<fragment
android:id="@+id/pairInstructionsFragment"
android:name="org.mozilla.fenix.settings.PairInstructionsFragment"
android:label="PairInstructionsFragment">
<action
android:id="@+id/action_pairInstructionsFragment_to_pairFragment"
app:destination="@id/pairFragment" />
</fragment>
<fragment
android:id="@+id/pairFragment"
android:name="org.mozilla.fenix.settings.PairFragment"
android:label="PairFragment">
<action
android:id="@+id/action_pairFragment_to_browserFragment"
app:destination="@id/browserFragment"
app:popUpTo="@+id/settingsFragment" />
</fragment>

View File

@ -35,6 +35,7 @@
<string name="pref_key_sync_bookmarks" translatable="false">pref_key_sync_bookmarks</string>
<string name="pref_key_sign_out" translatable="false">pref_key_sign_out</string>
<string name="pref_key_cached_account" translatable="false">pref_key_cached_account</string>
<string name="pref_key_sync_pair" translatable="false">pref_key_sync_pair</string>
<string name="pref_key_sync_sign_in" translatable="false">pref_key_sync_sign_in</string>
<string name="pref_key_sync_create_account" translatable="false">pref_key_sync_create_account</string>

View File

@ -186,11 +186,21 @@
<!-- Turn On Sync Preferences -->
<!-- Header of the Turn on Sync preference view -->
<string name="preferences_sync">Turn on Sync</string>
<!-- Preference for pairing -->
<string name="preferences_sync_pair">Scan pairing code in desktop Firefox</string>
<!-- Preference for account login -->
<string name="preferences_sync_sign_in">Sign in</string>
<!-- Preference for account creation -->
<string name="preferences_sync_create_account">Create an account</string>
<!-- Pairing Feature strings -->
<!-- Instructions on how to access pairing -->
<string name="pair_instructions"><![CDATA[Visit <b>firefox.com/pair</b> in Firefox on your computer to get your QR code.]]></string>
<!-- Button to open camera for pairing -->
<string name="pair_open_camera">Open Camera</string>
<!-- Button to cancel pairing -->
<string name="pair_cancel">Cancel</string>
<!-- Theme Preferences -->
<!-- Preference for using light theme -->
<string name="preference_light_theme">Light</string>

View File

@ -5,6 +5,10 @@
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.preference.Preference
android:key="@string/pref_key_sync_pair"
android:title="@string/preferences_sync_pair"
android:icon="@drawable/ic_qr" />
<androidx.preference.Preference
android:key="@string/pref_key_sync_sign_in"
android:title="@string/preferences_sync_sign_in"