You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iceraven-browser/app/src/main/java/org/mozilla/fenix/settings/creditcards/CreditCardEditorFragment.kt

168 lines
6.0 KiB
Kotlin

/* 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.creditcards
import android.annotation.SuppressLint
import android.content.DialogInterface
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.AlertDialog
import androidx.core.view.MenuProvider
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import mozilla.components.support.ktx.android.view.hideKeyboard
import mozilla.components.support.ktx.android.view.showKeyboard
import mozilla.components.ui.widgets.withCenterAlignedButtons
import org.mozilla.fenix.R
import org.mozilla.fenix.SecureFragment
import org.mozilla.fenix.databinding.FragmentCreditCardEditorBinding
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.placeCursorAtEnd
import org.mozilla.fenix.ext.redirectToReAuth
import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.settings.creditcards.controller.DefaultCreditCardEditorController
import org.mozilla.fenix.settings.creditcards.interactor.CreditCardEditorInteractor
import org.mozilla.fenix.settings.creditcards.interactor.DefaultCreditCardEditorInteractor
import org.mozilla.fenix.settings.creditcards.view.CreditCardEditorView
/**
* Display a credit card editor for adding and editing a credit card.
*/
class CreditCardEditorFragment :
SecureFragment(R.layout.fragment_credit_card_editor),
MenuProvider {
private lateinit var creditCardEditorState: CreditCardEditorState
private lateinit var creditCardEditorView: CreditCardEditorView
private lateinit var menu: Menu
private var deleteDialog: AlertDialog? = null
private val args by navArgs<CreditCardEditorFragmentArgs>()
/**
* Returns true if a credit card is being edited, and false otherwise.
*/
private val isEditing: Boolean
get() = args.creditCard != null
private lateinit var interactor: CreditCardEditorInteractor
@SuppressLint("ClickableViewAccessibility")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
requireActivity().addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED)
val storage = requireContext().components.core.autofillStorage
interactor = DefaultCreditCardEditorInteractor(
controller = DefaultCreditCardEditorController(
storage = storage,
lifecycleScope = lifecycleScope,
navController = findNavController(),
showDeleteDialog = ::showDeleteDialog,
),
)
val binding = FragmentCreditCardEditorBinding.bind(view)
lifecycleScope.launch(Dispatchers.Main) {
creditCardEditorState = withContext(Dispatchers.IO) {
args.creditCard?.toCreditCardEditorState(storage)
?: getInitialCreditCardEditorState()
}
creditCardEditorView = CreditCardEditorView(binding, interactor)
creditCardEditorView.bind(creditCardEditorState)
binding.apply {
cardNumberInput.apply {
requestFocus()
placeCursorAtEnd()
showKeyboard()
}
expiryMonthDropDown.setOnTouchListener { view, _ ->
view?.hideKeyboard()
false
}
expiryYearDropDown.setOnTouchListener { view, _ ->
view?.hideKeyboard()
false
}
}
}
}
override fun onResume() {
super.onResume()
if (!isEditing) {
showToolbar(getString(R.string.credit_cards_add_card))
} else {
showToolbar(getString(R.string.credit_cards_edit_card))
}
}
/**
* Close the keyboard, any open dialogs or menus and then reauthenticate if the
* fragment is paused and the user is not navigating to [CreditCardsManagementFragment].
*/
override fun onPause() {
view?.hideKeyboard()
menu.close()
deleteDialog?.dismiss()
redirectToReAuth(
listOf(R.id.creditCardsManagementFragment),
findNavController().currentDestination?.id,
R.id.creditCardEditorFragment,
)
super.onPause()
}
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.credit_card_editor, menu)
this.menu = menu
menu.findItem(R.id.delete_credit_card_button).isVisible = isEditing
}
@Suppress("MagicNumber")
override fun onMenuItemSelected(item: MenuItem): Boolean = when (item.itemId) {
R.id.delete_credit_card_button -> {
args.creditCard?.let { interactor.onDeleteCardButtonClicked(it.guid) }
true
}
R.id.save_credit_card_button -> {
creditCardEditorView.saveCreditCard(creditCardEditorState)
true
}
else -> false
}
private fun showDeleteDialog(onPositiveClickListener: DialogInterface.OnClickListener) {
deleteDialog = AlertDialog.Builder(requireContext()).apply {
setMessage(R.string.credit_cards_delete_dialog_confirmation_2)
setNegativeButton(R.string.credit_cards_cancel_button) { dialog: DialogInterface, _ ->
dialog.cancel()
}
setPositiveButton(R.string.credit_cards_delete_dialog_button, onPositiveClickListener)
create().withCenterAlignedButtons()
}.show()
}
companion object {
// Number of years to show in the expiry year dropdown.
const val NUMBER_OF_YEARS_TO_SHOW = 10
}
}