Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhancement: improve reposition field dialog #17900

Merged
merged 1 commit into from
Feb 8, 2025
Merged
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
103 changes: 58 additions & 45 deletions AnkiDroid/src/main/java/com/ichi2/anki/ModelFieldEditor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentManager
import com.google.android.material.snackbar.Snackbar
import com.ichi2.anki.CollectionManager.TR
import com.ichi2.anki.CollectionManager.withCol
import com.ichi2.anki.dialogs.ConfirmationDialog
import com.ichi2.anki.dialogs.LocaleSelectionDialog
Expand All @@ -45,6 +46,8 @@ import com.ichi2.libanki.NotetypeJson
import com.ichi2.libanki.exception.ConfirmModSchemaException
import com.ichi2.ui.FixedEditText
import com.ichi2.utils.customView
import com.ichi2.utils.getInputField
import com.ichi2.utils.input
import com.ichi2.utils.negativeButton
import com.ichi2.utils.positiveButton
import com.ichi2.utils.show
Expand Down Expand Up @@ -339,56 +342,66 @@ class ModelFieldEditor :
}
}

/*
* Allows the user to select a number less than the number of fields in the current model to
* reposition the current field to
* Processing time is scales with number of items
/**
* Displays a dialog to allow the user to reposition a field within a list.
*/
private fun repositionFieldDialog() {
fieldNameInput = FixedEditText(this).apply { focusWithKeyboard() }
fieldNameInput?.let { fieldNameInput ->
fieldNameInput.setRawInputType(InputType.TYPE_CLASS_NUMBER)
AlertDialog.Builder(this).show {
customView(view = fieldNameInput, paddingStart = 64, paddingEnd = 64, paddingTop = 32)
title(text = String.format(resources.getString(R.string.model_field_editor_reposition), 1, fieldsLabels.size))
positiveButton(R.string.dialog_ok) {
val newPosition = fieldNameInput.text.toString()
val pos: Int =
try {
newPosition.toInt()
} catch (n: NumberFormatException) {
Timber.w(n)
fieldNameInput.error = resources.getString(R.string.toast_out_of_range)
return@positiveButton
}
if (pos < 1 || pos > fieldsLabels.size) {
fieldNameInput.error = resources.getString(R.string.toast_out_of_range)
} else {
// Input is valid, now attempt to modify
try {
getColUnsafe.modSchema()
repositionField(pos - 1)
} catch (e: ConfirmModSchemaException) {
e.log()
/**
* Shows an input dialog for selecting a new position.
*
* @param numberOfTemplates The total number of available positions.
* @param result A lambda function that receives the validated new position as an integer.
*/
fun showDialog(
numberOfTemplates: Int,
result: (Int) -> Unit,
) {
AlertDialog
.Builder(this)
.show {
positiveButton(R.string.dialog_ok) {
val input = (it as AlertDialog).getInputField()
result(input.text.toString().toInt())
}
negativeButton(R.string.dialog_cancel)
setMessage(TR.fieldsNewPosition1(numberOfTemplates))
setView(R.layout.dialog_generic_text_input)
}.input(
prefill = (currentPos + 1).toString(),
inputType = InputType.TYPE_CLASS_NUMBER,
displayKeyboard = true,
waitForPositiveButton = false,
) { dialog, text: CharSequence ->
val number = text.toString().toIntOrNull()
dialog.positiveButton.isEnabled = number != null && number in 1..numberOfTemplates
}
}

// Handle mod schema confirmation
val c = ConfirmationDialog()
c.setArgs(resources.getString(R.string.full_sync_confirmation))
val confirm =
Runnable {
try {
getColUnsafe.modSchemaNoCheck()
repositionField(pos - 1)
} catch (e1: JSONException) {
throw RuntimeException(e1)
}
}
c.setConfirm(confirm)
[email protected](c)
// handle repositioning
showDialog(fieldsLabels.size) { newPosition ->
if (newPosition == currentPos + 1) return@showDialog

Timber.i("Repositioning field from %d to %d", currentPos, newPosition)
try {
getColUnsafe.modSchema()
repositionField(newPosition - 1)
} catch (e: ConfirmModSchemaException) {
e.log()

// Handle mod schema confirmation
val c = ConfirmationDialog()
c.setArgs(resources.getString(R.string.full_sync_confirmation))
val confirm =
Runnable {
try {
getColUnsafe.modSchemaNoCheck()
repositionField(newPosition - 1)
} catch (e1: JSONException) {
throw RuntimeException(e1)
}
}
}
negativeButton(R.string.dialog_cancel)
c.setConfirm(confirm)
[email protected](c)
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions AnkiDroid/src/main/res/values/17-model-manager.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
<string name="toast_last_field">Note types must have at least one field</string>
<string name="toast_empty_name">You must enter a name</string>
<string name="toast_duplicate_field">Field name already used</string>
<string name="toast_out_of_range">You must enter a valid value</string>


<!--Plurals-->
Expand Down Expand Up @@ -46,7 +45,6 @@
<string name="model_field_editor_rename">Rename field</string>
<string name="model_field_editor_language_hint">Set keyboard language hint</string>
<string name="model_field_editor_reposition_menu">Reposition field</string>
<string name="model_field_editor_reposition">Reposition field (enter a value %1$d–%2$d)</string>
<string name="model_field_editor_toggle_sticky">Remember last input when adding</string>
<string name="model_field_editor_changing">Updating fields</string>
<string name="model_field_editor_sort_field">Sort by this field</string>
Expand Down