fix(auth)!: resolve the 12 baselined Compose lint findings - #2502
Conversation
There was a problem hiding this comment.
Code Review
This pull request resolves several Compose correctness and localization issues, allowing the removal of suppressed issues from the lint baseline. Key changes include resolving string resources within composable scopes, moving composable lambda parameters to the end of function signatures, respecting per-context locale overrides, snapshotting mutable SDK lists to trigger recomposition, and capitalizing composable test functions. The feedback suggests using a locale-sensitive date format instead of a hardcoded pattern to ensure proper internationalization.
| val enrollmentDateFormat = remember(locale) { | ||
| java.text.SimpleDateFormat("MMM dd, yyyy", locale.platformLocale) | ||
| } |
There was a problem hiding this comment.
While using LocalLocale.current is a great improvement for localization, the date format string "MMM dd, yyyy" is hardcoded. This format is not suitable for all locales (e.g., many European locales use dd.MM.yyyy).
To properly internationalize the date, you should use a locale-sensitive date format provided by java.text.DateFormat. This will ensure the date is displayed in a format that is familiar to users in different regions.
| val enrollmentDateFormat = remember(locale) { | |
| java.text.SimpleDateFormat("MMM dd, yyyy", locale.platformLocale) | |
| } | |
| val enrollmentDateFormat = remember(locale) { | |
| java.text.DateFormat.getDateInstance(java.text.DateFormat.MEDIUM, locale.platformLocale) | |
| } |
64ce7cf to
4f2b154
Compare
d6efbb2 to
6b4bbe9
Compare
auth/lint-baseline.xmlshipped with 12 Compose findings suppressed alongside CPRN-432's168 localization entries, so the new lint gate could go green before the code behind them
was fixed. This fixes all 12 and removes exactly those entries; the 168 localization ones
are untouched.
MutableCollectionMutableStateatMfaEnrollmentScreen.kt:159was the only one withruntime consequences, though not the ones the check warns about. Nothing mutated that
collection in place, so there was no missed recomposition today. The hazard was at the two
enrolledFactors.value = user.multiFactor.enrolledFactorssites, where the SDK hands backits own
MutableList: had it ever returned the same instance it had just mutated,MutableState's structural-equality check would have compared the list against itself andskipped the update. The state now holds an immutable
List<MultiFactorInfo>and bothassignments snapshot with
toList(), which closes that off and satisfies the check.MfaEnrollmentContentStateandMfaEnrollmentDefaultsalready declaredList, so nothingdownstream changed.
The 7
LocalContextGetResourceValueCallsites could not all becomestringResource().Six are not in composable scopes at all: five sit in
LaunchedEffectbodies inFirebaseAuthScreen, andAuthTextField's is inside aModifier.semantics {}lambda.Those now resolve in composition and close over the result, which also means a
configuration change is observed — something
LocalContext.current.getString(...)neverdid. Only
SignInUI.kt:245was a direct read in composition. None of the seven weredeliberate
AuthUIStringProviderrouting: the provider exposes no slot for any of thefive strings involved, so keeping them on the resource path is the smaller change. Worth
raising separately that
FirebaseAuthUI.kt:432and:568buildAuthState.Loadingfromcontext.getString(R.string.fui_loading_signing_out)whileDefaultAuthUIStringProvideralready exposes
loadingSigningOutfor that exact string — the provider is partlybypassed by the runtime, which is its own piece of work.
ComposableLambdaParameterPositionis the breaking part.customLayoutmoves to the lastparameter of the public
AuthMethodPicker, andcontentto the last of the internalEmailAuthStep. All 28AuthMethodPickercall sites in the repo (3 inmain, 25 intests) and both
EmailAuthStepones pass named arguments, so nothing here changed — butan external positional caller of
AuthMethodPickerwould break. Acceptable pre-GA at10.0.0. The KDoc
@paramorder follows the signature.NonObservableLocaleatMfaEnrollmentDefaults.kt:399readjava.util.Locale.getDefault()in a composable. It now reads
LocalLocale.current, which resolves the Activity'sconfigured locale rather than the process global. The two disagree when a host installs a
per-context locale override, and the date was then rendering in a different language from
every
stringResourcebeside it.androidx.compose.ui.text.intl.Locale.currentwould nothave fixed that — it silences the detector but resolves through
AndroidLocaleDelegateAPI24to the same process-global
android.os.LocaleList. TheSimpleDateFormatalso moved into arememberkeyed on the locale; it was previously reconstructed on every recomposition.LocalLocaleis new in compose-ui 1.11, which the BOM already pins well past.ComposableNamingis test-only:ReauthScopeProbe.capture()becomesCapture(), with its27 call sites across three test files.
The
lint { }baseline comment inauth/build.gradle.ktsno longer claims the file holdsCompose findings, since it now holds only CPRN-432's localization entries.
./scripts/build.shand./gradlew lintAllare both clean — lint runs in its ownworkflow now rather than inside the script.
:authlint reports no new issues with 168filtered by baseline, and the baseline diff is 132 deletions with no additions.
:authunit tests are 78 classes / 990 tests, no failures.
Note: stacked on #2498 — needs a rebase once that lands.
Maintainer note: Fixes internal CPRN-436