Repository navigation
fix: repair four defects the app hit on a live Firebase project - #23
Merged
Merged
Conversation
Running the app against real Firestore surfaced four problems that no test
covered, because each one lives in the gap between a ViewModel's decision and
what the user actually meets.
**The password toggle showed the inverted icon.** The field used the legacy
`passwordToggleEnabled` attribute, whose default icon reports the *action*
(open eye while hidden, meaning "tap to reveal"). Read as state — which is how
people read it — that is backwards. Both screens now use `endIconMode` with a
`state_checked` selector: crossed-out eye while hidden, open eye while visible.
**Every auth failure collapsed into "Tekrar deneyin."** The mapping matched on
Firebase's English error *sentence* ("password is invalid", "no user record").
Those strings are not API; they changed, and the match silently stopped hitting
— so a wrong password and a dropped connection produced the same useless text.
Mapping now keys on `FirebaseAuthException.errorCode`. `ERROR_INVALID_CREDENTIAL`
is the case that mattered most: with email enumeration protection on, Firebase
returns it for both a wrong password and an unknown account, and nothing
recognised it.
**Leaving the app meant signing in again.** Firebase persists the session to
disk, but the launcher only skipped the form when a "keep me signed in" checkbox
had been ticked — so an untended box left the user signed in yet facing the
login screen at every start. The box is gone; the session now lasts until the
sign-out button in Profile, which is the only place that should end it.
**The leaderboard error followed the user across tabs.** Its retry snackbar
attaches to MainActivity's CoordinatorLayout, not to the fragment, so switching
tabs destroyed the fragment and left the snackbar. Combined with
LENGTH_INDEFINITE it never went away, and it sat over the upload form — the note
could not be submitted at all. The snackbar is now held and dismissed in
`onStop` and whenever a load succeeds. ProfileFragment carried the identical
defect and is fixed the same way.
Tests: 114 -> 129. `AuthErrorMessagesTest` pins each error code to its own
message; `PasswordToggleTest` inflates both screens under Robolectric and
asserts the icon reports state, since dropping `endIconDrawable` would leave a
working button with the wrong icon and break nothing else.
Not a code change, but worth recording: both composite indexes in
firestore.indexes.json were missing from the live project. The feed only looked
healthy because the contribution gate meant its query was never built; the first
upload unlocked the gate and it failed too. Deploying step 6 of the README's
Getting started is not optional.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Running the app against real Firestore surfaced four problems that no test covered, because each lives in the gap between a ViewModel's decision and what the user actually meets.
The password toggle showed the inverted icon
The field used the legacy
passwordToggleEnabledattribute, whose default icon reports the action — open eye while the password is hidden, meaning "tap to reveal". Read as state, which is how people read it, that is backwards. Both screens now useendIconMode="password_toggle"with astate_checkedselector: crossed-out eye while hidden, open eye while visible.Every auth failure collapsed into "Tekrar deneyin."
The mapping matched on Firebase's English error sentence (
"password is invalid","no user record"). Those strings are not API; they changed, and the match silently stopped hitting — so a wrong password and a dropped connection produced the same useless text. Mapping now keys onFirebaseAuthException.errorCode.ERROR_INVALID_CREDENTIALis the case that mattered most: with email enumeration protection on, Firebase returns it for both a wrong password and an unknown account, and nothing recognised it.Leaving the app meant signing in again
Firebase persists the session to disk, but the launcher only skipped the form when a "keep me signed in" checkbox had been ticked — so an unticked box left the user signed in yet facing the login screen at every start. The box is gone; the session now lasts until the sign-out button in Profile, which is the only place that should end it.
The leaderboard error followed the user across tabs
Its retry snackbar attaches to
MainActivity's CoordinatorLayout, not to the fragment, so switching tabs destroyed the fragment and left the snackbar behind. Combined withLENGTH_INDEFINITEit never went away, and it sat over the upload form — the note could not be submitted at all. The snackbar is now held and dismissed inonStopand whenever a load succeeds.ProfileFragmentcarried the identical defect and is fixed the same way.Tests
114 → 129, all green, lint clean.
AuthErrorMessagesTestpins each error code to its own message, including theERROR_INVALID_CREDENTIALregression and the split between the sign-in and register fallbacks.PasswordToggleTestinflates both screens under Robolectric and asserts the icon reports state — droppingendIconDrawablewould leave a working button with the wrong icon and break nothing else.Verified on a device
Emulator, against the live project: the app opens straight to the feed without asking to sign in; the leaderboard error clears on tab change and the upload form is usable; feed and leaderboard both load from the server.
Not a code change, but worth recording
Both composite indexes in
firestore.indexes.jsonwere missing from the live project. The feed only looked healthy because the contribution gate meant its query was never built — the first upload unlocked the gate and it failed too. Deploying step 6 of the README's Getting started is not optional.🤖 Generated with Claude Code