From f1e4fe377a6b69e6266d98c7d2d06080a86a2d39 Mon Sep 17 00:00:00 2001 From: vjrj Date: Mon, 13 Jul 2026 17:19:47 +0200 Subject: [PATCH] fix(chat): collapse trust/rating strips while the keyboard is open On short screens (e.g. landscape) the fixed-height trust and rating strips plus the composer overflowed the body once the keyboard shrank it. Wrap the two secondary strips in HideWhenKeyboardOpen so they yield their vertical space while typing and reappear when the keyboard closes. --- apps/app_seeds/lib/ui/chat_screen.dart | 23 +++++++++++++++++-- .../test/ui/hide_when_keyboard_open_test.dart | 23 +++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 apps/app_seeds/test/ui/hide_when_keyboard_open_test.dart diff --git a/apps/app_seeds/lib/ui/chat_screen.dart b/apps/app_seeds/lib/ui/chat_screen.dart index a48026c..ec8a492 100644 --- a/apps/app_seeds/lib/ui/chat_screen.dart +++ b/apps/app_seeds/lib/ui/chat_screen.dart @@ -386,8 +386,12 @@ class _ChatBody extends StatelessWidget { }, child: Column( children: [ - const _TrustBanner(), - const _RatingStrip(), + // Free the vertical space the trust/rating strips take while the + // keyboard is up: on short screens (e.g. landscape) their fixed height + // plus the composer would otherwise overflow the shrunken body. They + // reappear the moment the keyboard is dismissed. + const HideWhenKeyboardOpen(child: _TrustBanner()), + const HideWhenKeyboardOpen(child: _RatingStrip()), Expanded( child: ChatMessageList( peerName: peerName, @@ -403,6 +407,21 @@ class _ChatBody extends StatelessWidget { } } +/// Hides [child] while the on-screen keyboard is open. Used for the chat's +/// secondary strips (trust, rating) so their fixed height doesn't push the +/// composer off a short screen when the keyboard steals vertical space. +class HideWhenKeyboardOpen extends StatelessWidget { + const HideWhenKeyboardOpen({required this.child, super.key}); + + final Widget child; + + @override + Widget build(BuildContext context) => + MediaQuery.viewInsetsOf(context).bottom > 0 + ? const SizedBox.shrink() + : child; +} + /// The scrolling list of chat bubbles. Anchored at the bottom (chat /// convention): the newest message is always in view, and new arrivals show up /// in place instead of landing below the fold. Reads the [MessagesCubit] from diff --git a/apps/app_seeds/test/ui/hide_when_keyboard_open_test.dart b/apps/app_seeds/test/ui/hide_when_keyboard_open_test.dart new file mode 100644 index 0000000..1123d5f --- /dev/null +++ b/apps/app_seeds/test/ui/hide_when_keyboard_open_test.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:tane/ui/chat_screen.dart'; + +void main() { + Widget host({required double keyboardInset}) => MediaQuery( + data: MediaQueryData(viewInsets: EdgeInsets.only(bottom: keyboardInset)), + child: const Directionality( + textDirection: TextDirection.ltr, + child: HideWhenKeyboardOpen(child: Text('banner')), + ), + ); + + testWidgets('shows its child when the keyboard is closed', (tester) async { + await tester.pumpWidget(host(keyboardInset: 0)); + expect(find.text('banner'), findsOneWidget); + }); + + testWidgets('hides its child when the keyboard is open', (tester) async { + await tester.pumpWidget(host(keyboardInset: 300)); + expect(find.text('banner'), findsNothing); + }); +}