Skip to content

Commit

Permalink
fix: attach custom study dialog factory in SingleFragmentActivity
Browse files Browse the repository at this point in the history
this avoids a lifecycle crash where SingleFragmentActivity may
crash on activity-recreation if it is hosting the CongratsPage which
hosts the CustomStudyDialog, since CustomStudyDialog fragment does
not have a default constructor - it strictly requires its custom
factory to be installed
  • Loading branch information
mikehardy committed Nov 27, 2024
1 parent 0fe5e9b commit b2d34de
Showing 1 changed file with 47 additions and 1 deletion.
48 changes: 47 additions & 1 deletion AnkiDroid/src/main/java/com/ichi2/anki/SingleFragmentActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.KeyEvent
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentContainerView
import androidx.fragment.app.commit
import com.ichi2.anki.android.input.ShortcutGroup
import com.ichi2.anki.android.input.ShortcutGroupProvider
import com.ichi2.anki.dialogs.customstudy.CustomStudyDialog
import com.ichi2.anki.dialogs.customstudy.CustomStudyDialogFactory
import com.ichi2.utils.ExtendedFragmentFactory
import com.ichi2.utils.getInstanceFromClassName
import timber.log.Timber
import kotlin.reflect.KClass
Expand All @@ -38,14 +42,21 @@ import kotlin.reflect.jvm.jvmName
*
* [getIntent] can be used as an easy way to build a [SingleFragmentActivity]
*/
open class SingleFragmentActivity : AnkiActivity() {
open class SingleFragmentActivity : AnkiActivity(), CustomStudyDialog.CustomStudyListener {
/** The displayed fragment. */
lateinit var fragment: Fragment

override fun onCreate(savedInstanceState: Bundle?) {
if (showedActivityFailedScreen(savedInstanceState)) {
return
}

// This page *may* host the CustomStudyDialog (CongratsPage)
// CustomStudyDialog requires a custom factory install during lifecycle or it can
// crash during lifecycle resume after background kill
val customStudyDialogFactory = CustomStudyDialogFactory({ this.getColUnsafe }, this)
customStudyDialogFactory.attachToActivity<ExtendedFragmentFactory>(this)

super.onCreate(savedInstanceState)
if (!ensureStoragePermissions()) {
return
Expand Down Expand Up @@ -101,6 +112,41 @@ open class SingleFragmentActivity : AnkiActivity() {

override val shortcuts: ShortcutGroup?
get() = (fragment as? ShortcutGroupProvider)?.shortcuts

// Begin - implementation of CustomStudyListener methods here for crash fix
// TODO - refactor https://github.com/ankidroid/Anki-Android/pull/17508#pullrequestreview-2465561993
private fun openStudyOptionsAndFinish() {
val intent = Intent(this, StudyOptionsActivity::class.java).apply {
putExtra("withDeckOptions", false)
}
startActivity(intent, null)
this.finish()
}

override fun onExtendStudyLimits() {
Timber.v("CustomStudyListener::hideProgressBar() - not handled")
openStudyOptionsAndFinish()
}

override fun showDialogFragment(newFragment: DialogFragment) {
Timber.v("CustomStudyListener::showDialogFragment()")
newFragment.show(supportFragmentManager, null)
}

override fun startActivity(intent: Intent) {
Timber.v("CustomStudyListener::startActivity() - not handled")
}

override fun onCreateCustomStudySession() {
Timber.v("CustomStudyListener::onCreateCustomStudySession()")
openStudyOptionsAndFinish()
}

override fun hideProgressBar() {
Timber.v("CustomStudyListener::hideProgressBar() - not handled")
}

// END CustomStudyListener temporary implementation - should refactor out
}

interface DispatchKeyEventListener {
Expand Down

0 comments on commit b2d34de

Please sign in to comment.