merge: 合并 K86.10 评论面板高度与收起流程

This commit is contained in:
Zhou Weidong committed 2026-10-21 13:04:40 +08:00
commit a142a6c318
3 files changed
+128 -51

No files matched your search

+2
View File
@@ -810,6 +810,8 @@ class PlayerLogic extends ChangeNotifier {
isScrollControlled: true,
backgroundColor: Colors.transparent,
showDragHandle: false,
isDismissible: false,
enableDrag: false,
builder: (_) => DramaCommentsSheet(drama: drama),
);
} finally {
@@ -178,6 +178,14 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
).showSnackBar(SnackBar(content: Text(message)));
}
void _handleDismissLayerTap() {
if (_inputFocus.hasFocus || _keyboardHeight(context) > 0) {
_inputFocus.unfocus();
return;
}
Navigator.pop(context);
}
@override
Widget build(BuildContext context) {
final screenLimit = MediaQuery.sizeOf(context).height - 24;
@@ -194,61 +202,80 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
availableHeight,
);
_measureSheetWithoutKeyboard(keyboardHeight);
return AnimatedPadding(
duration: const Duration(milliseconds: 200),
curve: Curves.easeOut,
padding: EdgeInsets.only(bottom: keyboardHeight),
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: inputFocused ? _inputFocus.unfocus : null,
child: SizedBox(
key: _sheetMeasureKey,
child: Container(
key: const Key('player-comments-sheet'),
decoration: const BoxDecoration(
color: AppColors.card,
borderRadius: BorderRadius.vertical(
top: Radius.circular(_sheetRadius),
),
),
child: SafeArea(
top: false,
child: ListenableBuilder(
listenable: _controller,
builder: (context, _) {
final minHeight = _controller.comments.isEmpty
? (_minSheetHeight < maxHeight
? _minSheetHeight
: maxHeight)
: 0.0;
return AnimatedSize(
duration: const Duration(milliseconds: 200),
curve: Curves.easeOut,
alignment: Alignment.bottomCenter,
child: ConstrainedBox(
key: const Key('comment-sheet-constraints'),
constraints: keyboardOpen
? BoxConstraints.tightFor(height: keyboardPanelHeight)
: BoxConstraints(
minHeight: minHeight,
maxHeight: maxHeight,
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: _content(
context,
expanded: expanded,
keyboardHeight: keyboardHeight,
),
),
return Stack(
fit: StackFit.expand,
children: [
Positioned.fill(
child: GestureDetector(
key: const Key('player-comments-dismiss-layer'),
behavior: HitTestBehavior.opaque,
onTap: _handleDismissLayerTap,
),
),
Align(
alignment: Alignment.bottomCenter,
child: AnimatedPadding(
duration: const Duration(milliseconds: 200),
curve: Curves.easeOut,
padding: EdgeInsets.only(bottom: keyboardHeight),
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {},
child: SizedBox(
key: _sheetMeasureKey,
child: Container(
key: const Key('player-comments-sheet'),
decoration: const BoxDecoration(
color: AppColors.card,
borderRadius: BorderRadius.vertical(
top: Radius.circular(_sheetRadius),
),
);
},
),
child: SafeArea(
top: false,
child: ListenableBuilder(
listenable: _controller,
builder: (context, _) {
final minHeight = _controller.comments.isEmpty
? (_minSheetHeight < maxHeight
? _minSheetHeight
: maxHeight)
: 0.0;
return AnimatedSize(
duration: const Duration(milliseconds: 200),
curve: Curves.easeOut,
alignment: Alignment.bottomCenter,
child: ConstrainedBox(
key: const Key('comment-sheet-constraints'),
constraints: keyboardOpen
? BoxConstraints.tightFor(
height: keyboardPanelHeight,
)
: BoxConstraints(
minHeight: minHeight,
maxHeight: maxHeight,
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
),
child: _content(
context,
expanded: expanded,
keyboardHeight: keyboardHeight,
),
),
),
);
},
),
),
),
),
),
),
),
),
],
);
}
@@ -509,7 +536,6 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
focused: focused,
),
onTap: signedIn ? null : _authenticateForComment,
onTapOutside: (_) => _inputFocus.unfocus(),
onSubmitted: focused ? null : (_) => _post(),
),
),
@@ -307,12 +307,14 @@ void main() {
final sheet = find.byKey(const Key('player-comments-sheet'));
final list = find.byKey(const Key('comment-list'));
final heightBeforeKeyboard = tester.getSize(sheet).height;
tester.view.viewInsets = const FakeViewPadding(bottom: 180);
await tester.pump();
await tester.pump(const Duration(milliseconds: 200));
expect(sheet, findsOneWidget);
expect(list, findsOneWidget);
expect(tester.getSize(sheet).height, closeTo(heightBeforeKeyboard, 0.1));
expect(find.byKey(const Key('comment-count-label')), findsOneWidget);
final field = tester.widget<TextField>(
find.byKey(const Key('comment-input')),
@@ -378,6 +380,7 @@ void main() {
);
expect(collapsedField.maxLines, 1);
expect(tester.getSize(find.byKey(const Key('comment-input'))).height, 44);
expect(tester.getSize(sheet).height, closeTo(heightBeforeKeyboard, 0.1));
expect(tester.getSize(sheet).height, lessThan(520));
final editableAfterKeyboard = tester.state<EditableTextState>(
find.descendant(
@@ -402,6 +405,52 @@ void main() {
);
});
testWidgets('should_dismiss_from_outside_in_two_steps', (tester) async {
tester.view.physicalSize = const Size(390, 844);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
addTearDown(tester.view.resetViewInsets);
final repository = FakeCommentRepository(
pages: [
CommentPage(
comments: [commentFixture(id: '10', content: 'A comment')],
),
],
);
await _pumpSheet(tester, repository: repository);
final sheet = find.byKey(const Key('player-comments-sheet'));
final input = find.byKey(const Key('comment-input'));
expect(
find.byKey(const Key('player-comments-dismiss-layer')),
findsOneWidget,
);
tester.view.viewInsets = const FakeViewPadding(bottom: 180);
await tester.tap(input);
await tester.pumpAndSettle();
expect(sheet, findsOneWidget);
expect(tester.widget<TextField>(input).focusNode?.hasFocus, isTrue);
await tester.tap(find.byKey(const Key('comment-list')));
await tester.pump();
expect(sheet, findsOneWidget);
await tester.tapAt(const Offset(20, 20));
await tester.pump();
expect(sheet, findsOneWidget);
expect(tester.widget<TextField>(input).focusNode?.hasFocus, isFalse);
tester.view.viewInsets = const FakeViewPadding();
await tester.pumpAndSettle();
expect(sheet, findsOneWidget);
await tester.tapAt(const Offset(20, 20));
await tester.pumpAndSettle();
expect(sheet, findsNothing);
});
testWidgets('should_use_polished_comment_sizes', (tester) async {
final repository = FakeCommentRepository(
pages: [