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

Introduce enums in Dialog #17432

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Arthur-Milchior
Copy link
Member

In order to improve typing

Copy link
Member

@david-allison david-allison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't feel like a major improvement, but OK

@david-allison david-allison added the Needs Author Reply Waiting for a reply from the original author label Nov 13, 2024

This comment was marked as outdated.

Copy link
Member

@david-allison david-allison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make the public constants private and I'll approve.

The ARG_ prefix is a nice to have, but optional

I prefer Type.fromCode than fromCode, but this is optional

Subject: [PATCH] refactor: extract dialog fragments from Anki[Activity/Fragment]

* dismissAllDialogFragments
* showDialogFragment

**AnkiFragment**
* showDialogFragment

This affects all callers, as we now use extension methods
---
Index: AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt	(revision 1cc704df7c44c59a8bb3f342fa5c8052982d687b)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt	(date 1733282778465)
@@ -20,15 +20,11 @@
 import androidx.annotation.CheckResult
 import androidx.appcompat.app.AlertDialog
 import com.ichi2.anki.R
-import com.ichi2.anki.dialogs.ImportDialog.Type.Companion.fromCode
 import com.ichi2.utils.negativeButton
 import com.ichi2.utils.positiveButton
 import timber.log.Timber
 import java.net.URLDecoder
 
