Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 37 additions & 14 deletions AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateEditor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ import com.ichi2.anki.libanki.getStockNotetype
import com.ichi2.anki.libanki.getStockNotetypeKinds
import com.ichi2.anki.libanki.utils.append
import com.ichi2.anki.model.SelectableDeck
import com.ichi2.anki.notetype.AddCardTypeDialog
import com.ichi2.anki.notetype.RenameCardTemplateDialog
import com.ichi2.anki.notetype.RepositionCardTemplateDialog
import com.ichi2.anki.observability.undoableOp
Expand Down Expand Up @@ -833,9 +834,15 @@ open class CardTemplateEditor :
val ordinal = templateEditor.ord
val template = templateEditor.tempNoteType!!.getTemplate(ordinal)

val existingNames =
templateEditor.tempNoteType!!
.notetype.templates
.map { it.name }

RenameCardTemplateDialog.showInstance(
requireContext(),
prefill = template.name,
existingNames = existingNames,
) { newName ->
template.name = newName
Timber.i("updated card template name")
Expand Down Expand Up @@ -971,16 +978,26 @@ open class CardTemplateEditor :
Timber.w("addCardTemplate attempted on cloze note type")
return
}
// Show confirmation dialog
// isOrdinalPendingAdd method will check if there are any new card types added or not,
// if TempModel has new card type then numAffectedCards will be 0 by default.
val numAffectedCards =
if (!CardTemplateNotetype.isOrdinalPendingAdd(templateEditor.tempNoteType!!, templateEditor.ord)) {
templateEditor.getColUnsafe.notetypes.tmplUseCount(templateEditor.tempNoteType!!.notetype, templateEditor.ord)
} else {
0
}
confirmAddCards(templateEditor.tempNoteType!!.notetype, numAffectedCards)
// Show new card type name dialog
val templates = templateEditor.tempNoteType!!.notetype.templates
val defaultName = newCardName(templates)
val existingNames = templates.map { it.name }
AddCardTypeDialog.showInstance(requireContext(), defaultName, existingNames) { enteredName ->
// Show confirmation dialog
val ordinal = templateEditor.mainBinding.cardTemplateEditorPager.currentItem
// isOrdinalPendingAdd method will check if there are any new card types added or not,
// if TempModel has new card type then numAffectedCards will be 0 by default.
val numAffectedCards =
if (!CardTemplateNotetype.isOrdinalPendingAdd(templateEditor.tempNoteType!!, ordinal)) {
templateEditor.getColUnsafe.notetypes.tmplUseCount(templateEditor.tempNoteType!!.notetype, ordinal)
} else {
0
}
// confirmAddCards(templateEditor.tempNoteType!!.notetype, numAffectedCards, enteredName)
executeWithSyncCheck(
Runnable { addNewTemplate(templateEditor.tempNoteType!!.notetype, enteredName) },
)
}
}

fun saveNoteType(): Boolean {
Expand Down Expand Up @@ -1360,7 +1377,9 @@ open class CardTemplateEditor :
numAffectedCards,
tmpl.jsonObject.optString("name"),
)
d.setArgs(msg)
val title = resources.getString(R.string.delete_card_type_title)
d.setArgs(title, msg)
d.setPositiveButton(R.string.dialog_positive_delete)

val deleteCard = Runnable { deleteTemplate(tmpl, notetype) }
val confirm = Runnable { executeWithSyncCheck(deleteCard) }
Expand All @@ -1376,6 +1395,7 @@ open class CardTemplateEditor :
private fun confirmAddCards(
notetype: NotetypeJson,
numAffectedCards: Int,
enteredName: String,
) {
val d = ConfirmationDialog()
val msg =
Expand All @@ -1388,7 +1408,7 @@ open class CardTemplateEditor :
)
d.setArgs(msg)

