Skip to content

Commit

Permalink
8602 - Finished fully migrating DeckPicker over to using registerForA…
Browse files Browse the repository at this point in the history
…ctivityResults API instead of the deprecated startActivityForResult (ankidroid#14818)

* - finished fully migrating DeckPicker over to using registerForActivityResult API instead of the deprecated startActivityForResult
-- removed the last remaining request code dependencies in DeckPicker (PICK_APKG_FILE, PICK_CSV_FILE), and replaced with their equivalent ActivityResultLaunchers
-- removed deprecated onActivityResult function from DeckPicker
-- ImportFileSelectionFragment.openImportFilePicker needed a way to grab the ActivityResultLauncher from the activity, so I created 2 interfaces fetch the launcher, one for APKG imports and one for CSV imports.
-- Created ImportFileType enum to signal to ImportFileSelectionFragment.openImportFilePicker which launcher it should look for

* PR Review Updates:

ImportFileSelectionFragment
- changed multiple parameters flag back to false by default
- changed interface names for more concision and clarity
- added error logging if activity can't handle a particular import
- removed aggregate interface, FileImportResultLauncherHolder

DatabaseErrorDialog
- removed redundant type check
- fixed safe cast syntax typo

DeckPicker
- Aggregate interface FileImportResultLauncherHolder was removed, instead implementing ApkgImportResultLauncherProvider and CsvImportResultLauncherProvider separately
  • Loading branch information
nfragiskatos committed Nov 28, 2023
1 parent c315448 commit bb439de
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 29 deletions.
53 changes: 32 additions & 21 deletions AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import android.view.View.OnLongClickListener
import android.widget.*
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.StringRes
import androidx.annotation.VisibleForTesting
Expand Down Expand Up @@ -77,6 +78,8 @@ import com.ichi2.anki.analytics.UsageAnalytics
import com.ichi2.anki.dialogs.*
import com.ichi2.anki.dialogs.DatabaseErrorDialog.DatabaseErrorDialogType
import com.ichi2.anki.dialogs.ImportDialog.ImportDialogListener
import com.ichi2.anki.dialogs.ImportFileSelectionFragment.ApkgImportResultLauncherProvider
import com.ichi2.anki.dialogs.ImportFileSelectionFragment.CsvImportResultLauncherProvider
import com.ichi2.anki.dialogs.MediaCheckDialog.MediaCheckDialogListener
import com.ichi2.anki.dialogs.SyncErrorDialog.Companion.newInstance
import com.ichi2.anki.dialogs.SyncErrorDialog.SyncErrorDialogListener
Expand Down Expand Up @@ -173,7 +176,9 @@ open class DeckPicker :
ChangeManager.Subscriber,
SyncCompletionListener,
ImportColpkgListener,
BaseSnackbarBuilderProvider {
BaseSnackbarBuilderProvider,
ApkgImportResultLauncherProvider,
CsvImportResultLauncherProvider {
// Short animation duration from system
private var mShortAnimDuration = 0
private var mBackButtonPressedToExit = false
Expand Down Expand Up @@ -277,6 +282,24 @@ open class DeckPicker :
}
)

private val apkgFileImportResultLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult(),
DeckPickerActivityResultCallback {
if (it.resultCode == RESULT_OK) {
onSelectedPackageToImport(it.data!!)
}
}
)

private val csvImportResultLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult(),
DeckPickerActivityResultCallback {
if (it.resultCode == RESULT_OK) {
onSelectedCsvForImport(it.data!!)
}
}
)

private inner class DeckPickerActivityResultCallback(private val callback: (result: ActivityResult) -> Unit) : ActivityResultCallback<ActivityResult> {
override fun onActivityResult(result: ActivityResult) {
if (result.resultCode == RESULT_MEDIA_EJECTED) {
Expand Down Expand Up @@ -940,24 +963,6 @@ open class DeckPicker :
)
}

@Deprecated("Deprecated in Java")
@Suppress("deprecation") // onActivityResult
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_MEDIA_EJECTED) {
onSdCardNotMounted()
return
} else if (resultCode == RESULT_DB_ERROR) {
handleDbError()
return
}
if (requestCode == PICK_APKG_FILE && resultCode == RESULT_OK) {
onSelectedPackageToImport(data!!)
} else if (requestCode == PICK_CSV_FILE && resultCode == RESULT_OK) {
onSelectedCsvForImport(data!!)
}
}

private fun processReviewResults(resultCode: Int) {
if (resultCode == AbstractFlashcardViewer.RESULT_NO_MORE_CARDS) {
// Show a message when reviewing has finished
Expand Down Expand Up @@ -2182,8 +2187,6 @@ open class DeckPicker :
*/
@VisibleForTesting
const val REQUEST_STORAGE_PERMISSION = 0
const val PICK_APKG_FILE = 13
const val PICK_CSV_FILE = 14

// For automatic syncing
// 10 minutes in milliseconds..
Expand Down Expand Up @@ -2468,6 +2471,14 @@ open class DeckPicker :
/** The user has completed their studying for today, and there are future reviews */
REGULAR_DECK_NO_MORE_CARDS_TODAY
}

override fun getApkgFileImportResultLauncher(): ActivityResultLauncher<Intent?> {
return apkgFileImportResultLauncher
}

override fun getCsvFileImportResultLauncher(): ActivityResultLauncher<Intent?> {
return csvImportResultLauncher
}
}