-const val IMPORT_DIALOG_TYPE_KEY = "dialogType"
-const val IMPORT_DIALOG_PACKAGE_PATH_KEY = "packagePath"
-
 class ImportDialog : AsyncDialogFragment() {
     enum class Type(val code: Int) {
         DIALOG_IMPORT_ADD_CONFIRM(0), DIALOG_IMPORT_REPLACE_CONFIRM(1);
@@ -44,7 +40,7 @@
 
     override fun onCreateDialog(savedInstanceState: Bundle?): AlertDialog {
         super.onCreate(savedInstanceState)
-        val type = fromCode(requireArguments().getInt(IMPORT_DIALOG_TYPE_KEY))
+        val type = Type.fromCode(requireArguments().getInt(IMPORT_DIALOG_TYPE_KEY))
         val dialog = AlertDialog.Builder(requireActivity())
         dialog.setCancelable(true)
         val packagePath = requireArguments().getString(IMPORT_DIALOG_PACKAGE_PATH_KEY)!!
@@ -100,6 +96,8 @@
     }
 
     companion object {
+        private const val IMPORT_DIALOG_TYPE_KEY = "dialogType"
+        private const val IMPORT_DIALOG_PACKAGE_PATH_KEY = "packagePath"
 
         /**
          * A set of dialogs which deal with importing a file
Index: AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt	(revision 1cc704df7c44c59a8bb3f342fa5c8052982d687b)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt	(date 1733282523137)
@@ -15,29 +15,9 @@
 import com.ichi2.anki.AnkiActivity
 import com.ichi2.anki.DeckPicker
 import com.ichi2.anki.R
-import com.ichi2.anki.dialogs.MediaCheckDialog.Type.Companion.fromCode
 import com.ichi2.anki.showError
 import com.ichi2.libanki.MediaCheckResult
 
-/**
- * Key for an ordinal in the Type.entries.
- */
-const val MEDIA_CHECK_DIALOG_TYPE_KEY = "dialogType"
-
-/**
- * Key for an array of strings of name of missing media
- */
-const val NO_HAVE = "noHave"
-
-/**
- * Key for an array of strings of name of unused media
- */
-const val UNUSED = "unused"
-
-/**
- * Key for an array of strings of name of invalid media
- */
-const val INVALID = "invalid"
 class MediaCheckDialog : AsyncDialogFragment() {
     interface MediaCheckDialogListener {
         fun showMediaCheckDialog(dialogType: Type)
@@ -64,9 +44,9 @@
                     .create()
             }
             Type.DIALOG_MEDIA_CHECK_RESULTS -> {
-                val noHave = requireArguments().getStringArrayList(NO_HAVE)
-                val unused = requireArguments().getStringArrayList(UNUSED)
-                val invalid = requireArguments().getStringArrayList(INVALID)
+                val noHave = requireArguments().getStringArrayList(ARG_NO_HAVE)
+                val unused = requireArguments().getStringArrayList(ARG_UNUSED)
+                val invalid = requireArguments().getStringArrayList(ARG_INVALID)
                 // Generate report
                 val report = StringBuilder()
                 if (invalid!!.isNotEmpty()) {
@@ -146,14 +126,14 @@
             }
         }
 
-    private fun typeFromArguments() = fromCode(requireArguments().getInt(MEDIA_CHECK_DIALOG_TYPE_KEY))
+    private fun typeFromArguments() = Type.fromCode(requireArguments().getInt(ARG_MEDIA_CHECK_DIALOG_TYPE_KEY))
 
     override val dialogHandlerMessage: MediaCheckCompleteDialog
         get() {
             val dialogType = typeFromArguments()
-            val noHave = requireArguments().getStringArrayList(NO_HAVE)
-            val unused = requireArguments().getStringArrayList(UNUSED)
-            val invalid = requireArguments().getStringArrayList(INVALID)
+            val noHave = requireArguments().getStringArrayList(ARG_NO_HAVE)
+            val unused = requireArguments().getStringArrayList(ARG_UNUSED)
+            val invalid = requireArguments().getStringArrayList(ARG_INVALID)
 
             return MediaCheckCompleteDialog(dialogType, noHave, unused, invalid)
         }
@@ -168,11 +148,31 @@
     }
 
     companion object {
+        /**
+         * Key for an ordinal in the [Type.entries].
+         */
+        private const val ARG_MEDIA_CHECK_DIALOG_TYPE_KEY = "dialogType"
+
+        /**
+         * Key for an array of strings of name of missing media
+         */
+        private const val ARG_NO_HAVE = "noHave"
+
+        /**
+         * Key for an array of strings of name of unused media
+         */
+        private const val ARG_UNUSED = "unused"
+
+        /**
+         * Key for an array of strings of name of invalid media
+         */
+        private const val ARG_INVALID = "invalid"
+
         @CheckResult
         fun newInstance(dialogType: Type): MediaCheckDialog {
             val f = MediaCheckDialog()
             val args = Bundle()
-            args.putInt(MEDIA_CHECK_DIALOG_TYPE_KEY, dialogType.code)
+            args.putInt(ARG_MEDIA_CHECK_DIALOG_TYPE_KEY, dialogType.code)
             f.arguments = args
             return f
         }
@@ -183,10 +183,10 @@
         fun newInstance(dialogType: Type, checkList: MediaCheckResult): MediaCheckDialog {
             val f = MediaCheckDialog()
             val args = Bundle()
-            args.putStringArrayList(NO_HAVE, ArrayList(checkList.missingFileNames))
-            args.putStringArrayList(UNUSED, ArrayList(checkList.unusedFileNames))
-            args.putStringArrayList(INVALID, ArrayList(checkList.invalidFileNames))
-            args.putInt(MEDIA_CHECK_DIALOG_TYPE_KEY, dialogType.code)
+            args.putStringArrayList(ARG_NO_HAVE, ArrayList(checkList.missingFileNames))
+            args.putStringArrayList(ARG_UNUSED, ArrayList(checkList.unusedFileNames))
+            args.putStringArrayList(ARG_INVALID, ArrayList(checkList.invalidFileNames))
+            args.putInt(ARG_MEDIA_CHECK_DIALOG_TYPE_KEY, dialogType.code)
             f.arguments = args
             return f
         }
@@ -222,19 +222,19 @@
         override fun toMessage(): Message = Message.obtain().apply {
             what = [email protected]
             data = bundleOf(
-                NO_HAVE to noHave,
-                UNUSED to unused,
-                INVALID to invalid,
-                MEDIA_CHECK_DIALOG_TYPE_KEY to dialogType
+                ARG_NO_HAVE to noHave,
+                ARG_UNUSED to unused,
+                ARG_INVALID to invalid,
+                ARG_MEDIA_CHECK_DIALOG_TYPE_KEY to dialogType
             )
         }
 
         companion object {
             fun fromMessage(message: Message): MediaCheckCompleteDialog {
-                val dialogType = fromCode(message.data.getInt(MEDIA_CHECK_DIALOG_TYPE_KEY))
-                val noHave = message.data.getStringArrayList(NO_HAVE)
-                val unused = message.data.getStringArrayList(UNUSED)
-                val invalid = message.data.getStringArrayList(INVALID)
+                val dialogType = Type.fromCode(message.data.getInt(ARG_MEDIA_CHECK_DIALOG_TYPE_KEY))
+                val noHave = message.data.getStringArrayList(ARG_NO_HAVE)
+                val unused = message.data.getStringArrayList(ARG_UNUSED)
+                val invalid = message.data.getStringArrayList(ARG_INVALID)
                 return MediaCheckCompleteDialog(dialogType, noHave, unused, invalid)
             }
         }
Index: AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt	(revision 1cc704df7c44c59a8bb3f342fa5c8052982d687b)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt	(date 1733282931151)
@@ -27,20 +27,9 @@
 import com.ichi2.anki.ConflictResolution
 import com.ichi2.anki.DeckPicker
 import com.ichi2.anki.R
-import com.ichi2.anki.dialogs.SyncErrorDialog.Type.Companion.fromCode
 import com.ichi2.anki.joinSyncMessages
 import com.ichi2.anki.showError
 
-/**
- * Key for the ordinal of the sync error in Type
- */
-const val SYNC_ERROR_DIALOG_TYPE_KEY = "dialogType"
-
-/**
- * Key for the message to display in the dialog
- */
-const val DIALOG_MESSAGE_KEY = "dialogMessage"
-
 class SyncErrorDialog : AsyncDialogFragment() {
     interface SyncErrorDialogListener {
         fun showSyncErrorDialog(dialogType: Type)
@@ -53,7 +42,7 @@
     }
 
     /** The type of the sync error dialog*/
-    private fun type() = fromCode(requireArguments().getInt(SYNC_ERROR_DIALOG_TYPE_KEY))
+    private fun type() = Type.fromCode(requireArguments().getInt(ARG_SYNC_ERROR_DIALOG_TYPE_KEY))
 
     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
         super.onCreate(savedInstanceState)
@@ -214,12 +203,12 @@
             Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL, Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL -> res().getString(R.string.sync_conflict_local_confirm_new)
             Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE, Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE -> res().getString(R.string.sync_conflict_remote_confirm_new)
             Type.DIALOG_SYNC_CORRUPT_COLLECTION -> {
-                val syncMessage = requireArguments().getString(DIALOG_MESSAGE_KEY)
+                val syncMessage = requireArguments().getString(ARG_DIALOG_MESSAGE_KEY)
                 val repairUrl = res().getString(R.string.repair_deck)
                 val dialogMessage = res().getString(R.string.sync_corrupt_database, repairUrl)
                 joinSyncMessages(dialogMessage, syncMessage)
             }
-            else -> requireArguments().getString(DIALOG_MESSAGE_KEY)
+            else -> requireArguments().getString(ARG_DIALOG_MESSAGE_KEY)
         }
 
     /**
@@ -239,7 +228,7 @@
     override val dialogHandlerMessage: SyncErrorDialogMessageHandler
         get() {
             val dialogType = type()
-            val dialogMessage = requireArguments().getString(DIALOG_MESSAGE_KEY)
+            val dialogMessage = requireArguments().getString(ARG_DIALOG_MESSAGE_KEY)
             return SyncErrorDialogMessageHandler(dialogType, dialogMessage)
         }
 
@@ -266,6 +255,17 @@
     }
 
     companion object {
+
+        /**
+         * Key for [SyncErrorDialog.Type.code]; read using [SyncErrorDialog.Type.fromCode]
+         */
+        private const val ARG_SYNC_ERROR_DIALOG_TYPE_KEY = "dialogType"
+
+        /**
+         * Key for the message to display in the dialog
+         */
+        private const val ARG_DIALOG_MESSAGE_KEY = "dialogMessage"
+
         /**
          * A set of dialogs belonging to AnkiActivity which deal with sync problems
          *
@@ -276,8 +276,8 @@
         fun newInstance(dialogType: Type, dialogMessage: String?): SyncErrorDialog {
             val f = SyncErrorDialog()
             val args = Bundle()
-            args.putInt(SYNC_ERROR_DIALOG_TYPE_KEY, dialogType.code)
-            args.putString(DIALOG_MESSAGE_KEY, dialogMessage)
+            args.putInt(ARG_SYNC_ERROR_DIALOG_TYPE_KEY, dialogType.code)
+            args.putString(ARG_DIALOG_MESSAGE_KEY, dialogMessage)
             f.arguments = args
             return f
         }
@@ -304,15 +304,15 @@
         override fun toMessage(): Message = Message.obtain().apply {
             what = [email protected]
             data = bundleOf(
-                SYNC_ERROR_DIALOG_TYPE_KEY to dialogType,
-                DIALOG_MESSAGE_KEY to dialogMessage
+                ARG_SYNC_ERROR_DIALOG_TYPE_KEY to dialogType,
+                ARG_DIALOG_MESSAGE_KEY to dialogMessage
             )
         }
 
         companion object {
             fun fromMessage(message: Message): SyncErrorDialogMessageHandler {
-                val dialogType = fromCode(message.data.getInt(SYNC_ERROR_DIALOG_TYPE_KEY))
-                val dialogMessage = message.data.getString(DIALOG_MESSAGE_KEY)
+                val dialogType = Type.fromCode(message.data.getInt(ARG_SYNC_ERROR_DIALOG_TYPE_KEY))
+                val dialogMessage = message.data.getString(ARG_DIALOG_MESSAGE_KEY)
                 return SyncErrorDialogMessageHandler(dialogType, dialogMessage)
             }
         }

/**
* Key for an ordinal in the Type.entries.
*/
const val MEDIA_CHECK_DIALOG_TYPE_KEY = "dialogType"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should be private

fun loginToSyncServer()
fun sync(conflict: ConflictResolution? = null)
fun mediaCheck()
fun dismissAllDialogFragments()
fun integrityCheck()
}

/** The type of the sync error dialog*/
private fun type() = fromCode(requireArguments().getInt(SYNC_ERROR_DIALOG_TYPE_KEY))
Copy link
Member

@david-allison david-allison Dec 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personal preference to use a property, take it or leave it

    private val dialogType
        get() = Type.fromCode(requireArguments().getInt(ARG_SYNC_ERROR_DIALOG_TYPE_KEY))

@david-allison david-allison added Needs Author Reply Waiting for a reply from the original author and removed Needs Review labels Dec 4, 2024
Copy link
Member

@david-allison david-allison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

> Task :AnkiDroid:ktlintMainSourceSetCheck FAILED
/home/runner/work/Anki-Android/Anki-Android/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt:264:75 Missing spacing before "}"

Copy link
Member

@mikehardy mikehardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay by me, if David agrees now

@mikehardy mikehardy added Needs Second Approval Has one approval, one more approval to merge and removed Has Conflicts labels Dec 7, 2024
Copy link
Member

@david-allison david-allison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocker: one comment I don't understand

Everything else is nitpicks/implementer's choice

There's a lot of code churn from adding Type. inside the class which defined it, which doesn't seem necessary and is more verbose than it was

val displayFileName = filenameFromPath(convertToDisplayName(packagePath))

return when (type) {
DIALOG_IMPORT_ADD_CONFIRM -> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type. prefix seems like noise

@@ -20,10 +19,14 @@ import com.ichi2.anki.showError
import com.ichi2.anki.utils.ext.dismissAllDialogFragments
import com.ichi2.libanki.MediaCheckResult

/**
* Key for an array of strings of name of invalid media
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand

/**
* Key for an array of strings of name of invalid media
*/
const val INVALID = "invalid"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be public?

return when (requireArguments().getInt("dialogType")) {
DIALOG_CONFIRM_MEDIA_CHECK -> {
return when (typeFromArguments()) {
Type.DIALOG_CONFIRM_MEDIA_CHECK -> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again: Type. seems more verbose than what we had before

res().getString(R.string.app_name)
}
}

private fun typeFromArguments() = Type.fromCode(requireArguments().getInt(MEDIA_CHECK_DIALOG_TYPE_KEY))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

val dialogType get() would read much better

DIALOG_SYNC_CONFLICT_RESOLUTION -> res().getString(R.string.sync_conflict_title_new)
else -> res().getString(R.string.sync_error)
get() = when (type()) {
Type.DIALOG_USER_NOT_LOGGED_IN_SYNC -> res().getString(R.string.not_logged_in_title)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't be a need for the Type prefix

@Arthur-Milchior
Copy link
Member Author

There's a lot of code churn from adding Type. inside the class which defined it, which doesn't seem necessary and is more verbose than it was

I'm confused.
You wrote, above

I prefer Type.fromCode than fromCode, but this is optional

so I added the explicit Type prefix everywhere.

Visibly it's not what you were looking for. Can you clarify where I should have used the Type prefix then?

@david-allison
Copy link
Member

david-allison commented Dec 8, 2024

Here is a patch answering your question

Subject: [PATCH] 
---
Index: AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt	(revision 7016267ddede32c6d0f6ed7f1cf0b3bc5fb458ca)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt	(date 1733617931452)
@@ -20,6 +20,8 @@
 import androidx.annotation.CheckResult
 import androidx.appcompat.app.AlertDialog
 import com.ichi2.anki.R
+import com.ichi2.anki.dialogs.ImportDialog.Type.DIALOG_IMPORT_ADD_CONFIRM
+import com.ichi2.anki.dialogs.ImportDialog.Type.DIALOG_IMPORT_REPLACE_CONFIRM
 import com.ichi2.anki.utils.ext.dismissAllDialogFragments
 import com.ichi2.utils.negativeButton
 import com.ichi2.utils.positiveButton
@@ -47,7 +49,7 @@
         val displayFileName = filenameFromPath(convertToDisplayName(packagePath))
 
         return when (type) {
-            Type.DIALOG_IMPORT_ADD_CONFIRM -> {
+            DIALOG_IMPORT_ADD_CONFIRM -> {
                 dialog.setTitle(R.string.import_title)
                     .setMessage(res().getString(R.string.import_dialog_message_add, displayFileName))
                     .positiveButton(R.string.import_message_add) {
@@ -57,7 +59,7 @@
                     .negativeButton(R.string.dialog_cancel)
                     .create()
             }
-            Type.DIALOG_IMPORT_REPLACE_CONFIRM -> {
+            DIALOG_IMPORT_REPLACE_CONFIRM -> {
                 dialog.setTitle(R.string.import_title)
                     .setMessage(res().getString(R.string.import_message_replace_confirm, displayFileName))
                     .positiveButton(R.string.dialog_positive_replace) {
Index: AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt	(revision 7016267ddede32c6d0f6ed7f1cf0b3bc5fb458ca)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt	(date 1733618185655)
@@ -15,6 +15,8 @@
 import com.ichi2.anki.AnkiActivity
 import com.ichi2.anki.DeckPicker
 import com.ichi2.anki.R
+import com.ichi2.anki.dialogs.MediaCheckDialog.Type.DIALOG_CONFIRM_MEDIA_CHECK
+import com.ichi2.anki.dialogs.MediaCheckDialog.Type.DIALOG_MEDIA_CHECK_RESULTS
 import com.ichi2.anki.showError
 import com.ichi2.anki.utils.ext.dismissAllDialogFragments
 import com.ichi2.libanki.MediaCheckResult
@@ -36,7 +38,7 @@
         val dialog = AlertDialog.Builder(requireContext())
             .setTitle(notificationTitle)
         return when (typeFromArguments()) {
-            Type.DIALOG_CONFIRM_MEDIA_CHECK -> {
+            DIALOG_CONFIRM_MEDIA_CHECK -> {
                 dialog.setMessage(notificationMessage)
                     .setPositiveButton(R.string.dialog_ok) { _, _ ->
                         (activity as MediaCheckDialogListener?)?.mediaCheck()
@@ -47,7 +49,7 @@
                     }
                     .create()
             }
-            Type.DIALOG_MEDIA_CHECK_RESULTS -> {
+            DIALOG_MEDIA_CHECK_RESULTS -> {
                 val noHave = requireArguments().getStringArrayList(NO_HAVE)
                 val unused = requireArguments().getStringArrayList(UNUSED)
                 val invalid = requireArguments().getStringArrayList(INVALID)
@@ -111,19 +113,14 @@
 
     override val notificationMessage: String
         get() = when (typeFromArguments()) {
-            Type.DIALOG_CONFIRM_MEDIA_CHECK -> res().getString(R.string.check_media_warning)
-            Type.DIALOG_MEDIA_CHECK_RESULTS -> res().getString(R.string.check_media_acknowledge)
+            DIALOG_CONFIRM_MEDIA_CHECK -> res().getString(R.string.check_media_warning)
+            DIALOG_MEDIA_CHECK_RESULTS -> res().getString(R.string.check_media_acknowledge)
         }
 
     override val notificationTitle: String
         get() = when (typeFromArguments()) {
-            Type.DIALOG_CONFIRM_MEDIA_CHECK -> {
-                res().getString(R.string.check_media_title)
-            }
-
-            Type.DIALOG_MEDIA_CHECK_RESULTS -> {
-                res().getString(R.string.app_name)
-            }
+            DIALOG_CONFIRM_MEDIA_CHECK -> res().getString(R.string.check_media_title)
+            DIALOG_MEDIA_CHECK_RESULTS -> res().getString(R.string.app_name)
         }
 
     private fun typeFromArguments() = Type.fromCode(requireArguments().getInt(MEDIA_CHECK_DIALOG_TYPE_KEY))
@@ -197,7 +194,7 @@
         override fun handleAsyncMessage(activity: AnkiActivity) {
             // Media check results
             when (dialogType) {
-                Type.DIALOG_MEDIA_CHECK_RESULTS -> {
+                DIALOG_MEDIA_CHECK_RESULTS -> {
                     // we may be called via any AnkiActivity but media check is a DeckPicker thing
                     if (activity !is DeckPicker) {
                         showError(
@@ -211,7 +208,7 @@
                     val checkList = MediaCheckResult(noHave ?: arrayListOf(), unused ?: arrayListOf(), invalid ?: arrayListOf())
                     activity.showMediaCheckDialog(dialogType, checkList)
                 }
-                Type.DIALOG_CONFIRM_MEDIA_CHECK -> { }
+                DIALOG_CONFIRM_MEDIA_CHECK -> { }
             }
         }
 
Index: AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt	(revision 7016267ddede32c6d0f6ed7f1cf0b3bc5fb458ca)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt	(date 1733618150177)
@@ -27,6 +27,17 @@
 import com.ichi2.anki.ConflictResolution
 import com.ichi2.anki.DeckPicker
 import com.ichi2.anki.R
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_CONNECTION_ERROR
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_MEDIA_SYNC_ERROR
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_BASIC_CHECK_ERROR
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_CONFLICT_RESOLUTION
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_CORRUPT_COLLECTION
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_SANITY_ERROR
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_USER_NOT_LOGGED_IN_SYNC
 import com.ichi2.anki.joinSyncMessages
 import com.ichi2.anki.showError
 import com.ichi2.anki.utils.ext.dismissAllDialogFragments
@@ -52,7 +63,7 @@
             .setTitle(title)
             .setMessage(message)
         return when (type()) {
-            Type.DIALOG_USER_NOT_LOGGED_IN_SYNC -> {
+            DIALOG_USER_NOT_LOGGED_IN_SYNC -> {
                 // User not logged in; take them to login screen
                 dialog.setIcon(R.drawable.ic_sync_problem)
                     .setPositiveButton(R.string.log_in) { _, _ ->
@@ -61,7 +72,7 @@
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_CONNECTION_ERROR -> {
+            DIALOG_CONNECTION_ERROR -> {
                 // Connection error; allow user to retry or cancel
                 dialog.setIcon(R.drawable.ic_sync_problem)
                     .setPositiveButton(R.string.retry) { _, _ ->
@@ -72,21 +83,21 @@
                     }
                     .create()
             }
-            Type.DIALOG_SYNC_CONFLICT_RESOLUTION -> {
+            DIALOG_SYNC_CONFLICT_RESOLUTION -> {
                 // Sync conflict; allow user to cancel, or choose between local and remote versions
                 dialog.setIcon(R.drawable.ic_sync_problem)
                     .setPositiveButton(R.string.sync_conflict_keep_local_new) { _, _ ->
-                        requireSyncErrorDialogListener().showSyncErrorDialog(Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL)
+                        requireSyncErrorDialogListener().showSyncErrorDialog(DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL)
                     }
                     .setNegativeButton(R.string.sync_conflict_keep_remote_new) { _, _ ->
-                        requireSyncErrorDialogListener().showSyncErrorDialog(Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE)
+                        requireSyncErrorDialogListener().showSyncErrorDialog(DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE)
                     }
                     .setNeutralButton(R.string.dialog_cancel) { _, _ ->
                         activity?.dismissAllDialogFragments()
                     }
                     .create()
             }
-            Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL -> {
+            DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL -> {
                 // Confirmation before pushing local collection to server after sync conflict
                 dialog.setIcon(R.drawable.ic_sync_problem)
                     .setPositiveButton(R.string.dialog_positive_replace) { _, _ ->
@@ -95,7 +106,7 @@
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE -> {
+            DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE -> {
                 // Confirmation before overwriting local collection with server collection after sync conflict
                 dialog.setIcon(R.drawable.ic_sync_problem)
                     .setPositiveButton(R.string.dialog_positive_replace) { _, _ ->
@@ -104,18 +115,18 @@
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_SYNC_SANITY_ERROR -> {
+            DIALOG_SYNC_SANITY_ERROR -> {
                 // Sync sanity check error; allow user to cancel, or choose between local and remote versions
                 dialog.setPositiveButton(R.string.sync_sanity_local) { _, _ ->
-                    requireSyncErrorDialogListener().showSyncErrorDialog(Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL)
+                    requireSyncErrorDialogListener().showSyncErrorDialog(DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL)
                 }
                     .setNeutralButton(R.string.sync_sanity_remote) { _, _ ->
-                        requireSyncErrorDialogListener().showSyncErrorDialog(Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE)
+                        requireSyncErrorDialogListener().showSyncErrorDialog(DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE)
                     }
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL -> {
+            DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL -> {
                 // Confirmation before pushing local collection to server after sanity check error
                 dialog.setPositiveButton(R.string.dialog_positive_replace) { _, _ ->
                     syncAndDismissAllDialogFragments(ConflictResolution.FULL_UPLOAD)
@@ -123,7 +134,7 @@
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE -> {
+            DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE -> {
                 // Confirmation before overwriting local collection with server collection after sanity check error
                 dialog.setPositiveButton(R.string.dialog_positive_replace) { _, _ ->
                     syncAndDismissAllDialogFragments(ConflictResolution.FULL_DOWNLOAD)
@@ -131,7 +142,7 @@
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_MEDIA_SYNC_ERROR -> {
+            DIALOG_MEDIA_SYNC_ERROR -> {
                 dialog.setPositiveButton(R.string.check_media) { _, _ ->
                     requireSyncErrorDialogListener().mediaCheck()
                     activity?.dismissAllDialogFragments()
@@ -139,7 +150,7 @@
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_SYNC_CORRUPT_COLLECTION -> {
+            DIALOG_SYNC_CORRUPT_COLLECTION -> {
                 dialog.setPositiveButton(R.string.dialog_ok) { _, _ -> }
                     .setNegativeButton(R.string.help) { _, _ ->
                         (requireActivity() as AnkiActivity).openUrl(Uri.parse(getString(R.string.repair_deck)))
@@ -147,7 +158,7 @@
                     .setCancelable(false)
                     .create()
             }
-            Type.DIALOG_SYNC_BASIC_CHECK_ERROR -> {
+            DIALOG_SYNC_BASIC_CHECK_ERROR -> {
                 dialog.setPositiveButton(R.string.check_db) { _, _ ->
                     requireSyncErrorDialogListener().integrityCheck()
                     activity?.dismissAllDialogFragments()
@@ -160,16 +171,16 @@
 
     private val title: String
         get() = when (type()) {
-            Type.DIALOG_USER_NOT_LOGGED_IN_SYNC -> res().getString(R.string.not_logged_in_title)
-            Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL, Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE -> res().getString(R.string.sync_conflict_replace_title)
-            Type.DIALOG_SYNC_CONFLICT_RESOLUTION -> res().getString(R.string.sync_conflict_title_new)
-            Type.DIALOG_CONNECTION_ERROR,
-            Type.DIALOG_SYNC_SANITY_ERROR,
-            Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL,
-            Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE,
-            Type.DIALOG_MEDIA_SYNC_ERROR,
-            Type.DIALOG_SYNC_CORRUPT_COLLECTION,
-            Type.DIALOG_SYNC_BASIC_CHECK_ERROR -> res().getString(R.string.sync_error)
+            DIALOG_USER_NOT_LOGGED_IN_SYNC -> res().getString(R.string.not_logged_in_title)
+            DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL, DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE -> res().getString(R.string.sync_conflict_replace_title)
+            DIALOG_SYNC_CONFLICT_RESOLUTION -> res().getString(R.string.sync_conflict_title_new)
+            DIALOG_CONNECTION_ERROR,
+            DIALOG_SYNC_SANITY_ERROR,
+            DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL,
+            DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE,
+            DIALOG_MEDIA_SYNC_ERROR,
+            DIALOG_SYNC_CORRUPT_COLLECTION,
+            DIALOG_SYNC_BASIC_CHECK_ERROR -> res().getString(R.string.sync_error)
         }
 
     /**
@@ -179,7 +190,7 @@
      */
     override val notificationTitle: String
         get() {
-            return if (type() == Type.DIALOG_USER_NOT_LOGGED_IN_SYNC) {
+            return if (type() == DIALOG_USER_NOT_LOGGED_IN_SYNC) {
                 res().getString(R.string.sync_error)
             } else {
                 title
@@ -188,12 +199,12 @@
 
     private val message: String?
         get() = when (type()) {
-            Type.DIALOG_USER_NOT_LOGGED_IN_SYNC -> res().getString(R.string.login_create_account_message)
-            Type.DIALOG_CONNECTION_ERROR -> res().getString(R.string.connection_error_message)
-            Type.DIALOG_SYNC_CONFLICT_RESOLUTION -> res().getString(R.string.sync_conflict_message_new)
-            Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL, Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL -> res().getString(R.string.sync_conflict_local_confirm_new)
-            Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE, Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE -> res().getString(R.string.sync_conflict_remote_confirm_new)
-            Type.DIALOG_SYNC_CORRUPT_COLLECTION -> {
+            DIALOG_USER_NOT_LOGGED_IN_SYNC -> res().getString(R.string.login_create_account_message)
+            DIALOG_CONNECTION_ERROR -> res().getString(R.string.connection_error_message)
+            DIALOG_SYNC_CONFLICT_RESOLUTION -> res().getString(R.string.sync_conflict_message_new)
+            DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL, DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL -> res().getString(R.string.sync_conflict_local_confirm_new)
+            DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE, DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE -> res().getString(R.string.sync_conflict_remote_confirm_new)
+            DIALOG_SYNC_CORRUPT_COLLECTION -> {
                 val syncMessage = requireArguments().getString(DIALOG_MESSAGE_KEY)
                 val repairUrl = res().getString(R.string.repair_deck)
                 val dialogMessage = res().getString(R.string.sync_corrupt_database, repairUrl)
@@ -209,7 +220,7 @@
      */
     override val notificationMessage: String?
         get() {
-            return if (type() == Type.DIALOG_USER_NOT_LOGGED_IN_SYNC) {
+            return if (type() == DIALOG_USER_NOT_LOGGED_IN_SYNC) {
                 res().getString(R.string.not_logged_in_title)
             } else {
                 message

Here is a patch containing all suggested changes (except INVALID)

Subject: [PATCH] 
---
Index: AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt	(revision 7016267ddede32c6d0f6ed7f1cf0b3bc5fb458ca)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/ImportDialog.kt	(date 1733619016416)
@@ -19,7 +19,10 @@
 import android.os.Bundle
 import androidx.annotation.CheckResult
 import androidx.appcompat.app.AlertDialog
+import androidx.core.os.bundleOf
 import com.ichi2.anki.R
+import com.ichi2.anki.dialogs.ImportDialog.Type.DIALOG_IMPORT_ADD_CONFIRM
+import com.ichi2.anki.dialogs.ImportDialog.Type.DIALOG_IMPORT_REPLACE_CONFIRM
 import com.ichi2.anki.utils.ext.dismissAllDialogFragments
 import com.ichi2.utils.negativeButton
 import com.ichi2.utils.positiveButton
@@ -27,27 +30,25 @@
 import java.net.URLDecoder
 
 class ImportDialog : AsyncDialogFragment() {
-    enum class Type(val code: Int) {
-        DIALOG_IMPORT_ADD_CONFIRM(0), DIALOG_IMPORT_REPLACE_CONFIRM(1);
-        companion object {
-            fun fromCode(code: Int) = Type.entries.first { code == it.code }
-        }
-    }
     interface ImportDialogListener {
         fun importAdd(importPath: String)
         fun importReplace(importPath: String)
     }
 
+    private val dialogType: Type
+        get() = Type.fromCode(requireArguments().getInt(IMPORT_DIALOG_TYPE_KEY))
+
+    private val packagePath: String
+        get() = requireArguments().getString(IMPORT_DIALOG_PACKAGE_PATH_KEY)!!
+
     override fun onCreateDialog(savedInstanceState: Bundle?): AlertDialog {
         super.onCreate(savedInstanceState)
-        val type = Type.fromCode(requireArguments().getInt(IMPORT_DIALOG_TYPE_KEY))
         val dialog = AlertDialog.Builder(requireActivity())
         dialog.setCancelable(true)
-        val packagePath = requireArguments().getString(IMPORT_DIALOG_PACKAGE_PATH_KEY)!!
         val displayFileName = filenameFromPath(convertToDisplayName(packagePath))
 
-        return when (type) {
-            Type.DIALOG_IMPORT_ADD_CONFIRM -> {
+        return when (dialogType) {
+            DIALOG_IMPORT_ADD_CONFIRM -> {
                 dialog.setTitle(R.string.import_title)
                     .setMessage(res().getString(R.string.import_dialog_message_add, displayFileName))
                     .positiveButton(R.string.import_message_add) {
@@ -57,7 +58,7 @@
                     .negativeButton(R.string.dialog_cancel)
                     .create()
             }
-            Type.DIALOG_IMPORT_REPLACE_CONFIRM -> {
+            DIALOG_IMPORT_REPLACE_CONFIRM -> {
                 dialog.setTitle(R.string.import_title)
                     .setMessage(res().getString(R.string.import_message_replace_confirm, displayFileName))
                     .positiveButton(R.string.dialog_positive_replace) {
@@ -91,6 +92,14 @@
             return res().getString(R.string.import_title)
         }
 
+
+    enum class Type(val code: Int) {
+        DIALOG_IMPORT_ADD_CONFIRM(0), DIALOG_IMPORT_REPLACE_CONFIRM(1);
+        companion object {
+            fun fromCode(code: Int) = Type.entries.first { code == it.code }
+        }
+    }
+
     companion object {
         const val IMPORT_DIALOG_TYPE_KEY = "dialogType"
         const val IMPORT_DIALOG_PACKAGE_PATH_KEY = "packagePath"
@@ -102,14 +111,13 @@
          * @param packagePath the path of the package to import
          */
         @CheckResult
-        fun newInstance(dialogType: Type, packagePath: String): ImportDialog {
-            val f = ImportDialog()
-            val args = Bundle()
-            args.putInt(IMPORT_DIALOG_TYPE_KEY, dialogType.code)
-            args.putString(IMPORT_DIALOG_PACKAGE_PATH_KEY, packagePath)
-            f.arguments = args
-            return f
-        }
+        fun newInstance(dialogType: Type, packagePath: String): ImportDialog =
+            ImportDialog().apply {
+                arguments = bundleOf(
+                    IMPORT_DIALOG_TYPE_KEY to dialogType.code,
+                    IMPORT_DIALOG_PACKAGE_PATH_KEY to packagePath
+                )
+            }
 
         private fun filenameFromPath(path: String): String {
             return path.split("/").toTypedArray()[path.split("/").toTypedArray().size - 1]
Index: AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt	(revision 7016267ddede32c6d0f6ed7f1cf0b3bc5fb458ca)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/MediaCheckDialog.kt	(date 1733618819677)
@@ -15,14 +15,12 @@
 import com.ichi2.anki.AnkiActivity
 import com.ichi2.anki.DeckPicker
 import com.ichi2.anki.R
+import com.ichi2.anki.dialogs.MediaCheckDialog.Type.DIALOG_CONFIRM_MEDIA_CHECK
+import com.ichi2.anki.dialogs.MediaCheckDialog.Type.DIALOG_MEDIA_CHECK_RESULTS
 import com.ichi2.anki.showError
 import com.ichi2.anki.utils.ext.dismissAllDialogFragments
 import com.ichi2.libanki.MediaCheckResult
 
-/**
- * Key for an array of strings of name of invalid media
- */
-const val INVALID = "invalid"
 class MediaCheckDialog : AsyncDialogFragment() {
     interface MediaCheckDialogListener {
         fun showMediaCheckDialog(dialogType: Type)
@@ -31,12 +29,24 @@
         fun deleteUnused(unused: List<String>)
     }
 
+    private val dialogType: Type
+        get() = Type.fromCode(requireArguments().getInt(MEDIA_CHECK_DIALOG_TYPE_KEY))
+
+    private val noHave: List<String>?
+        get() = requireArguments().getStringArrayList(NO_HAVE)
+
+    private val unused: List<String>?
+        get() = requireArguments().getStringArrayList(UNUSED)
+
+    private val invalid: List<String>?
+        get() = requireArguments().getStringArrayList(INVALID)
+
     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
         super.onCreate(savedInstanceState)
         val dialog = AlertDialog.Builder(requireContext())
             .setTitle(notificationTitle)
-        return when (typeFromArguments()) {
-            Type.DIALOG_CONFIRM_MEDIA_CHECK -> {
+        return when (dialogType) {
+            DIALOG_CONFIRM_MEDIA_CHECK -> {
                 dialog.setMessage(notificationMessage)
                     .setPositiveButton(R.string.dialog_ok) { _, _ ->
                         (activity as MediaCheckDialogListener?)?.mediaCheck()
@@ -47,22 +57,22 @@
                     }
                     .create()
             }
-            Type.DIALOG_MEDIA_CHECK_RESULTS -> {
-                val noHave = requireArguments().getStringArrayList(NO_HAVE)
-                val unused = requireArguments().getStringArrayList(UNUSED)
-                val invalid = requireArguments().getStringArrayList(INVALID)
+            DIALOG_MEDIA_CHECK_RESULTS -> {
+                val noHave = noHave!!
+                val unused = unused!!
+                val invalid = invalid!!
                 // Generate report
                 val report = StringBuilder()
-                if (invalid!!.isNotEmpty()) {
+                if (invalid.isNotEmpty()) {
                     report.append(String.format(res().getString(R.string.check_media_invalid), invalid.size))
                 }
-                if (unused!!.isNotEmpty()) {
+                if (unused.isNotEmpty()) {
                     if (report.isNotEmpty()) {
                         report.append("\n")
                     }
                     report.append(String.format(res().getString(R.string.check_media_unused), unused.size))
                 }
-                if (noHave!!.isNotEmpty()) {
+                if (noHave.isNotEmpty()) {
                     if (report.isNotEmpty()) {
                         report.append("\n")
                     }
@@ -110,31 +120,19 @@
     }
 
     override val notificationMessage: String
-        get() = when (typeFromArguments()) {
-            Type.DIALOG_CONFIRM_MEDIA_CHECK -> res().getString(R.string.check_media_warning)
-            Type.DIALOG_MEDIA_CHECK_RESULTS -> res().getString(R.string.check_media_acknowledge)
+        get() = when (dialogType) {
+            DIALOG_CONFIRM_MEDIA_CHECK -> res().getString(R.string.check_media_warning)
+            DIALOG_MEDIA_CHECK_RESULTS -> res().getString(R.string.check_media_acknowledge)
         }
 
     override val notificationTitle: String
-        get() = when (typeFromArguments()) {
-            Type.DIALOG_CONFIRM_MEDIA_CHECK -> {
-                res().getString(R.string.check_media_title)
-            }
-
-            Type.DIALOG_MEDIA_CHECK_RESULTS -> {
-                res().getString(R.string.app_name)
-            }
+        get() = when (dialogType) {
+            DIALOG_CONFIRM_MEDIA_CHECK -> res().getString(R.string.check_media_title)
+            DIALOG_MEDIA_CHECK_RESULTS -> res().getString(R.string.app_name)
         }
-
-    private fun typeFromArguments() = Type.fromCode(requireArguments().getInt(MEDIA_CHECK_DIALOG_TYPE_KEY))
 
     override val dialogHandlerMessage: MediaCheckCompleteDialog
         get() {
-            val dialogType = typeFromArguments()
-            val noHave = requireArguments().getStringArrayList(NO_HAVE)
-            val unused = requireArguments().getStringArrayList(UNUSED)
-            val invalid = requireArguments().getStringArrayList(INVALID)
-
             return MediaCheckCompleteDialog(dialogType, noHave, unused, invalid)
         }
 
@@ -164,40 +162,38 @@
          */
         const val UNUSED = "unused"
 
+        /**
+         * Key for an array of strings of name of invalid media
+         */
+        const val INVALID = "invalid"
+
         @CheckResult
-        fun newInstance(dialogType: Type): MediaCheckDialog {
-            val f = MediaCheckDialog()
-            val args = Bundle()
-            args.putInt(MEDIA_CHECK_DIALOG_TYPE_KEY, dialogType.code)
-            f.arguments = args
-            return f
+        fun newInstance(dialogType: Type) = MediaCheckDialog().apply { 
+            arguments = bundleOf(MEDIA_CHECK_DIALOG_TYPE_KEY to dialogType.code)    
         }
 
         // TODO Instead of putting string arrays into the bundle,
-        //   make MediaCheckResult parcelable with @Parcelize and put it instead.
-        // TODO Extract keys to constants
-        fun newInstance(dialogType: Type, checkList: MediaCheckResult): MediaCheckDialog {
-            val f = MediaCheckDialog()
-            val args = Bundle()
-            args.putStringArrayList(NO_HAVE, ArrayList(checkList.missingFileNames))
-            args.putStringArrayList(UNUSED, ArrayList(checkList.unusedFileNames))
-            args.putStringArrayList(INVALID, ArrayList(checkList.invalidFileNames))
-            args.putInt(MEDIA_CHECK_DIALOG_TYPE_KEY, dialogType.code)
-            f.arguments = args
-            return f
+        //   make MediaCheckResult parcelable with @Parcelize and put it instead
+        fun newInstance(dialogType: Type, checkList: MediaCheckResult) = MediaCheckDialog().apply { 
+            arguments = bundleOf(
+                NO_HAVE to ArrayList(checkList.missingFileNames),
+                UNUSED to ArrayList(checkList.unusedFileNames),
+                INVALID to ArrayList(checkList.invalidFileNames),
+                MEDIA_CHECK_DIALOG_TYPE_KEY to dialogType.code,
+            )
         }
     }
 
     class MediaCheckCompleteDialog(
         private val dialogType: Type,
-        private val noHave: ArrayList<String>?,
-        private val unused: ArrayList<String>?,
-        private val invalid: ArrayList<String>?
+        private val noHave: List<String>?,
+        private val unused: List<String>?,
+        private val invalid: List<String>?
     ) : DialogHandlerMessage(WhichDialogHandler.MSG_SHOW_MEDIA_CHECK_COMPLETE_DIALOG, "MediaCheckCompleteDialog") {
         override fun handleAsyncMessage(activity: AnkiActivity) {
             // Media check results
             when (dialogType) {
-                Type.DIALOG_MEDIA_CHECK_RESULTS -> {
+                DIALOG_MEDIA_CHECK_RESULTS -> {
                     // we may be called via any AnkiActivity but media check is a DeckPicker thing
                     if (activity !is DeckPicker) {
                         showError(
@@ -211,7 +207,7 @@
                     val checkList = MediaCheckResult(noHave ?: arrayListOf(), unused ?: arrayListOf(), invalid ?: arrayListOf())
                     activity.showMediaCheckDialog(dialogType, checkList)
                 }
-                Type.DIALOG_CONFIRM_MEDIA_CHECK -> { }
+                DIALOG_CONFIRM_MEDIA_CHECK -> { }
             }
         }
 
Index: AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt	(revision 7016267ddede32c6d0f6ed7f1cf0b3bc5fb458ca)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/SyncErrorDialog.kt	(date 1733618952128)
@@ -27,6 +27,17 @@
 import com.ichi2.anki.ConflictResolution
 import com.ichi2.anki.DeckPicker
 import com.ichi2.anki.R
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_CONNECTION_ERROR
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_MEDIA_SYNC_ERROR
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_BASIC_CHECK_ERROR
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_CONFLICT_RESOLUTION
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_CORRUPT_COLLECTION
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_SANITY_ERROR
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE
+import com.ichi2.anki.dialogs.SyncErrorDialog.Type.DIALOG_USER_NOT_LOGGED_IN_SYNC
 import com.ichi2.anki.joinSyncMessages
 import com.ichi2.anki.showError
 import com.ichi2.anki.utils.ext.dismissAllDialogFragments
@@ -44,15 +55,16 @@
     fun requireSyncErrorDialogListener() = activity as SyncErrorDialogListener
 
     /** The type of the sync error dialog*/
-    private fun type() = Type.fromCode(requireArguments().getInt(SYNC_ERROR_DIALOG_TYPE_KEY))
+    private val dialogType: Type
+        get() = Type.fromCode(requireArguments().getInt(SYNC_ERROR_DIALOG_TYPE_KEY))
 
     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
         super.onCreate(savedInstanceState)
         val dialog = AlertDialog.Builder(requireContext())
             .setTitle(title)
             .setMessage(message)
-        return when (type()) {
-            Type.DIALOG_USER_NOT_LOGGED_IN_SYNC -> {
+        return when (dialogType) {
+            DIALOG_USER_NOT_LOGGED_IN_SYNC -> {
                 // User not logged in; take them to login screen
                 dialog.setIcon(R.drawable.ic_sync_problem)
                     .setPositiveButton(R.string.log_in) { _, _ ->
@@ -61,7 +73,7 @@
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_CONNECTION_ERROR -> {
+            DIALOG_CONNECTION_ERROR -> {
                 // Connection error; allow user to retry or cancel
                 dialog.setIcon(R.drawable.ic_sync_problem)
                     .setPositiveButton(R.string.retry) { _, _ ->
@@ -72,21 +84,21 @@
                     }
                     .create()
             }
-            Type.DIALOG_SYNC_CONFLICT_RESOLUTION -> {
+            DIALOG_SYNC_CONFLICT_RESOLUTION -> {
                 // Sync conflict; allow user to cancel, or choose between local and remote versions
                 dialog.setIcon(R.drawable.ic_sync_problem)
                     .setPositiveButton(R.string.sync_conflict_keep_local_new) { _, _ ->
-                        requireSyncErrorDialogListener().showSyncErrorDialog(Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL)
+                        requireSyncErrorDialogListener().showSyncErrorDialog(DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL)
                     }
                     .setNegativeButton(R.string.sync_conflict_keep_remote_new) { _, _ ->
-                        requireSyncErrorDialogListener().showSyncErrorDialog(Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE)
+                        requireSyncErrorDialogListener().showSyncErrorDialog(DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE)
                     }
                     .setNeutralButton(R.string.dialog_cancel) { _, _ ->
                         activity?.dismissAllDialogFragments()
                     }
                     .create()
             }
-            Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL -> {
+            DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL -> {
                 // Confirmation before pushing local collection to server after sync conflict
                 dialog.setIcon(R.drawable.ic_sync_problem)
                     .setPositiveButton(R.string.dialog_positive_replace) { _, _ ->
@@ -95,7 +107,7 @@
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE -> {
+            DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE -> {
                 // Confirmation before overwriting local collection with server collection after sync conflict
                 dialog.setIcon(R.drawable.ic_sync_problem)
                     .setPositiveButton(R.string.dialog_positive_replace) { _, _ ->
@@ -104,18 +116,18 @@
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_SYNC_SANITY_ERROR -> {
+            DIALOG_SYNC_SANITY_ERROR -> {
                 // Sync sanity check error; allow user to cancel, or choose between local and remote versions
                 dialog.setPositiveButton(R.string.sync_sanity_local) { _, _ ->
-                    requireSyncErrorDialogListener().showSyncErrorDialog(Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL)
+                    requireSyncErrorDialogListener().showSyncErrorDialog(DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL)
                 }
                     .setNeutralButton(R.string.sync_sanity_remote) { _, _ ->
-                        requireSyncErrorDialogListener().showSyncErrorDialog(Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE)
+                        requireSyncErrorDialogListener().showSyncErrorDialog(DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE)
                     }
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL -> {
+            DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL -> {
                 // Confirmation before pushing local collection to server after sanity check error
                 dialog.setPositiveButton(R.string.dialog_positive_replace) { _, _ ->
                     syncAndDismissAllDialogFragments(ConflictResolution.FULL_UPLOAD)
@@ -123,7 +135,7 @@
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE -> {
+            DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE -> {
                 // Confirmation before overwriting local collection with server collection after sanity check error
                 dialog.setPositiveButton(R.string.dialog_positive_replace) { _, _ ->
                     syncAndDismissAllDialogFragments(ConflictResolution.FULL_DOWNLOAD)
@@ -131,7 +143,7 @@
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_MEDIA_SYNC_ERROR -> {
+            DIALOG_MEDIA_SYNC_ERROR -> {
                 dialog.setPositiveButton(R.string.check_media) { _, _ ->
                     requireSyncErrorDialogListener().mediaCheck()
                     activity?.dismissAllDialogFragments()
@@ -139,7 +151,7 @@
                     .setNegativeButton(R.string.dialog_cancel) { _, _ -> }
                     .create()
             }
-            Type.DIALOG_SYNC_CORRUPT_COLLECTION -> {
+            DIALOG_SYNC_CORRUPT_COLLECTION -> {
                 dialog.setPositiveButton(R.string.dialog_ok) { _, _ -> }
                     .setNegativeButton(R.string.help) { _, _ ->
                         (requireActivity() as AnkiActivity).openUrl(Uri.parse(getString(R.string.repair_deck)))
@@ -147,7 +159,7 @@
                     .setCancelable(false)
                     .create()
             }
-            Type.DIALOG_SYNC_BASIC_CHECK_ERROR -> {
+            DIALOG_SYNC_BASIC_CHECK_ERROR -> {
                 dialog.setPositiveButton(R.string.check_db) { _, _ ->
                     requireSyncErrorDialogListener().integrityCheck()
                     activity?.dismissAllDialogFragments()
@@ -159,17 +171,17 @@
     }
 
     private val title: String
-        get() = when (type()) {
-            Type.DIALOG_USER_NOT_LOGGED_IN_SYNC -> res().getString(R.string.not_logged_in_title)
-            Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL, Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE -> res().getString(R.string.sync_conflict_replace_title)
-            Type.DIALOG_SYNC_CONFLICT_RESOLUTION -> res().getString(R.string.sync_conflict_title_new)
-            Type.DIALOG_CONNECTION_ERROR,
-            Type.DIALOG_SYNC_SANITY_ERROR,
-            Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL,
-            Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE,
-            Type.DIALOG_MEDIA_SYNC_ERROR,
-            Type.DIALOG_SYNC_CORRUPT_COLLECTION,
-            Type.DIALOG_SYNC_BASIC_CHECK_ERROR -> res().getString(R.string.sync_error)
+        get() = when (dialogType) {
+            DIALOG_USER_NOT_LOGGED_IN_SYNC -> res().getString(R.string.not_logged_in_title)
+            DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL, DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE -> res().getString(R.string.sync_conflict_replace_title)
+            DIALOG_SYNC_CONFLICT_RESOLUTION -> res().getString(R.string.sync_conflict_title_new)
+            DIALOG_CONNECTION_ERROR,
+            DIALOG_SYNC_SANITY_ERROR,
+            DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL,
+            DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE,
+            DIALOG_MEDIA_SYNC_ERROR,
+            DIALOG_SYNC_CORRUPT_COLLECTION,
+            DIALOG_SYNC_BASIC_CHECK_ERROR -> res().getString(R.string.sync_error)
         }
 
     /**
@@ -179,7 +191,7 @@
      */
     override val notificationTitle: String
         get() {
-            return if (type() == Type.DIALOG_USER_NOT_LOGGED_IN_SYNC) {
+            return if (dialogType == DIALOG_USER_NOT_LOGGED_IN_SYNC) {
                 res().getString(R.string.sync_error)
             } else {
                 title
@@ -187,13 +199,13 @@
         }
 
     private val message: String?
-        get() = when (type()) {
-            Type.DIALOG_USER_NOT_LOGGED_IN_SYNC -> res().getString(R.string.login_create_account_message)
-            Type.DIALOG_CONNECTION_ERROR -> res().getString(R.string.connection_error_message)
-            Type.DIALOG_SYNC_CONFLICT_RESOLUTION -> res().getString(R.string.sync_conflict_message_new)
-            Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL, Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL -> res().getString(R.string.sync_conflict_local_confirm_new)
-            Type.DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE, Type.DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE -> res().getString(R.string.sync_conflict_remote_confirm_new)
-            Type.DIALOG_SYNC_CORRUPT_COLLECTION -> {
+        get() = when (dialogType) {
+            DIALOG_USER_NOT_LOGGED_IN_SYNC -> res().getString(R.string.login_create_account_message)
+            DIALOG_CONNECTION_ERROR -> res().getString(R.string.connection_error_message)
+            DIALOG_SYNC_CONFLICT_RESOLUTION -> res().getString(R.string.sync_conflict_message_new)
+            DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_LOCAL, DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_LOCAL -> res().getString(R.string.sync_conflict_local_confirm_new)
+            DIALOG_SYNC_CONFLICT_CONFIRM_KEEP_REMOTE, DIALOG_SYNC_SANITY_ERROR_CONFIRM_KEEP_REMOTE -> res().getString(R.string.sync_conflict_remote_confirm_new)
+            DIALOG_SYNC_CORRUPT_COLLECTION -> {
                 val syncMessage = requireArguments().getString(DIALOG_MESSAGE_KEY)
                 val repairUrl = res().getString(R.string.repair_deck)
                 val dialogMessage = res().getString(R.string.sync_corrupt_database, repairUrl)
@@ -209,7 +221,7 @@
      */
     override val notificationMessage: String?
         get() {
-            return if (type() == Type.DIALOG_USER_NOT_LOGGED_IN_SYNC) {
+            return if (dialogType == DIALOG_USER_NOT_LOGGED_IN_SYNC) {
                 res().getString(R.string.not_logged_in_title)
             } else {
                 message
@@ -218,7 +230,6 @@
 
     override val dialogHandlerMessage: SyncErrorDialogMessageHandler
         get() {
-            val dialogType = type()
             val dialogMessage = requireArguments().getString(DIALOG_MESSAGE_KEY)
             return SyncErrorDialogMessageHandler(dialogType, dialogMessage)
         }
@@ -268,13 +279,11 @@
          * @param dialogMessage A string which can be optionally used to set the dialog message
          */
         @CheckResult
-        fun newInstance(dialogType: Type, dialogMessage: String?): SyncErrorDialog {
-            val f = SyncErrorDialog()
-            val args = Bundle()
-            args.putInt(SYNC_ERROR_DIALOG_TYPE_KEY, dialogType.code)
-            args.putString(DIALOG_MESSAGE_KEY, dialogMessage)
-            f.arguments = args
-            return f
+        fun newInstance(dialogType: Type, dialogMessage: String?) = SyncErrorDialog().apply {
+            arguments = bundleOf(
+                SYNC_ERROR_DIALOG_TYPE_KEY to dialogType.code,
+                DIALOG_MESSAGE_KEY to dialogMessage
+            )
         }
     }
 

@lukstbit lukstbit added the Needs Author Reply Waiting for a reply from the original author label Dec 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Has Conflicts Needs Author Reply Waiting for a reply from the original author Needs Second Approval Has one approval, one more approval to merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants