December 28, 2025
4 min read
By devshan

Table of Contents

This is a list of all the sections in this post. Click on any of them to jump to that section.

1. 功能需求背景

在聊天界面中,多媒体消息(图片、视频、文件)的UI需要进行优化,以提升整体体验和视觉一致性。

1.1 动机

  • 修复文件气泡卡片文件名文字颜色错误问题
  • 移除图片卡片右下角的发送时间(容易造成误解)
  • 视频卡片继续显示时间,但显示视频时长而非发送时间
  • 点击气泡显示发送时间(统一交互方式)
  • 输入框中的Markdown图标优化
  • 会话信息时间精确到秒
  • 日历今天日期边框优化

1.2 设计考量

  • 视觉一致性:统一颜色主题应用
  • 交互一致性:时间显示方式统一
  • 功能清晰性:避免时间信息混淆

2. 技术方案设计

2.1 问题分析

  1. 文件名颜色问题FileMessageContent 使用了错误的颜色逻辑
  2. 时间显示问题MediaMessageBubble 在右下角显示发送时间
  3. 视频时长显示:需要在视频组件中显示时长
  4. Markdown图标:输入框中的图标需要优化
  5. 时间精度:会话信息时间需要精确到秒

2.2 解决方案

  1. 颜色修复:统一使用 theme.colorScheme.onSurface
  2. 时间移除:从 MediaMessageBubble 移除时间显示
  3. 时长显示:在 VideoMessageContent 中保留时长显示
  4. 点击交互:使用之前实现的点击显示时间机制
  5. 图标优化:移除背景,使用主题颜色

3. 实现细节

3.1 文件名颜色修复

原代码

final textColor = isSent ? theme.colorScheme.onPrimary : null;

修改后

final textColor = theme.colorScheme.onSurface;

影响文件client/lib/ui/widgets/chat_widgets.dart

3.2 移除MediaMessageBubble时间显示

原代码

child: Stack(
  children: [
    child,
    // 时间戳
    Positioned(
      right: 8,
      bottom: 6,
      child: Container(
        // 时间显示逻辑
      ),
    ),
  ],
),

修改后

child: child,  // 直接使用child,无Stack包装

3.3 视频时长显示保留

VideoMessageContent 中的时长显示保持不变,位于视频缩略图右下角:

// 时长标签
if (duration != null)
  Positioned(
    right: 8,
    bottom: 8,
    child: Container(
      padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
      decoration: BoxDecoration(
        color: Colors.black54,
        borderRadius: BorderRadius.circular(4),
      ),
      child: Text(
        duration!,
        style: const TextStyle(color: Colors.white, fontSize: 12),
      ),
    ),
  ),

3.4 输入框Markdown图标优化

原代码

child: Container(
  padding: const EdgeInsets.all(4),
  decoration: BoxDecoration(
    color: isDark ? Colors.white : Colors.black,
    borderRadius: BorderRadius.circular(4),
  ),
  child: Icon(
    TablerIcons.markdown,
    color: isDark ? Colors.black : Colors.white,
    size: 16,
  ),
),

修改后

child: Icon(
  TablerIcons.markdown,
  color: isDark ? Colors.white : Colors.black,
  size: 20,
),

3.5 会话信息时间精确到秒

原代码

String _formatDate(DateTime date) {
  return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
}

修改后

String _formatDate(DateTime date) {
  return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')} '
         '${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}:${date.second.toString().padLeft(2, '0')}';
}

3.6 日历今天边框优化

原代码

border: isToday
    ? Border.all(
        color: Theme.of(context).colorScheme.primary,
        width: 2,  // 2px 边框
      )
    : null,

修改后

border: isToday
    ? Border.all(
        color: Theme.of(context).colorScheme.primary,
        width: 1,  // 1px 边框
      )
    : null,

4. 数据库变更

4.1 扩展SendMessages表

添加了两个字段以支持新功能:

  • format:支持Markdown格式
  • duration:支持语音时长

变更内容

class SendMessages extends Table {
  // ... 原有字段
  TextColumn get format => text().nullable()(); // 'plain' | 'markdown' | null
  IntColumn get duration => integer().nullable()(); // 语音时长(毫秒)
  // ... 其他字段
}

4.2 数据转换方法更新

更新了 recordToSendMessagesendMessageToCompanion 方法以支持新字段。

5. 遇到的问题及解决方案

5.1 Drift代码生成问题

问题:修改数据库表后需要重新生成Drift代码 解决方案:运行 dart run build_runner build --delete-conflicting-outputs

5.2 组件状态管理问题

问题:多个组件需要支持点击显示时间功能 解决方案:将相关组件改为StatefulWidget,统一实现时间显示逻辑

5.3 颜色主题一致性问题

问题:不同组件使用不同的颜色逻辑 解决方案:统一使用 Theme.of(context).colorScheme 中的颜色

6. 代码变更

6.1 文件变更

  • client/lib/ui/widgets/chat_widgets.dart:修复颜色、移除时间、组件重构
  • client/lib/ui/chat_page.dart:Markdown图标、时间格式化
  • client/lib/core/database/database.dart:数据库表结构变更
  • client/lib/ui/widgets/message_history_calendar.dart:日历边框优化

6.2 组件变更

  • FileMessageContent:修复文字颜色
  • MediaMessageBubble:移除时间显示
  • MessageBubble:支持点击显示时间
  • MediaMessageBubble:支持点击显示时间
  • 数据库表:添加format和duration字段

7. 测试验证

7.1 功能测试

  • 文件名颜色正确显示
  • 图片卡片无时间显示
  • 视频卡片显示时长
  • 点击气泡显示发送时间
  • 输入框Markdown图标显示正确
  • 会话信息时间精确到秒
  • 日历今天边框正常

7.2 性能测试

  • flutter analyze 无错误
  • 滚动性能正常
  • 内存使用正常
  • 数据库迁移正常

7.3 交互测试

  • 点击交互响应正常
  • 颜色主题切换正常
  • 不同消息类型显示正常

8. 设计决策总结

8.1 颜色统一决策

  • 原因:避免颜色不一致问题
  • 方案:统一使用 onSurface 颜色
  • 效果:提升视觉一致性

8.2 时间显示决策

  • 原因:避免时间信息混淆
  • 方案:移除右下角时间,统一点击显示
  • 效果:功能更清晰,交互更统一

8.3 组件重构决策

  • 原因:需要状态管理支持
  • 方案:StatelessWidget → StatefulWidget
  • 效果:支持交互功能,保持组件独立性

9. 未来优化方向

9.1 功能扩展

  • 支持更多多媒体格式
  • 添加动画效果
  • 优化加载状态显示

9.2 性能优化

  • 使用更高效的布局组件
  • 优化图片加载策略
  • 改进数据库查询性能