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.
This commit is contained in:
vjrj 2026-07-13 17:19:47 +02:00
parent 37761a029c
commit f1e4fe377a
2 changed files with 44 additions and 2 deletions

View file

@ -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

View file

@ -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);
});
}