1
0
Fork 0

Use navArgs helper in fragments

master
Tiger Oakes 2020-02-05 15:33:11 -08:00 committed by Jeff Boek
parent 383a70482c
commit c0d7bc5bd5
14 changed files with 117 additions and 162 deletions

View File

@ -8,11 +8,10 @@ import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.text.method.LinkMovementMethod import android.text.method.LinkMovementMethod
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.core.text.HtmlCompat import androidx.core.text.HtmlCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.navArgs
import kotlinx.android.synthetic.main.fragment_add_on_details.view.* import kotlinx.android.synthetic.main.fragment_add_on_details.view.*
import mozilla.components.feature.addons.Addon import mozilla.components.feature.addons.Addon
import mozilla.components.feature.addons.ui.translate import mozilla.components.feature.addons.ui.translate
@ -25,22 +24,13 @@ import java.util.Locale
/** /**
* A fragment to show the details of an add-on. * A fragment to show the details of an add-on.
*/ */
class AddonDetailsFragment : Fragment() { class AddonDetailsFragment : Fragment(R.layout.fragment_add_on_details) {
private val addon: Addon by lazy {
AddonDetailsFragmentArgs.fromBundle(requireNotNull(arguments)).addon
}
override fun onCreateView( private val args by navArgs<AddonDetailsFragmentArgs>()
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_add_on_details, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
bind(addon, view) bind(args.addon, view)
} }
private fun bind(addon: Addon, view: View) { private fun bind(addon: Addon, view: View) {

View File

@ -9,9 +9,9 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.navArgs
import kotlinx.android.synthetic.main.fragment_add_on_internal_settings.* import kotlinx.android.synthetic.main.fragment_add_on_internal_settings.*
import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSession
import mozilla.components.feature.addons.Addon
import mozilla.components.feature.addons.ui.translate import mozilla.components.feature.addons.ui.translate
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
@ -21,9 +21,8 @@ import org.mozilla.fenix.ext.showToolbar
* A fragment to show the internal settings of an add-on. * A fragment to show the internal settings of an add-on.
*/ */
class AddonInternalSettingsFragment : Fragment() { class AddonInternalSettingsFragment : Fragment() {
private val addon: Addon by lazy {
AddonDetailsFragmentArgs.fromBundle(requireNotNull(arguments)).addon private val args by navArgs<AddonInternalSettingsFragmentArgs>()
}
private lateinit var engineSession: EngineSession private lateinit var engineSession: EngineSession
override fun onCreateView( override fun onCreateView(
@ -38,14 +37,14 @@ class AddonInternalSettingsFragment : Fragment() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
showToolbar(addon.translatableName.translate()) showToolbar(args.addon.translatableName.translate())
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
addonSettingsEngineView.render(engineSession) addonSettingsEngineView.render(engineSession)
engineSession.loadUrl(addon.installedState!!.optionsPageUrl) engineSession.loadUrl(args.addon.installedState!!.optionsPageUrl)
} }
override fun onDestroyView() { override fun onDestroyView() {

View File

@ -7,11 +7,10 @@ package org.mozilla.fenix.addons
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.fragment_add_on_permissions.view.* import kotlinx.android.synthetic.main.fragment_add_on_permissions.view.*
import mozilla.components.feature.addons.Addon import mozilla.components.feature.addons.Addon
@ -26,24 +25,15 @@ private const val LEARN_MORE_URL =
/** /**
* A fragment to show the permissions of an add-on. * A fragment to show the permissions of an add-on.
*/ */
class AddonPermissionsDetailsFragment : Fragment(), View.OnClickListener { class AddonPermissionsDetailsFragment : Fragment(R.layout.fragment_add_on_permissions), View.OnClickListener {
private val addon: Addon by lazy {
AddonDetailsFragmentArgs.fromBundle(requireNotNull(arguments)).addon
}
override fun onCreateView( private val args by navArgs<AddonPermissionsDetailsFragmentArgs>()
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_add_on_permissions, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
showToolbar(addon.translatableName.translate()) showToolbar(args.addon.translatableName.translate())
bindPermissions(addon, view) bindPermissions(args.addon, view)
bindLearnMore(view) bindLearnMore(view)
} }

View File

@ -5,9 +5,7 @@
package org.mozilla.fenix.addons package org.mozilla.fenix.addons
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@ -32,15 +30,7 @@ import org.mozilla.fenix.ext.showToolbar
* Fragment use for managing add-ons. * Fragment use for managing add-ons.
*/ */
@Suppress("TooManyFunctions") @Suppress("TooManyFunctions")
class AddonsManagementFragment : Fragment(), AddonsManagerAdapterDelegate { class AddonsManagementFragment : Fragment(R.layout.fragment_add_ons_management), AddonsManagerAdapterDelegate {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_add_ons_management, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)

View File

@ -15,10 +15,10 @@ import androidx.navigation.findNavController
import kotlinx.android.synthetic.main.fragment_installed_add_on_details.view.* import kotlinx.android.synthetic.main.fragment_installed_add_on_details.view.*
import mozilla.components.feature.addons.Addon import mozilla.components.feature.addons.Addon
import mozilla.components.feature.addons.ui.translate import mozilla.components.feature.addons.ui.translate
import mozilla.components.feature.addons.ui.translatedName
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.ext.showToolbar
import mozilla.components.feature.addons.ui.translatedName
/** /**
* An activity to show the details of a installed add-on. * An activity to show the details of a installed add-on.
@ -57,9 +57,10 @@ class InstalledAddonDetailsFragment : Fragment() {
private fun bindEnableSwitch(view: View) { private fun bindEnableSwitch(view: View) {
val switch = view.enable_switch val switch = view.enable_switch
switch.setState(addon.isEnabled()) switch.setState(addon.isEnabled())
switch.setOnCheckedChangeListener { _, isChecked -> switch.setOnCheckedChangeListener { v, isChecked ->
val addonManager = v.context.components.addonManager
if (isChecked) { if (isChecked) {
requireContext().components.addonManager.enableAddon( addonManager.enableAddon(
addon, addon,
onSuccess = { onSuccess = {
runIfFragmentIsAttached { runIfFragmentIsAttached {
@ -87,7 +88,7 @@ class InstalledAddonDetailsFragment : Fragment() {
} }
) )
} else { } else {
requireContext().components.addonManager.disableAddon( addonManager.disableAddon(
addon, addon,
onSuccess = { onSuccess = {
runIfFragmentIsAttached { runIfFragmentIsAttached {

View File

@ -7,13 +7,11 @@ package org.mozilla.fenix.addons
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.fragment_not_yet_supported_addons.view.* import kotlinx.android.synthetic.main.fragment_not_yet_supported_addons.view.*
import mozilla.components.feature.addons.Addon
import mozilla.components.feature.addons.ui.UnsupportedAddonsAdapter import mozilla.components.feature.addons.ui.UnsupportedAddonsAdapter
import mozilla.components.feature.addons.ui.UnsupportedAddonsAdapterDelegate import mozilla.components.feature.addons.ui.UnsupportedAddonsAdapterDelegate
import org.mozilla.fenix.R import org.mozilla.fenix.R
@ -26,18 +24,10 @@ private const val LEARN_MORE_URL =
/** /**
* Fragment for displaying and managing add-ons that are not yet supported by the browser. * Fragment for displaying and managing add-ons that are not yet supported by the browser.
*/ */
class NotYetSupportedAddonFragment : Fragment(), UnsupportedAddonsAdapterDelegate { class NotYetSupportedAddonFragment :
private val addons: List<Addon> by lazy { Fragment(R.layout.fragment_not_yet_supported_addons), UnsupportedAddonsAdapterDelegate {
NotYetSupportedAddonFragmentArgs.fromBundle(requireNotNull(arguments)).addons.toList()
}
override fun onCreateView( private val args by navArgs<NotYetSupportedAddonFragmentArgs>()
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_not_yet_supported_addons, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
@ -47,7 +37,7 @@ class NotYetSupportedAddonFragment : Fragment(), UnsupportedAddonsAdapterDelegat
adapter = UnsupportedAddonsAdapter( adapter = UnsupportedAddonsAdapter(
addonManager = requireContext().components.addonManager, addonManager = requireContext().components.addonManager,
unsupportedAddonsAdapterDelegate = this@NotYetSupportedAddonFragment, unsupportedAddonsAdapterDelegate = this@NotYetSupportedAddonFragment,
unsupportedAddons = addons unsupportedAddons = args.addons.toList()
) )
} }

View File

@ -10,6 +10,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import kotlinx.android.synthetic.main.fragment_add_on_internal_settings.* import kotlinx.android.synthetic.main.fragment_add_on_internal_settings.*
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.browser.state.action.WebExtensionAction import mozilla.components.browser.state.action.WebExtensionAction
@ -25,12 +26,8 @@ import org.mozilla.fenix.ext.showToolbar
* A fragment to show the web extension action popup with [EngineView]. * A fragment to show the web extension action popup with [EngineView].
*/ */
class WebExtensionActionPopupFragment : Fragment(), EngineSession.Observer { class WebExtensionActionPopupFragment : Fragment(), EngineSession.Observer {
private val webExtensionTitle: String? by lazy {
WebExtensionActionPopupFragmentArgs.fromBundle(requireNotNull(arguments)).webExtensionTitle private val args by navArgs<WebExtensionActionPopupFragmentArgs>()
}
private val webExtensionId: String by lazy {
WebExtensionActionPopupFragmentArgs.fromBundle(requireNotNull(arguments)).webExtensionId
}
private var engineSession: EngineSession? = null private var engineSession: EngineSession? = null
private val coreComponents by lazy { requireComponents.core } private val coreComponents by lazy { requireComponents.core }
private val safeArguments get() = requireNotNull(arguments) private val safeArguments get() = requireNotNull(arguments)
@ -47,7 +44,7 @@ class WebExtensionActionPopupFragment : Fragment(), EngineSession.Observer {
): View? { ): View? {
// Grab the [EngineSession] from the store when the view is created if it is available. // Grab the [EngineSession] from the store when the view is created if it is available.
if (engineSession == null) { if (engineSession == null) {
engineSession = coreComponents.store.state.extensions[webExtensionId]?.popupSession engineSession = coreComponents.store.state.extensions[args.webExtensionId]?.popupSession
} }
return inflater.inflate(R.layout.fragment_add_on_internal_settings, container, false) return inflater.inflate(R.layout.fragment_add_on_internal_settings, container, false)
@ -55,7 +52,7 @@ class WebExtensionActionPopupFragment : Fragment(), EngineSession.Observer {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
val title = webExtensionTitle ?: webExtensionId val title = args.webExtensionTitle ?: args.webExtensionId
showToolbar(title) showToolbar(title)
} }
@ -86,7 +83,7 @@ class WebExtensionActionPopupFragment : Fragment(), EngineSession.Observer {
consumePopupSession() consumePopupSession()
} else { } else {
consumeFrom(coreComponents.store) { state -> consumeFrom(coreComponents.store) { state ->
state.extensions[webExtensionId]?.let { extState -> state.extensions[args.webExtensionId]?.let { extState ->
val popupSession = extState.popupSession val popupSession = extState.popupSession
if (popupSession != null) { if (popupSession != null) {
addonSettingsEngineView.render(popupSession) addonSettingsEngineView.render(popupSession)
@ -105,7 +102,7 @@ class WebExtensionActionPopupFragment : Fragment(), EngineSession.Observer {
private fun consumePopupSession() { private fun consumePopupSession() {
coreComponents.store.dispatch( coreComponents.store.dispatch(
WebExtensionAction.UpdatePopupSessionAction(webExtensionId, popupSession = null) WebExtensionAction.UpdatePopupSessionAction(args.webExtensionId, popupSession = null)
) )
sessionConsumed = true sessionConsumed = true
} }

View File

@ -19,6 +19,7 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import kotlinx.android.synthetic.main.fragment_edit_bookmark.bookmarkNameEdit import kotlinx.android.synthetic.main.fragment_edit_bookmark.bookmarkNameEdit
import kotlinx.android.synthetic.main.fragment_edit_bookmark.bookmarkParentFolderSelector import kotlinx.android.synthetic.main.fragment_edit_bookmark.bookmarkParentFolderSelector
import kotlinx.android.synthetic.main.fragment_edit_bookmark.bookmarkUrlEdit import kotlinx.android.synthetic.main.fragment_edit_bookmark.bookmarkUrlEdit
@ -52,7 +53,7 @@ import org.mozilla.fenix.library.bookmarks.DesktopFolders
*/ */
class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) { class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) {
private lateinit var guidToEdit: String private val args by navArgs<EditBookmarkFragmentArgs>()
private val sharedViewModel: BookmarksSharedViewModel by activityViewModels { private val sharedViewModel: BookmarksSharedViewModel by activityViewModels {
ViewModelProvider.NewInstanceFactory() // this is a workaround for #4652 ViewModelProvider.NewInstanceFactory() // this is a workaround for #4652
} }
@ -68,13 +69,12 @@ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initToolbar() initToolbar()
guidToEdit = EditBookmarkFragmentArgs.fromBundle(arguments!!).guidToEdit
lifecycleScope.launch(Main) { lifecycleScope.launch(Main) {
val context = requireContext() val context = requireContext()
withContext(IO) { withContext(IO) {
val bookmarksStorage = context.components.core.bookmarksStorage val bookmarksStorage = context.components.core.bookmarksStorage
bookmarkNode = bookmarksStorage.getTree(guidToEdit) bookmarkNode = bookmarksStorage.getTree(args.guidToEdit)
bookmarkParent = sharedViewModel.selectedFolder bookmarkParent = sharedViewModel.selectedFolder
?: bookmarkNode?.parentGuid ?: bookmarkNode?.parentGuid
?.let { bookmarksStorage.getTree(it) } ?.let { bookmarksStorage.getTree(it) }
@ -160,7 +160,7 @@ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) {
} }
setPositiveButton(R.string.tab_collection_dialog_positive) { dialog: DialogInterface, _ -> setPositiveButton(R.string.tab_collection_dialog_positive) { dialog: DialogInterface, _ ->
lifecycleScope.launch(IO) { lifecycleScope.launch(IO) {
requireComponents.core.bookmarksStorage.deleteNode(guidToEdit) requireComponents.core.bookmarksStorage.deleteNode(args.guidToEdit)
requireComponents.analytics.metrics.track(Event.RemoveBookmark) requireComponents.analytics.metrics.track(Event.RemoveBookmark)
launch(Main) { launch(Main) {
@ -205,7 +205,7 @@ class EditBookmarkFragment : Fragment(R.layout.fragment_edit_bookmark) {
components.analytics.metrics.track(Event.MovedBookmark) components.analytics.metrics.track(Event.MovedBookmark)
} }
components.core.bookmarksStorage.updateNode( components.core.bookmarksStorage.updateNode(
guidToEdit, args.guidToEdit,
BookmarkInfo( BookmarkInfo(
sharedViewModel.selectedFolder?.guid ?: bookmarkNode!!.parentGuid, sharedViewModel.selectedFolder?.guid ?: bookmarkNode!!.parentGuid,
bookmarkNode?.position, bookmarkNode?.position,

View File

@ -21,6 +21,7 @@ import androidx.core.view.marginStart
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.interpolator.view.animation.FastOutSlowInInterpolator import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import androidx.transition.TransitionInflater import androidx.transition.TransitionInflater
import kotlinx.android.synthetic.main.fragment_search.* import kotlinx.android.synthetic.main.fragment_search.*
import kotlinx.android.synthetic.main.fragment_search.view.* import kotlinx.android.synthetic.main.fragment_search.view.*
@ -73,17 +74,11 @@ class SearchFragment : Fragment(), UserInteractionHandler {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
val session = arguments val args = arguments?.let { navArgs<SearchFragmentArgs>().value }
?.let(SearchFragmentArgs.Companion::fromBundle) val session = args?.sessionId
?.let { it.sessionId }
?.let(requireComponents.core.sessionManager::findSessionById) ?.let(requireComponents.core.sessionManager::findSessionById)
val pastedText = args?.pastedText
val pastedText = arguments val searchAccessPoint = args?.searchAccessPoint
?.let(SearchFragmentArgs.Companion::fromBundle)
?.let { it.pastedText }
val searchAccessPoint = arguments
?.let(SearchFragmentArgs.Companion::fromBundle)?.searchAccessPoint
val view = inflater.inflate(R.layout.fragment_search, container, false) val view = inflater.inflate(R.layout.fragment_search, container, false)
val url = session?.url.orEmpty() val url = session?.url.orEmpty()

View File

@ -12,6 +12,7 @@ import androidx.core.text.HtmlCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import kotlinx.android.synthetic.main.fragment_turn_on_sync.view.* import kotlinx.android.synthetic.main.fragment_turn_on_sync.view.*
import mozilla.components.concept.sync.AccountObserver import mozilla.components.concept.sync.AccountObserver
import mozilla.components.concept.sync.AuthType import mozilla.components.concept.sync.AuthType
@ -22,11 +23,9 @@ import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.ext.showToolbar
@SuppressWarnings("TooManyFunctions")
class TurnOnSyncFragment : Fragment(), AccountObserver { class TurnOnSyncFragment : Fragment(), AccountObserver {
private val safeArguments get() = requireNotNull(arguments) private val args by navArgs<TurnOnSyncFragmentArgs>()
private val args get() = TurnOnSyncFragmentArgs.fromBundle(safeArguments)
private val signInClickListener = View.OnClickListener { private val signInClickListener = View.OnClickListener {
requireComponents.services.accountsAuthFeature.beginAuthentication(requireContext()) requireComponents.services.accountsAuthFeature.beginAuthentication(requireContext())

View File

@ -4,12 +4,16 @@
package org.mozilla.fenix.settings.logins package org.mozilla.fenix.settings.logins
import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.text.InputType import android.text.InputType
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
import androidx.annotation.StringRes
import androidx.appcompat.content.res.AppCompatResources.getDrawable
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.fragment_saved_login_site_info.* import kotlinx.android.synthetic.main.fragment_saved_login_site_info.*
import org.mozilla.fenix.R import org.mozilla.fenix.R
@ -18,14 +22,12 @@ import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.ext.showToolbar
/**
* Displays saved login information for a single website.
*/
class SavedLoginSiteInfoFragment : Fragment(R.layout.fragment_saved_login_site_info) { class SavedLoginSiteInfoFragment : Fragment(R.layout.fragment_saved_login_site_info) {
private val safeArguments get() = requireNotNull(arguments)
private val savedLoginItem: SavedLoginsItem by lazy { private val args by navArgs<SavedLoginSiteInfoFragmentArgs>()
SavedLoginSiteInfoFragmentArgs.fromBundle(
safeArguments
).savedLoginItem
}
override fun onPause() { override fun onPause() {
// If we pause this fragment, we want to pop users back to reauth // If we pause this fragment, we want to pop users back to reauth
@ -39,58 +41,40 @@ class SavedLoginSiteInfoFragment : Fragment(R.layout.fragment_saved_login_site_i
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
siteInfoText.text = savedLoginItem.url siteInfoText.text = args.savedLoginItem.url
copySiteItem.setOnClickListener { copySiteItem.setOnClickListener(
val clipboard = view.context.components.clipboardHandler CopyButtonListener(args.savedLoginItem.url, R.string.logins_site_copied)
clipboard.text = savedLoginItem.url )
showCopiedSnackbar(getString(R.string.logins_site_copied))
context?.components?.analytics?.metrics?.track(Event.CopyLogin)
}
usernameInfoText.text = savedLoginItem.userName usernameInfoText.text = args.savedLoginItem.userName
copyUsernameItem.setOnClickListener { copyUsernameItem.setOnClickListener(
val clipboard = view.context.components.clipboardHandler CopyButtonListener(args.savedLoginItem.userName, R.string.logins_username_copied)
clipboard.text = savedLoginItem.userName )
showCopiedSnackbar(getString(R.string.logins_username_copied))
context?.components?.analytics?.metrics?.track(Event.CopyLogin)
}
passwordInfoText.inputType = passwordInfoText.inputType =
InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
passwordInfoText.text = savedLoginItem.password passwordInfoText.text = args.savedLoginItem.password
revealPasswordItem.setOnClickListener { revealPasswordItem.setOnClickListener {
togglePasswordReveal() togglePasswordReveal(it.context)
}
copyPasswordItem.setOnClickListener {
val clipboard = view.context.components.clipboardHandler
clipboard.text = savedLoginItem.password
showCopiedSnackbar(getString(R.string.logins_password_copied))
context?.components?.analytics?.metrics?.track(Event.CopyLogin)
} }
copyPasswordItem.setOnClickListener(
CopyButtonListener(args.savedLoginItem.password, R.string.logins_password_copied)
)
} }
private fun showCopiedSnackbar(copiedItem: String) { private fun togglePasswordReveal(context: Context) {
view?.let {
FenixSnackbar.make(it, Snackbar.LENGTH_SHORT).setText(copiedItem).show()
}
}
private fun togglePasswordReveal() {
if (passwordInfoText.inputType == InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT) { if (passwordInfoText.inputType == InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT) {
context?.components?.analytics?.metrics?.track(Event.ViewLoginPassword) context.components.analytics.metrics.track(Event.ViewLoginPassword)
revealPasswordItem.setImageDrawable(context?.getDrawable(R.drawable.mozac_ic_password_hide))
passwordInfoText.inputType = InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD passwordInfoText.inputType = InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
revealPasswordItem.contentDescription = revealPasswordItem.setImageDrawable(getDrawable(context, R.drawable.mozac_ic_password_hide))
context?.getString(R.string.saved_login_hide_password) revealPasswordItem.contentDescription = context.getString(R.string.saved_login_hide_password)
} else { } else {
revealPasswordItem.setImageDrawable(context?.getDrawable(R.drawable.mozac_ic_password_reveal)) passwordInfoText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
passwordInfoText.inputType = revealPasswordItem.setImageDrawable(getDrawable(context, R.drawable.mozac_ic_password_reveal))
InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD revealPasswordItem.contentDescription = context.getString(R.string.saved_login_reveal_password)
revealPasswordItem.contentDescription =
context?.getString(R.string.saved_login_reveal_password)
} }
// For the new type to take effect you need to reset the text // For the new type to take effect you need to reset the text
passwordInfoText.text = savedLoginItem.password passwordInfoText.text = args.savedLoginItem.password
} }
override fun onResume() { override fun onResume() {
@ -99,6 +83,29 @@ class SavedLoginSiteInfoFragment : Fragment(R.layout.fragment_saved_login_site_i
WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE WindowManager.LayoutParams.FLAG_SECURE
) )
showToolbar(savedLoginItem.url) showToolbar(args.savedLoginItem.url)
}
/**
* Click listener for a textview's copy button.
* @param value Value to be copied
* @param snackbarText Text to display in snackbar after copying.
*/
private inner class CopyButtonListener(
private val value: String?,
@StringRes private val snackbarText: Int
) : View.OnClickListener {
override fun onClick(view: View) {
val clipboard = view.context.components.clipboardHandler
clipboard.text = value
showCopiedSnackbar(view.context.getString(snackbarText))
view.context.components.analytics.metrics.track(Event.CopyLogin)
}
private fun showCopiedSnackbar(copiedItem: String) {
view?.let {
FenixSnackbar.make(it, Snackbar.LENGTH_SHORT).setText(copiedItem).show()
}
}
} }
} }

View File

@ -21,6 +21,7 @@ import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import kotlinx.android.synthetic.main.fragment_quick_settings_dialog_sheet.* import kotlinx.android.synthetic.main.fragment_quick_settings_dialog_sheet.*
@ -42,26 +43,20 @@ import com.google.android.material.R as MaterialR
* - website permission. * - website permission.
*/ */
class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() { class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
private lateinit var quickSettingsStore: QuickSettingsFragmentStore private lateinit var quickSettingsStore: QuickSettingsFragmentStore
private lateinit var quickSettingsController: QuickSettingsController private lateinit var quickSettingsController: QuickSettingsController
private lateinit var websiteInfoView: WebsiteInfoView private lateinit var websiteInfoView: WebsiteInfoView
private lateinit var websitePermissionsView: WebsitePermissionsView private lateinit var websitePermissionsView: WebsitePermissionsView
private lateinit var interactor: QuickSettingsInteractor private lateinit var interactor: QuickSettingsInteractor
private val safeArguments get() = requireNotNull(arguments) private val args by navArgs<QuickSettingsSheetDialogFragmentArgs>()
private val promptGravity: Int by lazy {
QuickSettingsSheetDialogFragmentArgs.fromBundle(
safeArguments
).gravity
}
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
val context = requireContext()
val context = context!!
val args = QuickSettingsSheetDialogFragmentArgs.fromBundle(safeArguments)
val rootView = inflateRootView(container) val rootView = inflateRootView(container)
quickSettingsStore = QuickSettingsFragmentStore.createStore( quickSettingsStore = QuickSettingsFragmentStore.createStore(
@ -114,7 +109,7 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
} }
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return if (promptGravity == BOTTOM) { return if (args.gravity == BOTTOM) {
BottomSheetDialog(requireContext(), this.theme).apply { BottomSheetDialog(requireContext(), this.theme).apply {
setOnShowListener { setOnShowListener {
val bottomSheet = val bottomSheet =
@ -160,7 +155,7 @@ class QuickSettingsSheetDialogFragment : AppCompatDialogFragment() {
) )
window?.apply { window?.apply {
setGravity(promptGravity) setGravity(args.gravity)
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
// This must be called after addContentView, or it won't fully fill to the edge. // This must be called after addContentView, or it won't fully fill to the edge.
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)

View File

@ -13,6 +13,7 @@ import android.view.View
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import kotlinx.android.synthetic.main.custom_search_engine.* import kotlinx.android.synthetic.main.custom_search_engine.*
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
@ -28,10 +29,12 @@ import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.settings.SupportUtils import org.mozilla.fenix.settings.SupportUtils
import java.util.Locale import java.util.Locale
/**
* Fragment to enter a custom search engine name and URL template.
*/
class EditCustomSearchEngineFragment : Fragment(R.layout.fragment_add_search_engine) { class EditCustomSearchEngineFragment : Fragment(R.layout.fragment_add_search_engine) {
private val engineIdentifier: String by lazy {
EditCustomSearchEngineFragmentArgs.fromBundle(requireArguments()).searchEngineIdentifier private val args by navArgs<EditCustomSearchEngineFragmentArgs>()
}
private lateinit var searchEngine: SearchEngine private lateinit var searchEngine: SearchEngine
@ -39,7 +42,7 @@ class EditCustomSearchEngineFragment : Fragment(R.layout.fragment_add_search_eng
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setHasOptionsMenu(true) setHasOptionsMenu(true)
searchEngine = CustomSearchEngineStore.loadCustomSearchEngines(requireContext()).first { searchEngine = CustomSearchEngineStore.loadCustomSearchEngines(requireContext()).first {
it.identifier == engineIdentifier it.identifier == args.searchEngineIdentifier
} }
} }
@ -104,7 +107,7 @@ class EditCustomSearchEngineFragment : Fragment(R.layout.fragment_add_search_eng
.allSearchEngineIdentifiers() .allSearchEngineIdentifiers()
.map { it.toLowerCase(Locale.ROOT) } .map { it.toLowerCase(Locale.ROOT) }
val nameHasChanged = name != engineIdentifier val nameHasChanged = name != args.searchEngineIdentifier
if (existingIdentifiers.contains(name.toLowerCase(Locale.ROOT)) && nameHasChanged) { if (existingIdentifiers.contains(name.toLowerCase(Locale.ROOT)) && nameHasChanged) {
custom_search_engine_name_field.error = resources custom_search_engine_name_field.error = resources
@ -142,7 +145,7 @@ class EditCustomSearchEngineFragment : Fragment(R.layout.fragment_add_search_eng
SearchStringValidator.Result.Success -> { SearchStringValidator.Result.Success -> {
CustomSearchEngineStore.updateSearchEngine( CustomSearchEngineStore.updateSearchEngine(
context = requireContext(), context = requireContext(),
oldEngineName = engineIdentifier, oldEngineName = args.searchEngineIdentifier,
newEngineName = name, newEngineName = name,
searchQuery = searchString searchQuery = searchString
) )

View File

@ -17,6 +17,7 @@ import android.widget.RadioButton
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.navArgs
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import mozilla.components.feature.sitepermissions.SitePermissions import mozilla.components.feature.sitepermissions.SitePermissions
@ -32,6 +33,7 @@ import org.mozilla.fenix.settings.setStartCheckedIndicator
@SuppressWarnings("TooManyFunctions") @SuppressWarnings("TooManyFunctions")
class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment() { class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment() {
private lateinit var phoneFeature: PhoneFeature private lateinit var phoneFeature: PhoneFeature
private lateinit var sitePermissions: SitePermissions private lateinit var sitePermissions: SitePermissions
private lateinit var radioAllow: RadioButton private lateinit var radioAllow: RadioButton
@ -42,13 +44,10 @@ class SitePermissionsManageExceptionsPhoneFeatureFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
phoneFeature = SitePermissionsManageExceptionsPhoneFeatureFragmentArgs val args by navArgs<SitePermissionsManageExceptionsPhoneFeatureFragmentArgs>()
.fromBundle(requireArguments())
.phoneFeatureId.toPhoneFeature()
sitePermissions = SitePermissionsManageExceptionsPhoneFeatureFragmentArgs phoneFeature = args.phoneFeatureId.toPhoneFeature()
.fromBundle(requireArguments()) sitePermissions = args.sitePermissions
.sitePermissions
showToolbar(phoneFeature.getLabel(requireContext())) showToolbar(phoneFeature.getLabel(requireContext()))
} }