4 Commits
16 changed files with 634 additions and 278 deletions
+79
View File
@@ -0,0 +1,79 @@
# ============ Flutter 核心 ============
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
-keep class io.flutter.plugin.** { *; }
-keep class io.flutter.util.** { *; }
-keep class io.flutter.view.** { *; }
-keep class io.flutter.embedding.** { *; }
# 保留 Flutter 的 JNI 调用类
-keep class io.flutter.embedding.engine.FlutterJNI { *; }
-dontwarn io.flutter.embedding.**
# ============ Kotlin ============
-keep class kotlin.** { *; }
-keep class kotlin.Metadata { *; }
-dontwarn kotlin.**
-keepclassmembers class **$WhenMappings {
<fields>;
}
-keepclassmembers class kotlin.Metadata {
public <methods>;
}
# ============ sqflite / SQLite ============
-keep class com.tekartik.sqflite.** { *; }
-dontwarn com.tekartik.sqflite.**
# ============ shared_preferences ============
-keep class io.flutter.plugins.sharedpreferences.** { *; }
# ============ path_provider ============
-keep class io.flutter.plugins.pathprovider.** { *; }
# ============ permission_handler ============
-keep class com.baseflow.permissionhandler.** { *; }
# ============ url_launcher ============
-keep class io.flutter.plugins.urllauncher.** { *; }
# ============ device_info_plus ============
-keep class dev.fluttercommunity.plus.device_info.** { *; }
# ============ 你的原生通道(重要!) ============
# 你的 MethodChannel / EventChannel 相关类需要保留
-keep class com.lxh.battery_health.** { *; }
# ============ AndroidX 常见 ============
-keep class androidx.lifecycle.** { *; }
-dontwarn androidx.lifecycle.**
# ============ 保留 Parcelable / Serializable ============
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
# ============ 异常堆栈保留(方便排查 release 崩溃) ============
-keepattributes SourceFile,LineNumberTable
-renamesourcefileattribute SourceFile
-keepattributes Signature
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes EnclosingMethod
# ============ 移除日志(可选) ============
# 如果你想在 release 里保留日志,注释掉下面这几行
-assumenosideeffects class android.util.Log {
public static *** v(...);
public static *** d(...);
public static *** i(...);
}
File diff suppressed because one or more lines are too long
+27
View File
@@ -1,3 +1,30 @@
## 1.8.0
### 新增
- **夜间模式**:支持浅色 / 深色 / 跟随系统三种模式,可在右上角菜单切换
- **主题系统重构**:统一颜色抽象,所有界面颜色由主题管理
### 优化
- 深色主题下潘通色系重新调色,保证对比度
- AppBar 与内容区背景统一,消除浅色模式下的分界线
----
## [1.7.1] - 2026-09-16
### 新增
- **平均温度显示**:温度面板新增平均温度,与最高/最低温度同排展示(`↑ xx.x℃ ↓ xx.x℃ ⌀ xx.x℃`),更直观了解电池工作温度区间
### 优化
- **数据库升级至 v2**:新增 `temp_avg` 字段,历史数据自动迁移,每日平均温度随扫描自动入库
- **构建工具链同步**:适配最新 Flutter SDK 的 Android 构建要求(AGP 9.0 / Kotlin 2.2 / Gradle 9.3)
- **Release 打包加固**:补齐 ProGuard 混淆规则,release 版本构建更稳定
### 修复
- 修复 Release 版本因缺少混淆规则文件导致打包失败的问题
----
## [1.7.0] - 2026-07-31
### ✨ 新增功能
+65 -45
View File
@@ -1,11 +1,14 @@
import 'package:flutter/material.dart';
import 'pages/battery_health_page.dart';
import 'services/saf_storage_service.dart';
import 'theme/app_colors.dart';
import 'theme/theme_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await SafStorageService().init();
await ThemeService.init(); // 🆕
runApp(const MyApp());
}
@@ -15,53 +18,70 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '电池健康度',
theme: ThemeData(
// 🟢 中文用 HarmonyOS Sans SC
fontFamily: 'HarmonyOS_Sans_SC',
// 🟢 数字回退到 FlymeFont
fontFamilyFallback: const ['Flyme'],
// 🟢 统一文字颜色为黑色
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFFFFFFFF),
).copyWith(onSurface: Colors.black),
textTheme: const TextTheme(
// 大标题/数字(健康度、容量等)
displayMedium: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontFamilyFallback: ['Flyme'],
color: Colors.black,
),
// 标题(如“容量百分比变动趋势”)
headlineMedium: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontFamilyFallback: ['Flyme'],
color: Colors.black,
),
// 正文(电压、温度、循环次数等)
bodyMedium: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontFamilyFallback: ['Flyme'],
color: Colors.black,
),
// 小字(日期、辅助信息)
bodySmall: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontFamilyFallback: ['Flyme'],
color: Colors.black87,
),
// 数字专用(大号数字,如健康度百分比)
displayLarge: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontFamilyFallback: ['Flyme'],
color: Colors.black,
),
return ValueListenableBuilder<ThemeMode>(
valueListenable: ThemeService.notifier,
builder: (context, mode, _) {
return MaterialApp(
title: '电池健康度',
themeMode: mode,
theme: _buildTheme(Brightness.light, kLightColors),
darkTheme: _buildTheme(Brightness.dark, kDarkColors),
home: const BatteryHealthPage(),
debugShowCheckedModeBanner: false,
);
},
);
}
ThemeData _buildTheme(Brightness brightness, AppColors colors) {
return ThemeData(
useMaterial3: true,
brightness: brightness,
scaffoldBackgroundColor: colors.background,
fontFamily: 'HarmonyOS_Sans_SC',
fontFamilyFallback: const ['Flyme'],
colorScheme: ColorScheme.fromSeed(
seedColor: colors.background,
brightness: brightness,
),
extensions: [colors], // 🆕 注册 ThemeExtension
appBarTheme: AppBarTheme(
backgroundColor: colors.background, // ← 关键:和 Scaffold 一致
foregroundColor: colors.textPrimary,
// ← 关掉 M3 的滑动变色
elevation: 0,
iconTheme: IconThemeData(color: colors.textPrimary),
),
textTheme: TextTheme(
displayMedium: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontFamilyFallback: const ['Flyme'],
color: colors.textPrimary,
),
useMaterial3: true,
headlineMedium: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontFamilyFallback: const ['Flyme'],
color: colors.textPrimary,
),
bodyMedium: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontFamilyFallback: const ['Flyme'],
color: colors.textPrimary,
),
bodySmall: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontFamilyFallback: const ['Flyme'],
color: colors.textSecondary,
),
displayLarge: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontFamilyFallback: const ['Flyme'],
color: colors.textPrimary,
),
),
home: const BatteryHealthPage(),
debugShowCheckedModeBanner: false,
);
}
}
+19 -37
View File
@@ -1,16 +1,16 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:url_launcher/url_launcher.dart';
import '../theme/app_colors.dart';
class AboutPage extends StatelessWidget {
const AboutPage({super.key});
@override
Widget build(BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;
final c = context.colors;
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: AppBar(
title: const Text(
'关于',
@@ -19,10 +19,8 @@ class AboutPage extends StatelessWidget {
fontWeight: FontWeight.w500,
),
),
backgroundColor: Colors.transparent,
backgroundColor: c.background,
elevation: 0,
foregroundColor: Theme.of(context).iconTheme.color,
iconTheme: IconThemeData(color: Theme.of(context).iconTheme.color),
),
body: Center(
child: Padding(
@@ -30,15 +28,12 @@ class AboutPage extends StatelessWidget {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Logo
Container(
width: 120,
height: 120,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: isDark
? Colors.grey.shade800
: const Color(0xFFF0F4F8),
color: c.surface,
),
child: ClipOval(
child: Image.asset(
@@ -50,38 +45,39 @@ class AboutPage extends StatelessWidget {
),
),
const SizedBox(height: 24),
const Text(
Text(
'MEIZU Battery Healthy',
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 24,
fontWeight: FontWeight.w600,
color: c.textPrimary,
),
),
const SizedBox(height: 8),
Text(
'版本 1.7.0',
'版本 1.8.0',
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 14,
color: Colors.grey.shade500,
color: c.textTertiary,
fontWeight: FontWeight.w400,
),
),
const SizedBox(height: 16),
Divider(
color: Colors.grey.shade300,
color: c.divider,
thickness: 0.5,
indent: 40,
endIndent: 40,
),
const SizedBox(height: 16),
const Text(
Text(
'专机专配 · 仅针对魅族独家开发',
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 14,
color: Colors.grey,
color: c.textSecondary,
),
),
const SizedBox(height: 8),
@@ -90,13 +86,12 @@ class AboutPage extends StatelessWidget {
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 13,
color: Colors.grey.shade400,
color: c.textTertiary,
),
),
const SizedBox(height: 24),
// 源码链接按钮
InkWell(
onTap: () => _launchUrl(context), // 注意这里传入了 context
onTap: () => _launchUrl(context),
borderRadius: BorderRadius.circular(12),
child: Container(
padding: const EdgeInsets.symmetric(
@@ -104,34 +99,24 @@ class AboutPage extends StatelessWidget {
vertical: 12,
),
decoration: BoxDecoration(
color: isDark
? Colors.grey.shade800
: const Color(0xFFF0F4F8),
color: c.surface,
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.code,
size: 18,
color: Theme.of(context).iconTheme.color,
),
Icon(Icons.code, size: 18, color: c.textPrimary),
const SizedBox(width: 8),
Text(
'查看源码 / 反馈',
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 14,
color: Theme.of(context).iconTheme.color,
color: c.textPrimary,
),
),
const SizedBox(width: 4),
Icon(
Icons.open_in_new,
size: 14,
color: Colors.grey.shade500,
),
Icon(Icons.open_in_new, size: 14, color: c.textTertiary),
],
),
),
@@ -142,7 +127,7 @@ class AboutPage extends StatelessWidget {
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 12,
color: Colors.grey.shade400,
color: c.textTertiary,
),
),
],
@@ -155,14 +140,11 @@ class AboutPage extends StatelessWidget {
Future<void> _launchUrl(BuildContext context) async {
const url = 'https://git.whitetop.xyz/lxh2875931338/MEIZU-Battery-Healthy';
final uri = Uri.parse(url);
try {
// ✅ 直接尝试打开,不再检查 canLaunchUrl
await launchUrl(uri, mode: LaunchMode.externalApplication);
} catch (e) {
// 如果打开失败,复制链接并提示
debugPrint('打开链接失败: $e');
await Clipboard.setData(ClipboardData(text: url));
await Clipboard.setData(const ClipboardData(text: url));
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
+80 -24
View File
@@ -3,6 +3,8 @@ import 'dart:developer' as dev;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:device_info_plus/device_info_plus.dart';
import '../theme/theme_service.dart';
import '../theme/app_colors.dart';
// --- 本地导入 ---
import '../models/device_matching.dart';
@@ -626,6 +628,56 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
return ChargeUtils.getChargeTypeLabel(_isWireless, _chargeType);
}
// 🆕 夜间模式切换弹窗 ← 加在这里
void _showThemePicker() {
showModalBottomSheet(
context: context,
builder: (ctx) {
final current = ThemeService.notifier.value;
return SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.brightness_auto),
title: const Text('跟随系统'),
trailing: current == ThemeMode.system
? const Icon(Icons.check)
: null,
onTap: () {
ThemeService.setMode(ThemeMode.system);
Navigator.pop(ctx);
},
),
ListTile(
leading: const Icon(Icons.light_mode),
title: const Text('浅色'),
trailing: current == ThemeMode.light
? const Icon(Icons.check)
: null,
onTap: () {
ThemeService.setMode(ThemeMode.light);
Navigator.pop(ctx);
},
),
ListTile(
leading: const Icon(Icons.dark_mode),
title: const Text('深色'),
trailing: current == ThemeMode.dark
? const Icon(Icons.check)
: null,
onTap: () {
ThemeService.setMode(ThemeMode.dark);
Navigator.pop(ctx);
},
),
],
),
);
},
);
}
// ---------- Build ----------
@override
Widget build(BuildContext context) {
@@ -645,25 +697,23 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
);
return AnnotatedRegion<SystemUiOverlayStyle>(
value: const SystemUiOverlayStyle(
statusBarColor: Color.fromRGBO(157, 212, 237, 0.1),
value: SystemUiOverlayStyle(
statusBarColor: context.colors.statusBarTint,
statusBarIconBrightness: Brightness.dark,
statusBarBrightness: Brightness.dark,
),
child: Scaffold(
backgroundColor: Colors.white,
// backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.white,
// backgroundColor: Colors.white,
elevation: 0,
scrolledUnderElevation: 0,
shadowColor: Colors.transparent,
surfaceTintColor: Colors.transparent,
title: const Text(
title: Text(
'电池健康度',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w600,
color: Colors.black,
color: context.colors.textPrimary,
),
),
actions: [
@@ -671,11 +721,11 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
icon: const Icon(Icons.refresh),
onPressed: readBatteryCapacity,
tooltip: '刷新数据',
color: Colors.black,
color: context.colors.icon,
),
PopupMenuButton<String>(
icon: const Icon(Icons.more_vert),
color: Colors.white,
color: context.colors.surface,
onSelected: (value) {
switch (value) {
case 'changelog':
@@ -695,7 +745,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
);
break;
case 'dark_mode':
// 夜间模式切换逻辑(1.7.0 再实现)
_showThemePicker();
break;
}
},
@@ -705,11 +755,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
value: 'about', // 🟢 新增
child: Text('关于'),
),
const PopupMenuItem(
value: 'dark_mode',
enabled: false, // 暂时灰显
child: Text('夜间模式(开发中)'),
),
const PopupMenuItem(value: 'dark_mode', child: Text('夜间模式')),
],
),
],
@@ -725,9 +771,9 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
children: [
Text(
_deviceModel,
style: const TextStyle(
style: TextStyle(
fontSize: 14,
color: Colors.grey,
color: context.colors.textTertiary,
fontWeight: FontWeight.w400,
),
),
@@ -804,19 +850,29 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
),
],
)
: const Center(
: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.battery_unknown, size: 64, color: Colors.grey),
SizedBox(height: 16),
Icon(
Icons.battery_unknown,
size: 64,
color: context.colors.textTertiary,
),
const SizedBox(height: 16),
Text(
'暂无数据',
style: TextStyle(fontSize: 18, color: Colors.grey),
style: TextStyle(
fontSize: 18,
color: context.colors.textTertiary,
),
),
Text(
'点击右上角刷新尝试',
style: TextStyle(fontSize: 14, color: Colors.grey),
style: TextStyle(
fontSize: 14,
color: context.colors.textTertiary,
),
),
],
),
+27 -40
View File
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; // 🟢 添加这一行
import 'package:flutter/services.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import '../theme/app_colors.dart';
class ChangelogPage extends StatefulWidget {
const ChangelogPage({super.key});
@@ -15,33 +16,27 @@ class _ChangelogPageState extends State<ChangelogPage>
String _markdownContent = '';
bool _isLoading = true;
String? _error;
Widget? _cachedMarkdown;
// ---------- 滚动 ----------
final ScrollController _scrollController = ScrollController();
double _scrollProgress = 0.0;
bool _isScrolling = false;
// ---------- 呼吸动画(维持高刷感知) ----------
// ---------- 呼吸动画 ----------
late AnimationController _breathController;
late Animation<double> _breathAnimation;
// ---------- 原生刷新率控制 ----------
// 🟢 改用 static final(不是 const)
static final _frameRateChannel = MethodChannel(
'com.lxh.battery_health/frame_rate',
);
// ---------- 生命周期 ----------
@override
void initState() {
super.initState();
_loadChangelog();
// 进入页面时申请高刷(原生层)
_frameRateChannel.invokeMethod('setHighRefreshRate');
// 呼吸动画:让进度条在滚动时轻微抖动,维持高刷感知
_breathController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 500),
@@ -70,16 +65,13 @@ class _ChangelogPageState extends State<ChangelogPage>
@override
void dispose() {
// 离开页面时恢复默认刷新率
_frameRateChannel.invokeMethod('clearRefreshRate');
_scrollController.removeListener(_updateProgress);
_scrollController.dispose();
_breathController.dispose();
super.dispose();
}
// ---------- 方法 ----------
void _updateProgress() {
if (!_scrollController.hasClients) return;
final maxScroll = _scrollController.position.maxScrollExtent;
@@ -96,7 +88,6 @@ class _ChangelogPageState extends State<ChangelogPage>
setState(() {
_markdownContent = content;
_isLoading = false;
_cachedMarkdown = _buildMarkdown(content);
});
} catch (e) {
setState(() {
@@ -106,78 +97,74 @@ class _ChangelogPageState extends State<ChangelogPage>
}
}
Widget _buildMarkdown(String content) {
Widget _buildMarkdown(BuildContext context, String content) {
final c = context.colors;
return Markdown(
data: content,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
styleSheet: MarkdownStyleSheet(
h1: const TextStyle(
h1: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 24,
fontWeight: FontWeight.w700,
color: Colors.black,
color: c.textPrimary,
),
h2: const TextStyle(
h2: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 20,
fontWeight: FontWeight.w600,
color: Colors.black87,
color: c.textPrimary,
),
h3: const TextStyle(
h3: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.black87,
color: c.textSecondary,
),
p: const TextStyle(
p: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 16,
color: Colors.black87,
color: c.textSecondary,
),
listBullet: const TextStyle(
listBullet: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 16,
color: Colors.black87,
color: c.textSecondary,
),
code: const TextStyle(
code: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 14,
color: Colors.black87,
backgroundColor: Color(0xFFF5F5F5),
color: c.textSecondary,
backgroundColor: c.surface,
),
),
);
}
// ---------- Build ----------
@override
Widget build(BuildContext context) {
final c = context.colors;
final breathOffset = _isScrolling ? _breathAnimation.value : 0.0;
final displayProgress = (_scrollProgress + breathOffset).clamp(0.0, 1.0);
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: const Text(
title: Text(
'更新日志',
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
color: Colors.black,
color: c.textPrimary,
),
),
backgroundColor: Colors.white,
elevation: 0,
foregroundColor: Colors.black,
iconTheme: const IconThemeData(color: Colors.black),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(2.0),
child: LinearProgressIndicator(
value: displayProgress,
backgroundColor: Colors.grey.shade200,
valueColor: const AlwaysStoppedAnimation<Color>(
Color.fromRGBO(157, 212, 237, 1.0),
),
backgroundColor: c.divider,
valueColor: AlwaysStoppedAnimation<Color>(c.progressBar),
minHeight: 2.0,
),
),
@@ -188,16 +175,16 @@ class _ChangelogPageState extends State<ChangelogPage>
? Center(
child: Text(
_error!,
style: const TextStyle(
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
color: Colors.grey,
color: c.textTertiary,
),
),
)
: SingleChildScrollView(
controller: _scrollController,
padding: const EdgeInsets.all(16.0),
child: _cachedMarkdown ?? const SizedBox.shrink(),
child: _buildMarkdown(context, _markdownContent),
),
);
}
+164
View File
@@ -0,0 +1,164 @@
import 'package:flutter/material.dart';
@immutable
class AppColors extends ThemeExtension<AppColors> {
final Color background; // 页面背景
final Color surface; // 卡片/面板背景
final Color textPrimary; // 主文字
final Color textSecondary; // 次要文字
final Color textTertiary; // 弱化文字
final Color divider; // 分割线
final Color icon; // 图标色
final Color healthGreen; // 健康度 ≥80%
final Color healthYellow; // 70~80%
final Color healthOrange;
final Color healthRed; // <70% 或异常
final Color barEmpty; // 无数据柱
final Color voltUp; // 电压↑
final Color voltDown; // 电压↓
final Color tempUp;
final Color tempDown;
final Color progressBar; // 更新日志进度条
final Color statusBarTint; // 状态栏背景
const AppColors({
required this.background,
required this.surface,
required this.textPrimary,
required this.textSecondary,
required this.textTertiary,
required this.divider,
required this.icon,
required this.healthGreen,
required this.healthYellow,
required this.healthOrange,
required this.healthRed,
required this.barEmpty,
required this.voltUp,
required this.voltDown,
required this.tempUp,
required this.tempDown,
required this.progressBar,
required this.statusBarTint,
});
@override
AppColors copyWith({
Color? background,
Color? surface,
Color? textPrimary,
Color? textSecondary,
Color? textTertiary,
Color? divider,
Color? icon,
Color? healthGreen,
Color? healthYellow,
Color? healthOrange,
Color? healthRed,
Color? barEmpty,
Color? voltUp,
Color? voltDown,
Color? tempUp,
Color? tempDown,
Color? progressBar,
Color? statusBarTint,
}) {
return AppColors(
background: background ?? this.background,
surface: surface ?? this.surface,
textPrimary: textPrimary ?? this.textPrimary,
textSecondary: textSecondary ?? this.textSecondary,
textTertiary: textTertiary ?? this.textTertiary,
divider: divider ?? this.divider,
icon: icon ?? this.icon,
healthGreen: healthGreen ?? this.healthGreen,
healthYellow: healthYellow ?? this.healthYellow,
healthOrange: healthOrange ?? this.healthOrange,
healthRed: healthRed ?? this.healthRed,
barEmpty: barEmpty ?? this.barEmpty,
voltUp: voltUp ?? this.voltUp,
voltDown: voltDown ?? this.voltDown,
tempUp: tempUp ?? this.tempUp,
tempDown: tempDown ?? this.tempDown,
progressBar: progressBar ?? this.progressBar,
statusBarTint: statusBarTint ?? this.statusBarTint,
);
}
@override
AppColors lerp(ThemeExtension<AppColors>? other, double t) {
if (other is! AppColors) return this;
return AppColors(
background: Color.lerp(background, other.background, t)!,
surface: Color.lerp(surface, other.surface, t)!,
textPrimary: Color.lerp(textPrimary, other.textPrimary, t)!,
textSecondary: Color.lerp(textSecondary, other.textSecondary, t)!,
textTertiary: Color.lerp(textTertiary, other.textTertiary, t)!,
divider: Color.lerp(divider, other.divider, t)!,
icon: Color.lerp(icon, other.icon, t)!,
healthGreen: Color.lerp(healthGreen, other.healthGreen, t)!,
healthYellow: Color.lerp(healthYellow, other.healthYellow, t)!,
healthOrange: Color.lerp(healthOrange, other.healthOrange, t)!,
healthRed: Color.lerp(healthRed, other.healthRed, t)!,
barEmpty: Color.lerp(barEmpty, other.barEmpty, t)!,
voltUp: Color.lerp(voltUp, other.voltUp, t)!,
voltDown: Color.lerp(voltDown, other.voltDown, t)!,
tempUp: Color.lerp(tempUp, other.tempUp, t)!,
tempDown: Color.lerp(tempDown, other.tempDown, t)!,
progressBar: Color.lerp(progressBar, other.progressBar, t)!,
statusBarTint: Color.lerp(statusBarTint, other.statusBarTint, t)!,
);
}
}
/// 浅色主题(保持现有视觉)
const AppColors kLightColors = AppColors(
background: Colors.white,
surface: Color(0xFFF0F4F8),
textPrimary: Colors.black,
textSecondary: Color(0xFF5F5F5F),
textTertiary: Colors.grey,
divider: Color(0xFFE0E0E0),
icon: Colors.black,
healthGreen: Color(0xFF00B140),
healthYellow: Color(0xFFEFDF00),
healthOrange: Color(0xFFD75A16),
healthRed: Colors.red,
barEmpty: Color(0xFFE0E0E0),
voltUp: Colors.red,
voltDown: Colors.blue,
tempUp: Colors.red,
tempDown: Colors.blue,
progressBar: Color.fromRGBO(157, 212, 237, 1.0),
statusBarTint: Color.fromRGBO(157, 212, 237, 0.1),
);
/// 深色主题(色相保留,明度调整)
const AppColors kDarkColors = AppColors(
background: Color(0xFF121212),
surface: Color(0xFF1E1E1E),
textPrimary: Color(0xFFE8E8E8),
textSecondary: Color(0xFFA0A0A0),
textTertiary: Color(0xFF707070),
divider: Color(0xFF2A2A2A),
icon: Color(0xFFE8E8E8),
healthGreen: Color(0xFF00D14D),
healthYellow: Color(0xFFD4C520),
healthOrange: Color(0xFFFF7838),
healthRed: Color(0xFFFF5252),
barEmpty: Color(0xFF2A2A2A),
voltUp: Color(0xFFFF5252),
voltDown: Color(0xFF5AA9FF),
tempUp: Color(0xFFFF5252),
tempDown: Color(0xFF5AA9FF),
progressBar: Color(0xFF5A9BBD),
statusBarTint: Color(0xFF121212),
);
/// 便捷扩展:context.colors.textPrimary
extension AppColorsX on BuildContext {
AppColors get colors => Theme.of(this).extension<AppColors>()!;
}
+45
View File
@@ -0,0 +1,45 @@
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class ThemeService {
static const _prefKey = 'theme_mode';
static final ValueNotifier<ThemeMode> notifier = ValueNotifier(
ThemeMode.system,
);
/// 启动时调用(main.dart)
static Future<void> init() async {
final prefs = await SharedPreferences.getInstance();
final saved = prefs.getString(_prefKey);
notifier.value = _parse(saved);
}
/// 菜单里调用
static Future<void> setMode(ThemeMode mode) async {
notifier.value = mode;
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_prefKey, _name(mode));
}
static ThemeMode _parse(String? s) {
switch (s) {
case 'light':
return ThemeMode.light;
case 'dark':
return ThemeMode.dark;
default:
return ThemeMode.system;
}
}
static String _name(ThemeMode m) {
switch (m) {
case ThemeMode.light:
return 'light';
case ThemeMode.dark:
return 'dark';
case ThemeMode.system:
return 'system';
}
}
}
+43 -45
View File
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import '../models/data_abnormal_type.dart';
import '../theme/app_colors.dart';
class BatteryInfoPanel extends StatelessWidget {
final double batteryVolt;
@@ -9,9 +10,8 @@ class BatteryInfoPanel extends StatelessWidget {
final double minVolt;
final double maxTemp;
final double minTemp;
final DataAbnormalType abnormalType;
final double tempAvg;
final DataAbnormalType abnormalType;
const BatteryInfoPanel({
super.key,
@@ -27,19 +27,22 @@ class BatteryInfoPanel extends StatelessWidget {
@override
Widget build(BuildContext context) {
final c = context.colors;
final bool isVoltageAbnormal =
abnormalType == DataAbnormalType.voltageAbnormal;
final Color voltColor = isVoltageAbnormal ? Colors.red : Colors.black;
final Color voltColor = isVoltageAbnormal ? c.healthRed : c.textPrimary;
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// ---------- 电压列 ----------
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildInfoItem(
_buildIcon('voltage'),
context,
_buildIcon(context, 'voltage'),
'电压',
'${batteryVolt.toStringAsFixed(3)}V',
textColor: voltColor,
@@ -53,22 +56,17 @@ class BatteryInfoPanel extends StatelessWidget {
fontFamily: 'Flyme',
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.red,
color: c.voltUp,
),
children: [
const TextSpan(
TextSpan(
text: '↑ ',
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
color: Colors.red,
),
),
TextSpan(
text: '${maxVolt.toStringAsFixed(3)}V',
style: TextStyle(
color: isVoltageAbnormal ? Colors.red : Colors.red,
color: c.voltUp,
),
),
TextSpan(text: '${maxVolt.toStringAsFixed(3)}V'),
],
),
),
@@ -79,22 +77,17 @@ class BatteryInfoPanel extends StatelessWidget {
fontFamily: 'Flyme',
fontSize: 14,
fontWeight: FontWeight.w500,
color: Colors.blue,
color: c.voltDown,
),
children: [
const TextSpan(
TextSpan(
text: '↓ ',
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
color: Colors.blue,
),
),
TextSpan(
text: '${minVolt.toStringAsFixed(3)}V',
style: TextStyle(
color: isVoltageAbnormal ? Colors.red : Colors.blue,
color: c.voltDown,
),
),
TextSpan(text: '${minVolt.toStringAsFixed(3)}V'),
],
),
),
@@ -103,33 +96,34 @@ class BatteryInfoPanel extends StatelessWidget {
],
),
),
// ---------- 温度列 ----------
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildInfoItem(
_buildIcon('temperature'),
context,
_buildIcon(context, 'temperature'),
'温度',
'${batteryTemp.toStringAsFixed(0)}℃',
),
const SizedBox(height: 8),
// 🆕 一行显示:↑ max ↓ min [avg] avg
Row(
children: [
RichText(
text: TextSpan(
style: const TextStyle(
style: TextStyle(
fontFamily: 'Flyme',
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.red,
color: c.tempUp,
),
children: [
const TextSpan(
TextSpan(
text: '↑ ',
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
color: Colors.red,
color: c.tempUp,
),
),
TextSpan(text: '${maxTemp.toStringAsFixed(1)}℃'),
@@ -139,18 +133,18 @@ class BatteryInfoPanel extends StatelessWidget {
const SizedBox(width: 6),
RichText(
text: TextSpan(
style: const TextStyle(
style: TextStyle(
fontFamily: 'Flyme',
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.blue,
color: c.tempDown,
),
children: [
const TextSpan(
TextSpan(
text: '↓ ',
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
color: Colors.blue,
color: c.tempDown,
),
),
TextSpan(text: '${minTemp.toStringAsFixed(1)}℃'),
@@ -158,15 +152,15 @@ class BatteryInfoPanel extends StatelessWidget {
),
),
const SizedBox(width: 6),
_buildIcon('avg', size: 14),
_buildIcon(context, 'avg', size: 14),
const SizedBox(width: 2),
Text(
'${tempAvg.toStringAsFixed(1)}℃',
style: const TextStyle(
style: TextStyle(
fontFamily: 'Flyme',
fontSize: 12,
fontWeight: FontWeight.w500,
color: Colors.grey,
color: c.textTertiary,
),
),
],
@@ -178,50 +172,54 @@ class BatteryInfoPanel extends StatelessWidget {
);
}
Widget _buildIcon(String type, {double size = 18}) {
Widget _buildIcon(BuildContext context, String type, {double size = 18}) {
final c = context.colors;
final filter = ColorFilter.mode(c.textTertiary, BlendMode.srcIn);
switch (type) {
case 'voltage':
return SvgPicture.asset(
'assets/icons/si--lightning-fill.svg',
width: size,
height: size,
colorFilter: const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
colorFilter: filter,
);
case 'temperature':
return SvgPicture.asset(
'assets/icons/mdi--temperature.svg',
width: size,
height: size,
colorFilter: const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
colorFilter: filter,
);
case 'avg': // 🆕
case 'avg':
return SvgPicture.asset(
'assets/icons/avg.svg',
width: size,
height: size,
colorFilter: const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
colorFilter: filter,
);
default:
return Icon(Icons.help_outline, size: size, color: Colors.grey);
return Icon(Icons.help_outline, size: size, color: c.textTertiary);
}
}
Widget _buildInfoItem(
BuildContext context,
Widget icon,
String label,
String value, {
Color textColor = Colors.black,
Color? textColor,
}) {
final c = context.colors;
return Row(
children: [
icon,
const SizedBox(width: 6),
Text(
label,
style: const TextStyle(
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 14,
color: Colors.grey,
color: c.textTertiary,
),
),
const SizedBox(width: 6),
@@ -231,7 +229,7 @@ class BatteryInfoPanel extends StatelessWidget {
fontFamily: 'Flyme',
fontSize: 16,
fontWeight: FontWeight.w500,
color: textColor,
color: textColor ?? c.textPrimary,
),
),
],
+13 -15
View File
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import '../models/data_abnormal_type.dart';
import '../theme/app_colors.dart';
class BatterySummary extends StatelessWidget {
final double healthPercent;
@@ -19,25 +20,23 @@ class BatterySummary extends StatelessWidget {
@override
Widget build(BuildContext context) {
final c = context.colors;
final bool isAbnormal = abnormalType != DataAbnormalType.none;
final bool isCapacityAbnormal =
abnormalType == DataAbnormalType.capacityTooLow ||
abnormalType == DataAbnormalType.capacityTooHigh;
// 健康度颜色:异常时红色,否则按阈值
final Color healthColor = isAbnormal
? Colors.red
: (healthPercent < 70 ? Colors.red : Colors.black);
? c.healthRed
: (healthPercent < 70 ? c.healthRed : c.textPrimary);
// 容量颜色:异常时红色,否则灰色
final Color capacityColor = isCapacityAbnormal
? Colors.red
: const Color(0xFF5F5F5F);
? c.healthRed
: c.textSecondary;
return Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
// 健康度大数字
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
@@ -60,34 +59,33 @@ class BatterySummary extends StatelessWidget {
fontSize: 20,
fontWeight: FontWeight.w300,
height: 1.0,
color: healthColor == Colors.red
? Colors.red
: Colors.grey.shade600,
color: healthColor == c.healthRed
? c.healthRed
: c.textSecondary,
),
),
],
),
const Spacer(),
// cycles + mAh
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
RichText(
text: TextSpan(
style: const TextStyle(
style: TextStyle(
fontFamily: 'Flyme',
fontSize: 16,
fontWeight: FontWeight.w500,
height: 1.2,
color: Colors.black,
color: c.textPrimary,
),
children: [
TextSpan(text: '$cycleCount'),
const TextSpan(
TextSpan(
text: ' cycles',
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
color: Colors.black,
color: c.textPrimary,
),
),
],
+42 -38
View File
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../utils/charge_utils.dart';
import '../theme/app_colors.dart';
class ChargeDetailPage extends StatelessWidget {
final String chargeType;
@@ -41,50 +42,48 @@ class ChargeDetailPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final c = context.colors;
final isDark = Theme.of(context).brightness == Brightness.dark;
return AnnotatedRegion<SystemUiOverlayStyle>(
value: const SystemUiOverlayStyle(
statusBarColor: Color.fromRGBO(157, 212, 237, 0.1),
statusBarIconBrightness: Brightness.dark,
statusBarBrightness: Brightness.dark,
value: SystemUiOverlayStyle(
statusBarColor: c.statusBarTint,
statusBarIconBrightness: isDark ? Brightness.light : Brightness.dark,
statusBarBrightness: Theme.of(context).brightness,
),
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: const Text('充电详情'),
backgroundColor: Colors.white,
backgroundColor: c.background,
elevation: 0,
scrolledUnderElevation: 0,
shadowColor: Colors.transparent,
surfaceTintColor: Colors.transparent,
foregroundColor: Colors.black,
iconTheme: const IconThemeData(color: Colors.black),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildTextRow('协议', _getProtocolDisplay()),
_buildTextRow(context, '协议', _getProtocolDisplay()),
const Divider(),
if (!isWireless) ...[
_buildTextRow('标定档位', _getRequestedDisplay()),
_buildTextRow(context, '标定档位', _getRequestedDisplay()),
const Divider(),
_buildTextRow('实际功率', _getActualDisplay()),
_buildTextRow(context, '实际功率', _getActualDisplay()),
const Divider(),
] else ...[
_buildTextRow('功率', ChargeUtils.getDisplayPowerWireless(power)),
_buildTextRow(
context,
'功率',
ChargeUtils.getDisplayPowerWireless(power),
),
const Divider(),
],
_buildDetailRow('电压', volt, 'V'),
_buildDetailRow(context, '电压', volt, 'V'),
const Divider(),
_buildDetailRow('电流', curr, 'A'),
_buildDetailRow(context, '电流', curr, 'A'),
const Divider(),
if (isWireless) _buildTextRow('类型', '无线'),
if (!isWireless && wiredLevel == null) _buildTextRow('档位', '自动'),
if (isWireless) _buildTextRow(context, '类型', '无线'),
if (!isWireless && wiredLevel == null)
_buildTextRow(context, '档位', '自动'),
const Spacer(),
Center(
child: Text(
@@ -92,7 +91,7 @@ class ChargeDetailPage extends StatelessWidget {
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 12,
color: Colors.grey.shade500,
color: c.textTertiary,
),
),
),
@@ -103,8 +102,8 @@ class ChargeDetailPage extends StatelessWidget {
);
}
/// 纯文本行(协议、功率、档位等)
Widget _buildTextRow(String label, String value) {
Widget _buildTextRow(BuildContext context, String label, String value) {
final c = context.colors;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 6.0),
child: Row(
@@ -112,20 +111,20 @@ class ChargeDetailPage extends StatelessWidget {
children: [
Text(
label,
style: const TextStyle(
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 16,
fontWeight: FontWeight.w400,
color: Colors.grey,
color: c.textTertiary,
),
),
Text(
value,
style: const TextStyle(
fontFamily: 'HarmonyOS_Sans_SC', // 复杂字符串保持 Harmony
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.black87,
color: c.textPrimary,
),
),
],
@@ -133,8 +132,13 @@ class ChargeDetailPage extends StatelessWidget {
);
}
/// 数值行(电压/电流,数字用 Flyme,单位用 Harmony)
Widget _buildDetailRow(String label, double value, String unit) {
Widget _buildDetailRow(
BuildContext context,
String label,
double value,
String unit,
) {
final c = context.colors;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 6.0),
child: Row(
@@ -142,24 +146,24 @@ class ChargeDetailPage extends StatelessWidget {
children: [
Text(
label,
style: const TextStyle(
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 16,
fontWeight: FontWeight.w400,
color: Colors.grey,
color: c.textTertiary,
),
),
RichText(
text: TextSpan(
style: const TextStyle(
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.black87,
color: c.textPrimary,
),
children: [
TextSpan(
text: value.toStringAsFixed(2),
style: const TextStyle(fontFamily: 'Flyme'), // 🟢 数字用 Flyme
style: const TextStyle(fontFamily: 'Flyme'),
),
TextSpan(
text: unit,
+7 -5
View File
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import '../theme/app_colors.dart';
class ChargeEntry extends StatelessWidget {
final String summary;
@@ -14,6 +15,7 @@ class ChargeEntry extends StatelessWidget {
@override
Widget build(BuildContext context) {
final c = context.colors;
return GestureDetector(
onTap: isCharging ? onTap : null,
child: Row(
@@ -21,11 +23,11 @@ class ChargeEntry extends StatelessWidget {
children: [
Text(
summary,
style: const TextStyle(
fontFamily: 'HarmonyOS_Sans_SC', // 🟢 混合文本用 Harmony
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.black87,
color: c.textPrimary,
),
),
Row(
@@ -36,7 +38,7 @@ class ChargeEntry extends StatelessWidget {
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.grey.shade700,
color: c.textTertiary,
),
),
const SizedBox(width: 4),
@@ -46,7 +48,7 @@ class ChargeEntry extends StatelessWidget {
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.grey.shade700,
color: c.textTertiary,
),
),
],
+19 -21
View File
@@ -1,11 +1,6 @@
import 'package:flutter/material.dart';
import '../theme/app_colors.dart';
// --- 潘通色定义 ---
const Color kHealthGreen = Color(0xFF00B140);
const Color kHealthYellow = Color(0xFFEFDF00);
const Color kHealthOrange = Color(0xFFD75A16);
/// 趋势图柱状图组件
class TrendChart extends StatelessWidget {
final List<Map<String, dynamic>> data;
final int designCap;
@@ -14,6 +9,8 @@ class TrendChart extends StatelessWidget {
@override
Widget build(BuildContext context) {
final c = context.colors;
List<Map<String, dynamic>> displayData = data.isNotEmpty
? data
: _getMockData();
@@ -48,12 +45,13 @@ class TrendChart extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
Text(
'容量百分比变动趋势(近15天)',
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 16,
fontWeight: FontWeight.w500,
color: c.textPrimary,
),
),
const SizedBox(height: 8),
@@ -64,13 +62,13 @@ class TrendChart extends StatelessWidget {
height: 180,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
children: [
Text(
'100',
style: TextStyle(
fontFamily: 'Flyme',
fontSize: 10,
color: Colors.grey,
color: c.textTertiary,
height: 1.0,
),
),
@@ -79,7 +77,7 @@ class TrendChart extends StatelessWidget {
style: TextStyle(
fontFamily: 'Flyme',
fontSize: 10,
color: Colors.grey,
color: c.textTertiary,
height: 1.0,
),
),
@@ -106,14 +104,14 @@ class TrendChart extends StatelessWidget {
Color barColor;
if (value > 0) {
if (value >= 80) {
barColor = kHealthGreen;
barColor = c.healthGreen;
} else if (value >= 70) {
barColor = kHealthYellow;
barColor = c.healthYellow;
} else {
barColor = Colors.red;
barColor = c.healthRed;
}
} else {
barColor = Colors.grey.shade300;
barColor = c.barEmpty;
}
double clampedValue = value.clamp(70.0, 100.0);
double heightFactor =
@@ -144,10 +142,10 @@ class TrendChart extends StatelessWidget {
bottom: 2,
child: Text(
sevenDaysAgoDate,
style: const TextStyle(
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 9,
color: Colors.grey,
color: c.textTertiary,
height: 1.0,
),
),
@@ -158,10 +156,10 @@ class TrendChart extends StatelessWidget {
bottom: 2,
child: Text(
todayDate,
style: const TextStyle(
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 9,
color: Colors.black,
color: c.textPrimary,
height: 1.0,
fontWeight: FontWeight.w600,
),
@@ -176,14 +174,14 @@ class TrendChart extends StatelessWidget {
],
),
if (percents.every((v) => v == 0))
const Padding(
padding: EdgeInsets.only(top: 8.0),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
'暂无历史数据,请点击刷新按钮更新',
style: TextStyle(
fontFamily: 'HarmonyOS_Sans_SC',
fontSize: 12,
color: Colors.grey,
color: c.textTertiary,
),
),
),
+1 -1
View File
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.7.2
version: 1.8.0
environment:
sdk: ^3.9.2