Files
xianyan/lib/features/file_transfer/presentation/widgets/transfer_speed_chart.dart
Developer ae1df22732 feat: v6.10.3 多语言翻译补全 + 17项功能修复
- 引导页协议多语言支持(languageId传递)
- 登录页双书名号修复 + 注册页协议勾选
- 个人中心页面多语言(18个翻译键)
- 网络断开提示增加关闭/刷新按钮
- 了解我们:新增秋叶qy开发者 + ayk签名修改 + 贡献者精简 + 微风暴微信搜索
- iOS快捷按钮重复修复(删除Info.plist静态定义)
- 测试账号123456警告提示
- 扫码登录自动跳转(HTTP轮询+WebSocket双通道)
- 登录页老用户按钮改次要色
- Syncfusion图表崩溃修复(DeferredBuilder+animationDuration:0)
- macOS标题栏跟随软件夜间模式
- 平台兼容分发渠道弹窗
- 软件著作权图片+交叉水印
- 桌面小部件平台兼容说明默认收起
- iOS/macOS图标更新+名称确认为闲言
- 12个语言文件补全roleNative+7个分发渠道翻译字段
2026-06-02 04:50:32 +08:00

123 lines
3.6 KiB
Dart

// ============================================================
// 闲言APP — 传输速度实时折线图
// 创建时间: 2026-05-19
// 更新时间: 2026-05-19
// 作用: 紧凑型实时速度图表 — 嵌入聊天页输入栏上方
// 上次更新: 初始创建
// ============================================================
import 'package:flutter/cupertino.dart';
import 'package:xianyan/core/theme/app_theme.dart';
import 'package:xianyan/core/theme/app_spacing.dart';
import 'package:xianyan/core/theme/app_typography.dart';
import 'package:xianyan/shared/widgets/containers/deferred_builder.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
class TransferSpeedChart extends StatelessWidget {
const TransferSpeedChart({
super.key,
required this.speedHistory,
this.currentSpeed,
});
final List<double> speedHistory;
final double? currentSpeed;
@override
Widget build(BuildContext context) {
final ext = AppTheme.ext(context);
return Container(
height: 60,
padding: const EdgeInsets.symmetric(
horizontal: AppSpacing.md,
vertical: AppSpacing.xs,
),
decoration: BoxDecoration(
color: ext.bgCard,
border: Border(
top: BorderSide(color: ext.bgElevated, width: 0.5),
),
),
child: Row(
children: [
if (currentSpeed != null && currentSpeed! > 0)
Padding(
padding: const EdgeInsets.only(right: AppSpacing.sm),
child: Text(
_formatSpeed(currentSpeed!),
style: AppTypography.caption2.copyWith(
color: ext.accent,
fontWeight: FontWeight.w600,
),
),
),
Expanded(child: _buildChart(ext)),
],
),
);
}
Widget _buildChart(AppThemeExtension ext) {
final data = speedHistory.isEmpty ? [0.0] : speedHistory;
final chartData = data.asMap().entries.map((e) => _SpeedPt(e.key, e.value)).toList();
return DeferredBuilder(
builder: (context) => SfCartesianChart(
plotAreaBorderWidth: 0,
margin: EdgeInsets.zero,
primaryXAxis: const NumericAxis(
majorGridLines: MajorGridLines(width: 0),
majorTickLines: MajorTickLines(size: 0),
axisLine: AxisLine(width: 0),
labelStyle: TextStyle(fontSize: 0),
isVisible: false,
),
primaryYAxis: const NumericAxis(
majorGridLines: MajorGridLines(width: 0),
majorTickLines: MajorTickLines(size: 0),
axisLine: AxisLine(width: 0),
labelStyle: TextStyle(fontSize: 0),
isVisible: false,
minimum: 0,
),
series: [
AreaSeries<_SpeedPt, int>(
dataSource: chartData,
xValueMapper: (d, _) => d.index,
yValueMapper: (d, _) => d.speed,
color: ext.accent,
borderColor: ext.accent,
borderWidth: 1.5,
animationDuration: 0,
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
ext.accent.withValues(alpha: 0.25),
ext.accent.withValues(alpha: 0.02),
],
),
),
],
),
);
}
String _formatSpeed(double speed) {
if (speed <= 0) return '0 KB/s';
if (speed < 1024) return '${speed.toStringAsFixed(0)} B/s';
if (speed < 1024 * 1024) {
return '${(speed / 1024).toStringAsFixed(1)} KB/s';
}
return '${(speed / (1024 * 1024)).toStringAsFixed(1)} MB/s';
}
}
class _SpeedPt {
const _SpeedPt(this.index, this.speed);
final int index;
final double speed;
}