Files
mail-hub/lib/ui/widgets/attachment_chip.dart
hz4th_coder 6c1225f588 MailHub v1.0.0: 跨平台邮箱客户端(纯 Dart IMAP/SMTP/MIME 协议栈)
- 登录: QQ/163/126/189/搜狐/Gmail/Outlook/Yahoo/iCloud/企业邮/自定义, 自动识别+测试连接
- 收信: IMAP 多文件夹同步/未读/星标/搜索(本地+服务器)
- 读信: HTML渲染/CID内嵌图/原文查看/附件下载
- 写信: 收件人/抄送/密送/附件/富文本/草稿/回复转发
- 存储: SQLite + 系统安全存储(DPAPI/Keychain/Keystore)
- 测试: 单元测试 + Mock IMAP/SMTP 服务器集成测试(23项全过)
- 可迁移: Windows/Android/iOS/macOS/Linux 一套代码
2026-08-18 01:10:11 +08:00

71 lines
2.3 KiB
Dart

import 'package:flutter/material.dart';
import '../../core/models/address.dart';
/// 附件展示 chip
class AttachmentChip extends StatelessWidget {
final MailAttachment attachment;
final VoidCallback onTap; // 打开/保存
final VoidCallback? onRemove;
const AttachmentChip({
super.key,
required this.attachment,
required this.onTap,
this.onRemove,
});
@override
Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme;
final icon = _iconFor(attachment.fileName);
return InputChip(
avatar: Icon(icon, size: 18, color: scheme.primary),
label: Text(
attachment.fileName,
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 12.5),
),
tooltip: '${attachment.fileName} (${_size(attachment.size)})',
onPressed: onTap,
onDeleted: onRemove,
deleteIcon: onRemove == null ? null : const Icon(Icons.close, size: 15),
visualDensity: VisualDensity.compact,
);
}
IconData _iconFor(String name) {
final lower = name.toLowerCase();
if (lower.endsWith('.pdf')) return Icons.picture_as_pdf_outlined;
if (lower.endsWith('.doc') || lower.endsWith('.docx')) return Icons.description_outlined;
if (lower.endsWith('.xls') || lower.endsWith('.xlsx') || lower.endsWith('.csv')) {
return Icons.table_chart_outlined;
}
if (lower.endsWith('.ppt') || lower.endsWith('.pptx')) return Icons.slideshow_outlined;
if (lower.endsWith('.zip') || lower.endsWith('.rar') || lower.endsWith('.7z')) {
return Icons.folder_zip_outlined;
}
if (lower.endsWith('.png') ||
lower.endsWith('.jpg') ||
lower.endsWith('.jpeg') ||
lower.endsWith('.gif') ||
lower.endsWith('.webp') ||
lower.endsWith('.bmp')) {
return Icons.image_outlined;
}
if (lower.endsWith('.mp3') || lower.endsWith('.wav') || lower.endsWith('.flac')) {
return Icons.music_note_outlined;
}
if (lower.endsWith('.mp4') || lower.endsWith('.mov') || lower.endsWith('.avi')) {
return Icons.movie_outlined;
}
return Icons.insert_drive_file_outlined;
}
static String _size(int bytes) {
if (bytes < 1024) return '$bytes B';
if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(1)} KB';
return '${(bytes / 1048576).toStringAsFixed(1)} MB';
}
}