Docs: textfield-centering pitfall + config-source / FCM channel conventions
- mitra_app/CLAUDE.md: pitfall entry for the InputDecorationTheme
min-height collision that broke chat-input centering. Walks through
the working recipe (constraints: BoxConstraints(), Material +
StadiumBorder + Center wrapper). Points at chat_screen.dart::_InputBar
in both apps as the source of truth.
- backend/CLAUDE.md: two new convention sections.
- Config-source: when to use DB-stored (operator-tunable via CC) vs
env-driven (deploy-fixed). Codifies the pattern shipped today for
MITRA_HEARTBEAT_CADENCE_SECONDS so Xendit credentials / callback
tokens follow the same shape tomorrow.
- FCM channel: single shared `halobestie_chat_v1` channel for both
apps, target via android.notification.channelId. Bump the channel
ID when introducing a new sound (Android API 26+ binds sound at
channel-create time).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -63,3 +63,29 @@ void disconnect() {
|
||||
```
|
||||
|
||||
The synchronous side-effects (closing the WS, cancelling timers) still happen immediately. Only the `state =` assignment is deferred, which is a no-op for users — they're navigating away anyway. Regression coverage: `.maestro/flows/ts-mitra-3-08-back_press_after_session_expired_no_red_screen.yaml`.
|
||||
|
||||
### Custom-styled TextField must override the theme's min-height constraint
|
||||
|
||||
The app-wide `InputDecorationTheme` in `lib/core/theme/halo_theme.dart` sets a 48dp min-height for form fields (auth, profile, etc.). Any pill-style chat-input or compact TextField that has a fixed-height parent (≤ 48dp) will **silently lose vertical centering** — the field refuses to collapse below 48dp, the line-box can't sit on the parent's midline, and `textAlignVertical` becomes a no-op. Text anchors top.
|
||||
|
||||
**Rule:** when building a custom-shaped TextField (pill, dense, fixed-height), explicitly null the theme constraint:
|
||||
|
||||
```dart
|
||||
TextField(
|
||||
textAlignVertical: TextAlignVertical.center,
|
||||
decoration: const InputDecoration(
|
||||
isCollapsed: true,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16),
|
||||
constraints: BoxConstraints(), // ← REQUIRED — overrides theme min-height
|
||||
border: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
focusedErrorBorder: InputBorder.none,
|
||||
filled: false,
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
Wrap in `Material(shape: StadiumBorder(...), clipBehavior: antiAlias) + Center(child: TextField)` for proper pill clipping. The chat input bar in [mitra_chat_screen.dart](lib/features/chat/screens/mitra_chat_screen.dart) and [client_app/chat_screen.dart::_InputBar](../client_app/lib/features/chat/screens/chat_screen.dart) both use this pattern; copy from there rather than reinventing.
|
||||
|
||||
Reference in New Issue
Block a user