1616
1717package com.ichi2.anki.dialogs
1818
19+ import android.content.Context
1920import android.os.Bundle
21+ import android.text.Spanned
22+ import android.view.LayoutInflater
2023import android.view.View
21- import android.view.View.MeasureSpec
2224import android.view.ViewGroup
2325import android.widget.TextView
26+ import androidx.annotation.CheckResult
2427import androidx.annotation.StringRes
2528import androidx.appcompat.app.AlertDialog
2629import androidx.core.os.bundleOf
30+ import androidx.core.text.HtmlCompat
31+ import androidx.core.text.parseAsHtml
2732import androidx.fragment.app.DialogFragment
2833import androidx.fragment.app.Fragment
29- import androidx.fragment.app.FragmentManager
3034import androidx.fragment.app.viewModels
3135import androidx.recyclerview.widget.LinearLayoutManager
3236import androidx.recyclerview.widget.RecyclerView
@@ -35,18 +39,23 @@ import androidx.viewpager2.widget.ViewPager2
3539import com.google.android.material.tabs.TabLayout
3640import com.google.android.material.tabs.TabLayoutMediator
3741import com.ichi2.anki.CardTemplateEditor
42+ import com.ichi2.anki.Flag
3843import com.ichi2.anki.R
3944import com.ichi2.anki.databinding.DialogGenericRecyclerViewBinding
4045import com.ichi2.anki.databinding.DialogInsertFieldBinding
46+ import com.ichi2.anki.databinding.DialogInsertSpecialFieldRecyclerItemBinding
4147import com.ichi2.anki.dialogs.InsertFieldDialogViewModel.Companion.KEY_FIELD_ITEMS
4248import com.ichi2.anki.dialogs.InsertFieldDialogViewModel.Companion.KEY_INSERT_FIELD_METADATA
4349import com.ichi2.anki.dialogs.InsertFieldDialogViewModel.Companion.KEY_REQUEST_KEY
4450import com.ichi2.anki.dialogs.InsertFieldDialogViewModel.Tab
4551import com.ichi2.anki.launchCatchingTask
52+ import com.ichi2.anki.model.SpecialField
53+ import com.ichi2.anki.model.SpecialFields
4654import com.ichi2.utils.create
4755import com.ichi2.utils.negativeButton
4856import com.ichi2.utils.title
4957import dev.androidbroadcast.vbpd.viewBinding
58+ import org.jetbrains.annotations.VisibleForTesting
5059
5160/* *
5261 * Dialog fragment used to show the fields that the user can insert in the card editor. This
@@ -99,8 +108,6 @@ class InsertFieldDialog : DialogFragment() {
99108 viewModel.currentTab = selectedTab
100109 }
101110 super .onPageSelected(position)
102-
103- binding.viewPager.updateHeight(childFragmentManager)
104111 }
105112 },
106113 )
@@ -199,6 +206,11 @@ class InsertFieldDialog : DialogFragment() {
199206 override fun getItemCount (): Int = viewModel.fieldNames.size
200207 }
201208 }
209+
210+ override fun onResume () {
211+ super .onResume()
212+ this .requireView().requestLayout() // update the height of the ViewPager
213+ }
202214 }
203215
204216 class SelectSpecialFieldFragment : Fragment (R .layout.dialog_generic_recycler_view) {
@@ -214,52 +226,93 @@ class InsertFieldDialog : DialogFragment() {
214226 super .onViewCreated(view, savedInstanceState)
215227
216228 binding.root.adapter =
217- object : RecyclerView .Adapter <RecyclerView . ViewHolder >() {
229+ object : RecyclerView .Adapter <InsertFieldViewHolder >() {
218230 override fun onCreateViewHolder (
219231 parent : ViewGroup ,
220232 viewType : Int ,
221- ): RecyclerView .ViewHolder {
222- val root = layoutInflater.inflate(R .layout.material_dialog_list_item, parent, false )
223- return object : RecyclerView .ViewHolder (root) {}
224- }
233+ ) = InsertFieldViewHolder (
234+ DialogInsertSpecialFieldRecyclerItemBinding .inflate(
235+ LayoutInflater .from(parent.context),
236+ parent,
237+ false ,
238+ ),
239+ )
225240
226241 override fun onBindViewHolder (
227- holder : RecyclerView . ViewHolder ,
242+ holder : InsertFieldViewHolder ,
228243 position : Int ,
229244 ) {
230- val textView = holder.itemView as TextView
231245 val field = viewModel.specialFields[position]
232- textView.text = field.name
233- textView.setOnClickListener { viewModel.selectSpecialField(field) }
246+
247+ holder.binding.title.text = " {{${field.name} }}"
248+ holder.binding.description.text = field.buildDescription(requireContext(), viewModel.metadata)
249+ holder.binding.root.setOnClickListener { viewModel.selectSpecialField(field) }
234250 }
235251
236252 override fun getItemCount (): Int = viewModel.specialFields.size
237253 }
238254 binding.root.layoutManager = LinearLayoutManager (context)
239255 }
256+
257+ override fun onResume () {
258+ super .onResume()
259+ this .requireView().requestLayout() // update the height of the ViewPager
260+ }
240261 }
262+
263+ private class InsertFieldViewHolder (
264+ val binding : DialogInsertSpecialFieldRecyclerItemBinding ,
265+ ) : RecyclerView.ViewHolder(binding.root)
241266}
242267
243- fun ViewPager2.updateHeight (fragmentManager : FragmentManager ) {
244- fun getCurrentFragment (fragmentManager : FragmentManager ): Fragment ? {
245- val currentTag = " f$currentItem "
246- return fragmentManager.findFragmentByTag(currentTag)
268+ @VisibleForTesting
269+ @CheckResult
270+ fun SpecialField.buildDescription (
271+ context : Context ,
272+ metadata : InsertFieldMetadata ,
273+ ): Spanned {
274+ fun buildSuffix (value : String? ): String {
275+ if (value == null ) return " "
276+ return context.getString(R .string.special_field_example_suffix, value)
247277 }
278+ return when (this ) {
279+ SpecialFields .FrontSide -> context.getString(R .string.special_field_front_side_help)
280+ SpecialFields .Deck ->
281+ context.getString(R .string.special_field_deck_help, buildSuffix(metadata.deck))
248282
249- post {
250- val fragment = getCurrentFragment(fragmentManager) ? : return @post
251- val recyclerView = fragment.view as ? RecyclerView ? : return @post
283+ SpecialFields .Subdeck ->
284+ context.getString(R .string.special_field_subdeck_help, buildSuffix(metadata.subdeck))
285+ SpecialFields .Flag -> {
286+ val code = metadata.flag ? : " N"
287+ context.getString(
288+ R .string.special_field_card_flag_help,
289+ if (code == " N" ) " flag$code " else " <b>flag$code </b>" ,
290+ " <b>$code </b>" ,
291+ Flag .entries.minOf { it.code },
292+ Flag .entries.maxOf { it.code },
293+ )
294+ }
295+ SpecialFields .Tags -> {
296+ val tags = if (metadata.tags.isNullOrBlank()) null else metadata.tags
297+ context.getString(R .string.special_field_tags_help, buildSuffix(tags))
298+ }
299+ SpecialFields .CardId ->
300+ context.getString(R .string.special_field_card_id_help, buildSuffix(metadata.cardId?.toString()))
252301
253- // Measure RecyclerView height
254- recyclerView.measure (
255- MeasureSpec .makeMeasureSpec(width, MeasureSpec . EXACTLY ) ,
256- MeasureSpec .makeMeasureSpec( 0 , MeasureSpec . UNSPECIFIED ),
257- )
302+ SpecialFields . CardTemplate ->
303+ context.getString (
304+ R .string.special_field_card_help ,
305+ buildSuffix(metadata.cardTemplateName ),
306+ )
258307
259- // Update ViewPager height
260- layoutParams.height = recyclerView.measuredHeight
261- requestLayout()
262- }
308+ SpecialFields .NoteType ->
309+ context.getString(
310+ R .string.special_field_type_help,
311+ buildSuffix(metadata.noteTypeName),
312+ )
313+ // this shouldn't happen
314+ else -> " "
315+ }.parseAsHtml(HtmlCompat .FROM_HTML_MODE_LEGACY )
263316}
264317
265318context(dialog: InsertFieldDialog )
0 commit comments