val addCard = Runnable { addNewTemplate(notetype) }
val addCard = Runnable { addNewTemplate(notetype, enteredName) }
val confirm = Runnable { executeWithSyncCheck(addCard) }
d.setConfirm(confirm)
templateEditor.showDialogFragment(d)
Expand Down Expand Up @@ -1462,12 +1482,15 @@ open class CardTemplateEditor :
* Add new template to a given note type
* @param noteType note type to add new template to
*/
private fun addNewTemplate(noteType: NotetypeJson) {
private fun addNewTemplate(
noteType: NotetypeJson,
name: String,
) {
// Build new template
val oldCardIndex = requireArguments().getInt(CARD_INDEX)
val templates = noteType.templates
val oldTemplate = templates[oldCardIndex]
val newTemplate = Notetypes.newTemplate(newCardName(templates))
val newTemplate = Notetypes.newTemplate(name)
// Set up question & answer formats
newTemplate.qfmt = oldTemplate.qfmt
newTemplate.afmt = oldTemplate.afmt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.ichi2.anki.dialogs

import android.os.Bundle
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import com.ichi2.anki.R
Expand All @@ -32,8 +33,18 @@ import com.ichi2.utils.title
*/
class ConfirmationDialog : DialogFragment() {
private var confirm = Runnable {} // Do nothing by default

private var cancel = Runnable {} // Do nothing by default

@StringRes
private var positiveButtonTextRes: Int = R.string.dialog_ok

fun setPositiveButton(
@StringRes resId: Int,
) {
this.positiveButtonTextRes = resId
}

fun setArgs(message: String?) {
setArgs("", message)
}
Expand Down Expand Up @@ -63,7 +74,7 @@ class ConfirmationDialog : DialogFragment() {
return AlertDialog.Builder(requireContext()).create {
title(text = (if ("" == title) res.getString(R.string.app_name) else title)!!)
message(text = requireArguments().getString("message")!!)
positiveButton(R.string.dialog_ok) {
positiveButton(positiveButtonTextRes) {
confirm.run()
}
negativeButton(R.string.dialog_cancel) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2015 Timothy Rae <perceptualchaos2@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.ichi2.anki.notetype

import android.content.Context
import androidx.appcompat.app.AlertDialog
import androidx.core.widget.doOnTextChanged
import com.ichi2.anki.R
import com.ichi2.utils.getInputField
import com.ichi2.utils.getInputTextLayout
import com.ichi2.utils.input
import com.ichi2.utils.negativeButton
import com.ichi2.utils.positiveButton
import com.ichi2.utils.show
import com.ichi2.utils.title

class AddCardTypeDialog {
companion object {
fun showInstance(
context: Context,
prefill: String,
existingNames: List<String>,
block: (newName: String) -> Unit,
) {
AlertDialog
.Builder(context)
.show {
title(R.string.add_card_type)
positiveButton(R.string.menu_add) { }
negativeButton(R.string.dialog_cancel)
setView(R.layout.dialog_generic_text_input)
}.input(
hint = context.getString(R.string.card_type_name),
displayKeyboard = true,
allowEmpty = false,
prefill = prefill,
waitForPositiveButton = true,
callback = { dialog, result ->
block(result.toString())
dialog.dismiss()
},
).apply {
val field = getInputField()
val layout = getInputTextLayout()
field.doOnTextChanged { text, _, _, _ ->
val name = text.toString().trim()
val isDuplicate = existingNames.any { it.equals(name, ignoreCase = true) }
if (isDuplicate) {
layout.error = context.getString(R.string.card_type_name_used)
positiveButton.isEnabled = false
} else {
layout.error = null
positiveButton.isEnabled = name.isNotEmpty()
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ package com.ichi2.anki.notetype

import android.content.Context
import androidx.appcompat.app.AlertDialog
import androidx.core.widget.doOnTextChanged
import com.ichi2.anki.CollectionManager
import com.ichi2.anki.R
import com.ichi2.anki.utils.ext.actionsNewNameClean
import com.ichi2.utils.getInputField
import com.ichi2.utils.getInputTextLayout
import com.ichi2.utils.input
import com.ichi2.utils.negativeButton
import com.ichi2.utils.positiveButton
Expand All @@ -31,6 +35,7 @@ class RenameCardTemplateDialog {
fun showInstance(
context: Context,
prefill: String,
existingNames: List<String>,
block: (result: String) -> Unit,
) {
AlertDialog
Expand All @@ -41,7 +46,7 @@ class RenameCardTemplateDialog {
negativeButton(R.string.dialog_cancel)
setView(R.layout.dialog_generic_text_input)
}.input(
hint = CollectionManager.TR.actionsNewName(),
hint = CollectionManager.TR.actionsNewNameClean(),
displayKeyboard = true,
allowEmpty = false,
prefill = prefill,
Expand All @@ -50,7 +55,21 @@ class RenameCardTemplateDialog {
block(result.toString())
dialog.dismiss()
},
)
).apply {
val field = getInputField()
val layout = getInputTextLayout()
field.doOnTextChanged { text, _, _, _ ->
val name = text.toString().trim()
val isDuplicate = name != prefill && existingNames.any { it.equals(name, ignoreCase = true) }
if (isDuplicate) {
layout.error = context.getString(R.string.card_type_name_used)
positiveButton.isEnabled = false
} else {
layout.error = null
positiveButton.isEnabled = name.isNotEmpty()
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ fun Translations.cardStatsNoCardClean(): String {
return cardStatsNoCard().replace("[().]".toRegex(), "")
}

/** New name (Removes colon for use as a label) */
fun Translations.actionsNewNameClean(): String = actionsNewName().removeSuffix(":")

/** Previous Card (Study) */
fun Translations.previousCardStudy() = cardStatsPreviousCard(decksStudy())

Expand Down
4 changes: 4 additions & 0 deletions AnkiDroid/src/main/res/values/01-core.xml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@

<!-- Card template editor -->
<string name="title_activity_template_editor">Card types</string>
<string name="delete_card_type_title">Delete card type</string>
<string name="card_template_editor_front">Front template</string>
<string name="card_template_editor_back">Back template</string>
<string name="card_template_editor_styling" maxLength="28">Styling</string>
Expand All @@ -139,6 +140,9 @@
<string name="card_template_editor_insert_field" maxLength="28">Insert field</string>
<string name="card_template_editor_select_field">Select field</string>
<string name="card_template_editor_cant_delete">At least one card type is required</string>
<string name="add_card_type">Add card type</string>
<string name="card_type_name">Card type name</string>
<string name="card_type_name_used">Card type name already used</string>
<plurals name="card_template_editor_confirm_add">
<item quantity="one">This will create %1$d card. Proceed?</item>
<item quantity="other">This will create %1$d cards. Proceed?</item>
Expand Down
Loading