3273d63b23
- 新增 Home Screen 视觉设计 token (背景、工具栏、对话区、输入框等) - 重构首页布局为浮动式底部输入栈结构 - 新增 HomeBackgroundField、HomeFloatingHeader、HomeAttachmentStrip 组件 - 优化 MessageComposer 视觉样式为悬浮 shell 设计 - 添加相关测试用例
107 lines
2.9 KiB
Dart
107 lines
2.9 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:image_picker/image_picker.dart';
|
|
import 'package:lucide_icons/lucide_icons.dart';
|
|
|
|
import '../../../../core/theme/design_tokens.dart';
|
|
|
|
const homeAttachmentStripKey = ValueKey('home_attachment_strip');
|
|
|
|
class HomeAttachmentStrip extends StatelessWidget {
|
|
const HomeAttachmentStrip({
|
|
super.key,
|
|
required this.images,
|
|
required this.onRemove,
|
|
});
|
|
|
|
final List<XFile> images;
|
|
final ValueChanged<int> onRemove;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (images.isEmpty) {
|
|
return const SizedBox.shrink();
|
|
}
|
|
|
|
return Container(
|
|
key: homeAttachmentStripKey,
|
|
padding: const EdgeInsets.all(AppSpacing.sm),
|
|
decoration: BoxDecoration(
|
|
color: AppColors.homeAttachmentSurface,
|
|
borderRadius: BorderRadius.circular(AppRadius.xl),
|
|
border: Border.all(color: AppColors.homeComposerBorder),
|
|
),
|
|
child: Wrap(
|
|
spacing: AppSpacing.sm,
|
|
runSpacing: AppSpacing.sm,
|
|
children: images.asMap().entries.map((entry) {
|
|
return _AttachmentPreviewTile(
|
|
image: entry.value,
|
|
onRemove: () => onRemove(entry.key),
|
|
);
|
|
}).toList(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _AttachmentPreviewTile extends StatelessWidget {
|
|
const _AttachmentPreviewTile({required this.image, required this.onRemove});
|
|
|
|
final XFile image;
|
|
final VoidCallback onRemove;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
const previewExtent = AppSpacing.xxl * 3 + AppSpacing.sm;
|
|
|
|
return Stack(
|
|
children: [
|
|
ClipRRect(
|
|
borderRadius: BorderRadius.circular(AppRadius.md),
|
|
child: Image.file(
|
|
File(image.path),
|
|
width: previewExtent,
|
|
height: previewExtent,
|
|
fit: BoxFit.cover,
|
|
errorBuilder: (context, error, stackTrace) {
|
|
return Container(
|
|
width: previewExtent,
|
|
height: previewExtent,
|
|
color: AppColors.white,
|
|
alignment: Alignment.center,
|
|
child: const Icon(
|
|
LucideIcons.image,
|
|
size: AppSpacing.xl,
|
|
color: AppColors.slate400,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
Positioned(
|
|
top: AppSpacing.xs,
|
|
right: AppSpacing.xs,
|
|
child: GestureDetector(
|
|
onTap: onRemove,
|
|
child: Container(
|
|
width: AppSpacing.lg + AppSpacing.sm,
|
|
height: AppSpacing.lg + AppSpacing.sm,
|
|
decoration: const BoxDecoration(
|
|
color: AppColors.red500,
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: const Icon(
|
|
LucideIcons.x,
|
|
size: AppSpacing.md,
|
|
color: AppColors.white,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|