diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateEditor.kt b/AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateEditor.kt index b15cd90fd8e4..842f28db48ba 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateEditor.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateEditor.kt @@ -41,14 +41,12 @@ import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayoutMediator import com.ichi2.anim.ActivityTransitionAnimation.Direction.* -import com.ichi2.anki.dialogs.ConfirmationDialog -import com.ichi2.anki.dialogs.DeckSelectionDialog +import com.ichi2.anki.dialogs.* import com.ichi2.anki.dialogs.DeckSelectionDialog.DeckSelectionListener import com.ichi2.anki.dialogs.DeckSelectionDialog.SelectableDeck -import com.ichi2.anki.dialogs.DiscardChangesDialog -import com.ichi2.anki.dialogs.InsertFieldDialog.InsertFieldListener -import com.ichi2.anki.dialogs.InsertFieldDialogFactory +import com.ichi2.anki.dialogs.InsertFieldDialog.Companion.REQUEST_FIELD_INSERT import com.ichi2.anki.exception.ConfirmModSchemaException +import com.ichi2.annotations.NeedsTest import com.ichi2.async.TaskListenerWithContext import com.ichi2.libanki.* import com.ichi2.libanki.Collection @@ -428,20 +426,13 @@ open class CardTemplateEditor : AnkiActivity(), DeckSelectionListener { } } + @NeedsTest( + "the kotlin migration made this method crash due to a recursive call when the dialog would return its data" + ) private fun showInsertFieldDialog() { - if (mTemplateEditor.mFieldNames == null) { - return + mTemplateEditor.mFieldNames?.let { fieldNames -> + mTemplateEditor.showDialogFragment(InsertFieldDialog.newInstance(fieldNames)) } - val insertFieldDialogFactory = InsertFieldDialogFactory( - object : InsertFieldListener { - override fun insertField(field: String?) { - insertField(field) - } - }).attachToActivity(mTemplateEditor) - val insertFieldDialog = insertFieldDialogFactory - .newInsertFieldDialog() - .withArguments(mTemplateEditor.mFieldNames!!) - mTemplateEditor.showDialogFragment(insertFieldDialog) } @Suppress("unused") @@ -463,6 +454,12 @@ open class CardTemplateEditor : AnkiActivity(), DeckSelectionListener { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { initTabLayoutMediator() + parentFragmentManager.setFragmentResultListener(REQUEST_FIELD_INSERT, viewLifecycleOwner) { key, bundle -> + if (key == REQUEST_FIELD_INSERT) { + // this is guaranteed to be non null, as we put a non null value on the other side + insertField(bundle.getString(InsertFieldDialog.KEY_INSERTED_FIELD)!!) + } + } } private fun initTabLayoutMediator() { diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/InsertFieldDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/InsertFieldDialog.kt index e2dd62c5ab57..23ab180932d6 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/InsertFieldDialog.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/InsertFieldDialog.kt @@ -19,32 +19,30 @@ package com.ichi2.anki.dialogs import android.os.Bundle import android.view.ViewGroup import android.widget.TextView +import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import androidx.recyclerview.widget.RecyclerView import com.afollestad.materialdialogs.MaterialDialog +import com.ichi2.anki.CardTemplateEditor import com.ichi2.anki.R import java.util.* /** - * This is a reusable convenience class which makes it easy to show a insert field dialog as a DialogFragment. - * Create a new instance with required fields list, then show it via the fragment manager as usual. + * Dialog fragment used to show the fields that the user can insert in the card editor. This + * fragment can notify other fragments from the same activity about an inserted field. + * + * @see [CardTemplateEditor.CardTemplateFragment] */ -class InsertFieldDialog(private val insertFieldListener: InsertFieldListener) : DialogFragment() { +class InsertFieldDialog : DialogFragment() { private lateinit var mDialog: MaterialDialog private lateinit var mFieldList: List - fun withArguments(fieldItems: List): InsertFieldDialog { - val args = Bundle() - args.putStringArrayList("fieldItems", ArrayList(fieldItems)) - this.arguments = args - return this - } /** * A dialog for inserting field in card template editor */ override fun onCreateDialog(savedInstanceState: Bundle?): MaterialDialog { super.onCreate(savedInstanceState) - mFieldList = requireArguments().getStringArrayList("fieldItems")!! + mFieldList = requireArguments().getStringArrayList(KEY_FIELD_ITEMS)!! val adapter: RecyclerView.Adapter<*> = object : RecyclerView.Adapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val root = layoutInflater.inflate(R.layout.material_dialog_list_item, parent, false) @@ -70,11 +68,28 @@ class InsertFieldDialog(private val insertFieldListener: InsertFieldListener) : } private fun selectFieldAndClose(textView: TextView) { - insertFieldListener.insertField(textView.text.toString()) + parentFragmentManager.setFragmentResult( + REQUEST_FIELD_INSERT, + bundleOf(KEY_INSERTED_FIELD to textView.text.toString()) + ) mDialog.dismiss() } - interface InsertFieldListener { - fun insertField(field: String?) + companion object { + /** + * Other fragments sharing the activity can use this with + * [androidx.fragment.app.FragmentManager.setFragmentResultListener] to get a result back. + */ + const val REQUEST_FIELD_INSERT = "request_field_insert" + + /** + * This fragment requires that a list of fields names to be passed in. + */ + const val KEY_INSERTED_FIELD = "key_inserted_field" + private const val KEY_FIELD_ITEMS = "key_field_items" + + fun newInstance(fieldItems: List): InsertFieldDialog = InsertFieldDialog().apply { + arguments = bundleOf(KEY_FIELD_ITEMS to ArrayList(fieldItems)) + } } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/InsertFieldDialogFactory.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/InsertFieldDialogFactory.kt deleted file mode 100644 index ef0b0178c93a..000000000000 --- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/InsertFieldDialogFactory.kt +++ /dev/null @@ -1,35 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2021 Akshay Jadhav * - * * - * This program is free software; you can redistribute it and/or modify it under * - * the terms of the GNU General Public License as published by the Free Software * - * Foundation; either version 3 of the License, or (at your option) any later * - * version. * - * * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY * - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * - * PARTICULAR PURPOSE. See the GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License along with * - * this program. If not, see . * - ****************************************************************************************/ - -package com.ichi2.anki.dialogs - -import androidx.fragment.app.Fragment -import com.ichi2.anki.dialogs.InsertFieldDialog.InsertFieldListener -import com.ichi2.utils.ExtendedFragmentFactory -import java.io.Serializable - -class InsertFieldDialogFactory(private val insertFieldListener: InsertFieldListener) : ExtendedFragmentFactory(), Serializable { - override fun instantiate(classLoader: ClassLoader, className: String): Fragment { - val cls = loadFragmentClass(classLoader, className) - return if (cls == InsertFieldDialog::class.java) { - newInsertFieldDialog() - } else super.instantiate(classLoader, className) - } - - fun newInsertFieldDialog(): InsertFieldDialog { - return InsertFieldDialog(insertFieldListener) - } -}