/** Android's onCreateOptionsMenu does not play well with coroutines, as
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,9 @@ class DatabaseErrorDialog : AsyncDialogFragment() {

dialog.title(R.string.backup_restore_select_title)
.positiveButton(R.string.restore_backup_choose_another) {
ImportFileSelectionFragment.openImportFilePicker(activity as AnkiActivity, DeckPicker.PICK_APKG_FILE)
(activity as? AnkiActivity)?.let {
ImportFileSelectionFragment.openImportFilePicker(it, ImportFileSelectionFragment.ImportFileType.APKG)
}
}
.negativeButton(R.string.dialog_cancel)
.listItemsSingleChoice(items = dates.toTypedArray().toList(), waitForPositiveButton = false) { _: MaterialDialog, index: Int, _: CharSequence ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package com.ichi2.anki.dialogs

import android.content.Intent
import androidx.activity.result.ActivityResultLauncher
import com.ichi2.anim.ActivityTransitionAnimation
import com.ichi2.anki.AnkiActivity
import com.ichi2.anki.DeckPicker
import com.ichi2.anki.R
Expand All @@ -31,19 +33,31 @@ import timber.log.Timber
class ImportFileSelectionFragment {
data class ImportOptions(val importColpkg: Boolean, val importApkg: Boolean, val importTextFile: Boolean)

enum class ImportFileType {
APKG, COLPKG, CSV
}

interface ApkgImportResultLauncherProvider {
fun getApkgFileImportResultLauncher(): ActivityResultLauncher<Intent?>
}

interface CsvImportResultLauncherProvider {
fun getCsvFileImportResultLauncher(): ActivityResultLauncher<Intent?>
}

companion object {
fun createInstance(@Suppress("UNUSED_PARAMETER") context: DeckPicker, options: ImportOptions): RecursivePictureMenu {
// this needs a deckPicker for now. See use of PICK_APKG_FILE

// This is required for serialization of the lambda
class OpenFilePicker(
val requestCode: Int,
val importFileType: ImportFileType,
var multiple: Boolean = false,
val mimeType: String = "*/*",
val extraMimes: Array<String>? = null
) : FunctionItem.ActivityConsumer {
override fun consume(activity: AnkiActivity) {
openImportFilePicker(activity, requestCode, multiple, mimeType, extraMimes)
openImportFilePicker(activity, importFileType, multiple, mimeType, extraMimes)
}
}

Expand All @@ -53,7 +67,7 @@ class ImportFileSelectionFragment {
R.string.import_deck_package,
R.drawable.ic_manual_black_24dp,
UsageAnalytics.Actions.IMPORT_APKG_FILE,
OpenFilePicker(DeckPicker.PICK_APKG_FILE, false)
OpenFilePicker(ImportFileType.APKG, false)
)
} else {
null
Expand All @@ -63,7 +77,7 @@ class ImportFileSelectionFragment {
R.string.import_collection_package,
R.drawable.ic_manual_black_24dp,
UsageAnalytics.Actions.IMPORT_COLPKG_FILE,
OpenFilePicker(DeckPicker.PICK_APKG_FILE)
OpenFilePicker(ImportFileType.COLPKG)
)
} else {
null
Expand All @@ -74,7 +88,7 @@ class ImportFileSelectionFragment {
R.drawable.ic_baseline_description_24,
UsageAnalytics.Actions.IMPORT_CSV_FILE,
OpenFilePicker(
DeckPicker.PICK_CSV_FILE,
ImportFileType.CSV,
multiple = false,
mimeType = "*/*",
extraMimes = arrayOf("text/plain", "text/comma-separated-values", "text/csv", "text/tab-separated-values")
Expand All @@ -90,7 +104,7 @@ class ImportFileSelectionFragment {
// needs to be static for serialization
fun openImportFilePicker(
activity: AnkiActivity,
requestCode: Int,
fileType: ImportFileType,
multiple: Boolean = false,
mimeType: String = "*/*",
extraMimes: Array<String>? = null
Expand All @@ -104,7 +118,14 @@ class ImportFileSelectionFragment {
intent.putExtra("android.content.extra.SHOW_FILESIZE", true)
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiple)
extraMimes?.let { intent.putExtra(Intent.EXTRA_MIME_TYPES, it) }
activity.startActivityForResultWithoutAnimation(intent, requestCode)
if ((fileType == ImportFileType.APKG || fileType == ImportFileType.COLPKG) && activity is ApkgImportResultLauncherProvider) {
activity.launchActivityForResultWithAnimation(intent, activity.getApkgFileImportResultLauncher(), ActivityTransitionAnimation.Direction.NONE)
} else if (fileType == ImportFileType.CSV && activity is CsvImportResultLauncherProvider) {
activity.launchActivityForResultWithAnimation(intent, activity.getCsvFileImportResultLauncher(), ActivityTransitionAnimation.Direction.NONE)
} else {
Timber.w("Activity($activity) can't handle requested import: $fileType")
}
}
}
}

0 comments on commit bb439de

Please sign in to comment.