4.2 KiB
4.2 KiB
Code standardization & modernization review (2026-07-06)
A grounded pass over the Android app (313 Kotlin files), Cloud Functions (TypeScript), and build. Each item is a real, measured inconsistency (with counts), not generic advice. Applied = done + verified this session; the rest are prioritized by value ÷ risk so the riskier ones can be greenlit deliberately.
Applied (done + verified)
- Compose state collection unified on
collectAsStateWithLifecycle— was 55 files oncollectAsState()vs 2 on the lifecycle-aware variant; now all 57. Addedandroidx.lifecycle:lifecycle-runtime-compose. Upstream flow collection pauses when the UI isn't visible. Commit61a8609. - Firebase Tasks →
.await()(safe subset) —FirestoreOutcomeDataSource(mixed both styles in one file),FirestoreCoupleDataSource,PlayIntegrityChecker. Commit7507ca6.
Recommended next — LOW risk, high value
- Finish Firebase Tasks →
.await()across the remaining ~11 data sources (FirestoreAnswerDataSource11 blocks,FirestoreUserDataSource13,FirebaseAuthDataSource13,FirestoreConversationDataSource,…DateSwipe/DatePlan/DateReflection/DateMemory/QuestionThread/ BucketList/DateMatch,FirebaseStorageDataSource). ~72 blocks remain. Per-block review required — these files mixcallbackFlowsnapshot listeners (leave as-is) and one transaction (FirestoreDateMatchDataSource) with the convertible one-shot Tasks. Watch for the failure→null idiom (seePlayIntegrityChecker.verifyWithServer: userunCatching{ …await() }.getOrNull(), not a bareawait()). Not unit-tested (live Firebase I/O), so do it incrementally with a smoke per file, not a bulk sed.
Recommended — MEDIUM risk / churn
- Gradle version catalog (
gradle/libs.versions.toml) — 57 dependency versions are hardcoded across the build files. The modern Gradle standard centralizes versions + enables thelibs.*accessors. Build-only, fully verifiable (build must pass), but pure mechanical churn with typo risk. FirebaseFirestore/FirebaseFunctionsinjected directly into 9 ViewModels/screens (HomeViewModel,DailyQuestionViewModel,QuestionThreadViewModel,BucketListViewModel,DateBuilderViewModel,MessagesInboxViewModel,ConversationViewModel,PartnerHomeScreen,DeleteAccountScreen) — an architectural leak past the repository/data-source layer that the rest of the app respects.HomeViewModeleven runs raw FirestoreaddSnapshotListeners. Worth extracting to data sources, but higher-risk (touches live listeners) and best done one ViewModel at a time.
Recommended — HIGHER risk, do deliberately
- ~175 hardcoded
Color(0xFF…)literals inui/vs. theme tokens. A theme-token migration is the right modern Compose practice, but carries visual-regression risk; the repo already hasscripts/theme-scan.shand prior brand work, so pair any migration with that scanner + screenshot checks. Do per-screen, not en masse. - Cloud Functions on the v1 API (
functions.https.onCall,functions.pubsub.schedule, all 30 importsfrom 'firebase-functions'). Firebase Functions v2 (firebase-functions/v2/*) is the modern target (better cold-start, concurrency, typed params). Migration changes signatures + deploy config and touches the billing webhook / callables — meaningful risk; do as its own project with sandbox verification, not bundled. - 11
: anytypes in TypeScript (e.g.onCall(async (data: any, …))) — tighten to typed request shapes. Low risk, low urgency; fold into the v2 migration if/when it happens.
Healthy already (no action)
- Material3 only (86 files, zero Material2 imports).
- No
GlobalScope; scoping viaviewModelScope/lifecycleScopethroughout. - Only 9
!!non-null assertions app-wide. - Analytics hashing single-sourced (
AnalyticsHashing, this session); DI split of@Binds/@Providesmodules is idiomatic (not an inconsistency).
Suggested order
3 (finish .await()) → 4 (version catalog) → 5 (ViewModel Firebase extraction, per-VM) → 7 (Functions
v2, standalone) → 6 (colors, per-screen) → 8 (TS types, with #7).