Skip to content

Commit

Permalink
fix: Show an error message if a Dao error occurs during login (#1235)
Browse files Browse the repository at this point in the history
Previous code would crash on an SQLiteException. Catch it and convert to
a specific error.
  • Loading branch information
nikclayton authored Jan 25, 2025
1 parent ab95891 commit 353f123
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 0 deletions.
14 changes: 14 additions & 0 deletions app/src/main/java/app/pachli/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,20 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
}
}

// Database errors are not retryable. Display the error, offer to
// switch back to the fall back account.
//
// If these occur it's a bug in Pachli, the database should never
// get to a bad state.
is SetActiveAccountError.Dao -> {
uiError.cause.wantedAccount?.let { builder.setTitle(it.fullName) }
val button = builder.await(android.R.string.ok)
if (button == AlertDialog.BUTTON_POSITIVE && uiError.cause.fallbackAccount != null) {
viewModel.accept(FallibleUiAction.SetActiveAccount(uiError.cause.fallbackAccount!!.id))
}
return
}

// Other errors are retryable.
is SetActiveAccountError.Unexpected -> {
builder.setTitle(uiError.cause.wantedAccount.fullName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package app.pachli.core.data.repository

import android.database.sqlite.SQLiteException
import app.pachli.core.common.PachliError
import app.pachli.core.common.di.ApplicationScope
import app.pachli.core.data.R
Expand Down Expand Up @@ -120,6 +121,23 @@ sealed interface SetActiveAccountError : PachliError {
val apiError: ApiError,
) : SetActiveAccountError, PachliError by apiError

/**
* A DAO exception occurred while logging in.
*
* @param fallbackAccount See [SetActiveAccountError.fallbackAccount]
* @param wantedAccount The account entity that could not be made active
* (if known)
*/
data class Dao(
override val fallbackAccount: AccountEntity?,
val wantedAccount: AccountEntity?,
val sqlException: SQLiteException,
) : SetActiveAccountError {
override val resourceId = R.string.account_manager_error_dao
override val formatArgs: Array<String> = arrayOf(sqlException.localizedMessage ?: "unknown")
override val cause = null
}

/**
* Catch-all for unexpected exceptions when logging in.
*
Expand Down Expand Up @@ -435,6 +453,8 @@ class AccountManager @Inject constructor(
}
} catch (e: ApiErrorException) {
Err(SetActiveAccountError.Api(fallbackAccount, accountEntity!!, e.apiError))
} catch (e: SQLiteException) {
Err(SetActiveAccountError.Dao(fallbackAccount, accountEntity, e))
} catch (e: Throwable) {
currentCoroutineContext().ensureActive()
Err(SetActiveAccountError.Unexpected(fallbackAccount, accountEntity!!, e))
Expand Down
1 change: 1 addition & 0 deletions core/data/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@

<string name="account_manager_error_account_does_not_exist">Account does not exist in local database. This should never happen. If you see this message please send a bug report.</string>
<string name="account_manager_error_no_active_account">no account is marked active</string>
<string name="account_manager_error_dao">Database error, please report this to [email protected]: %1$s</string>
<string name="account_manager_error_unexpected">unexpected error: %1$s</string>
</resources>

0 comments on commit 353f123

Please sign in to comment.