Build Keyboard-Aware Layout Utility
epic-email-password-login-foundation-task-003 — Implement a reusable KeyboardAwareLayout widget that listens to MediaQuery.viewInsets to detect software keyboard appearance and dismissal. Dynamically adjust scroll offset so the focused input field remains visible. Handle edge cases for small-viewport devices and ensure smooth animation when keyboard slides in or out.
Acceptance Criteria
Technical Requirements
Implementation Notes
The simplest robust pattern is to wrap the content in a SingleChildScrollView with padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom). Wrap this in an AnimatedContainer or use AnimatedPadding for the smooth transition. Avoid the keyboard_avoider package — it has known issues with nested scrollables. Do not use resizeToAvoidBottomInset: true on the Scaffold in combination with this widget — choose one approach.
For the login screen specifically (two fields: email + password), the scroll offset will be small; the widget becomes critical on the registration or profile screens with more fields. Since this app serves users with motor and cognitive disabilities (NHF requirement), ensure the dismiss-on-tap area is large and does not conflict with button tap targets.
Testing Requirements
Widget tests using flutter_test: (1) pumpWidget with a simulated keyboard inset via MediaQuery override and assert the scroll controller offset increases; (2) assert offset returns to 0 when viewInsets.bottom returns to 0; (3) assert no RenderFlex overflow error on a 320x568 viewport (iPhone SE equivalent). Golden tests for layout at keyboard-open and keyboard-closed states. Manual QA on physical iOS and Android devices — TestFlight build for accessibility testing with VoiceOver enabled.
Supabase client initialization may fail silently in certain Flutter environments if environment variables are missing or the anon key is rotated, leading to runtime null-pointer errors throughout the auth layer.
Mitigation & Contingency
Mitigation: Add explicit assertion checks during app startup that verify the Supabase client is initialized before the router resolves. Document required --dart-define keys in the project README and add a CI step that validates their presence.
Contingency: Implement a fallback initialization error screen with a clear message and a retry button. Log initialization failures to crash reporting immediately.
The flutter_secure_storage package behaviour differs between iOS Keychain and Android Keystore implementations. On Android, biometric-enrolled devices may require additional authentication to read stored tokens, causing unexpected session read failures.
Mitigation & Contingency
Mitigation: Test the repository on Android devices with and without biometric enrollment early in development. Use accessibility options in flutter_secure_storage to configure whether biometric authentication is required for storage access.
Contingency: If biometric-gated storage causes regressions, fall back to a non-biometric storage option for session tokens (reserving biometric-gated storage for higher-sensitivity credentials only).