feat: 重构 Home Screen 视觉设计与消息输入组件

- 新增 Home Screen 视觉设计 token (背景、工具栏、对话区、输入框等)
- 重构首页布局为浮动式底部输入栈结构
- 新增 HomeBackgroundField、HomeFloatingHeader、HomeAttachmentStrip 组件
- 优化 MessageComposer 视觉样式为悬浮 shell 设计
- 添加相关测试用例
This commit is contained in:
qzl
2026-03-13 17:25:29 +08:00
parent 4c10929498
commit 3273d63b23
10 changed files with 1212 additions and 259 deletions
@@ -2,6 +2,7 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:lucide_icons/lucide_icons.dart';
import 'package:social_app/core/theme/design_tokens.dart';
import 'package:social_app/shared/widgets/message_composer.dart';
Widget _buildTestApp({
@@ -50,8 +51,11 @@ void main() {
);
expect(find.byKey(messageComposerContainerKey), findsOneWidget);
expect(find.byKey(messageComposerShellKey), findsOneWidget);
expect(find.byKey(messageComposerInnerKey), findsOneWidget);
final containerFinder = find.byKey(messageComposerContainerKey);
final shellFinder = find.byKey(messageComposerShellKey);
final plusFinder = find.byKey(messageComposerPlusButtonKey);
final rightFinder = find.byKey(messageComposerRightButtonKey);
@@ -63,6 +67,29 @@ void main() {
find.descendant(of: containerFinder, matching: rightFinder),
findsOneWidget,
);
final container = tester.widget<Container>(shellFinder);
final decoration = container.decoration! as BoxDecoration;
expect(decoration.color, AppColors.homeComposerShell);
expect(
(decoration.border! as Border).top.color,
AppColors.homeComposerBorder,
);
});
testWidgets('recording state keeps unified floating shell', (tester) async {
await tester.pumpWidget(
_buildTestApp(
mode: MessageComposerMode.holdToSpeak,
process: MessageComposerProcess.recording,
hasMessage: false,
isWaitingAgent: false,
),
);
expect(find.byKey(messageComposerShellKey), findsOneWidget);
expect(find.byKey(messageComposerInnerKey), findsOneWidget);
expect(find.text('松开发送'), findsOneWidget);
});
testWidgets('right action icon follows state priority', (tester) async {
@@ -85,7 +112,9 @@ void main() {
of: find.byKey(messageComposerRightButtonKey),
matching: find.byType(Icon),
);
expect(iconFinder, findsOneWidget);
final iconWidget = tester.widget<Icon>(iconFinder.first);
expect(iconWidget.icon, isNotNull);
return iconWidget.icon!;
}