Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
125fb969e4 | ||
|
|
8be4ff7e40 | ||
|
|
4829cd1da2 | ||
|
|
7989495521 | ||
|
|
1d033670f7 | ||
|
|
2512f88f30 | ||
|
|
1f94114d26 | ||
|
|
75e9e85848 | ||
|
|
68e7be98ed |
@@ -27,7 +27,8 @@
|
||||
| 1.5.0 | 功率计算优化 | ✅ 已发布 |
|
||||
| 1.5.2 | 部分场景字体替换 | ✅ 已发布 |
|
||||
| 1.6.0 | 更新日志独立页面 | ✅ 已发布 |
|
||||
| 1.7.0 | 适配夜间模式 | 📋近期开发 |
|
||||
| 1.7.0 | 关于页与紧急发布log文件数据反作弊能力 | ✅ 已发布 |
|
||||
| 1.8.0 | 适配夜间模式 | 📋近期开发 |
|
||||
| 2.0.0 | 数据看板月份显示扩展等系列更新 | 📋 远景 |
|
||||
| 3.0.0 | 搭配PC上位机记录充电信息等 | 📋 远景 |
|
||||
---
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
analyzer:
|
||||
exclude:
|
||||
- build/**
|
||||
- android/**
|
||||
- web/**
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
id("dev.flutter.flutter-gradle-plugin")
|
||||
}
|
||||
|
||||
@@ -14,10 +13,6 @@ android {
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.lxh.battery_health"
|
||||
minSdk = flutter.minSdkVersion
|
||||
@@ -64,6 +59,12 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
kotlin { // ← 新增块
|
||||
compilerOptions {
|
||||
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
|
||||
@@ -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(...);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.lxh.battery_health
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.BatteryManager
|
||||
|
||||
class BatteryManagerHelper(private val context: Context) {
|
||||
|
||||
fun getBatteryData(): Map<String, Any?> {
|
||||
val bm = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
|
||||
|
||||
// 电流(µA)。部分机型充电为负、放电为正,部分相反
|
||||
val rawCurrentUa = bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_NOW)
|
||||
|
||||
// 电压 / 状态从 ACTION_BATTERY_CHANGED 广播里拿(比 BATTERY_PROPERTY_VOLTAGE 兼容性好)
|
||||
val intent = context.registerReceiver(
|
||||
null,
|
||||
IntentFilter(Intent.ACTION_BATTERY_CHANGED)
|
||||
)
|
||||
val voltageMv = intent?.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1) ?: -1
|
||||
val status = intent?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1
|
||||
val plugged = intent?.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) ?: -1
|
||||
val temperatureTenth = intent?.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1) ?: -1
|
||||
|
||||
val isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
|
||||
status == BatteryManager.BATTERY_STATUS_FULL
|
||||
|
||||
// 符号规约:充电为正
|
||||
val normalizedUa = when {
|
||||
rawCurrentUa == Int.MIN_VALUE -> 0
|
||||
isCharging && rawCurrentUa < 0 -> -rawCurrentUa
|
||||
!isCharging && rawCurrentUa > 0 -> -rawCurrentUa
|
||||
else -> rawCurrentUa
|
||||
}
|
||||
|
||||
// 功率 W = V × A = (mV / 1000) × (µA / 1_000_000)
|
||||
val powerW = if (voltageMv > 0 && normalizedUa != 0) {
|
||||
(voltageMv / 1000.0) * (normalizedUa / 1_000_000.0)
|
||||
} else 0.0
|
||||
|
||||
return mapOf(
|
||||
"voltageMv" to voltageMv,
|
||||
"currentUa" to normalizedUa,
|
||||
"powerW" to powerW,
|
||||
"temperatureC" to if (temperatureTenth > 0) temperatureTenth / 10.0 else 0.0,
|
||||
"plugged" to plugged, // 0=未插, 1=AC, 2=USB, 4=WIRELESS
|
||||
"isCharging" to isCharging,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -255,26 +255,35 @@ private fun clearRefreshRate() {
|
||||
|
||||
// 充电状态通道
|
||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHARGE_CHANNEL)
|
||||
.setMethodCallHandler { call, result ->
|
||||
if (call.method == "getChargeState") {
|
||||
val isCharging = getBatteryStatus()
|
||||
val chargeType = if (isCharging) {
|
||||
val batteryIntent = registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
|
||||
val plug = batteryIntent?.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) ?: -1
|
||||
when (plug) {
|
||||
BatteryManager.BATTERY_PLUGGED_AC -> "AC"
|
||||
BatteryManager.BATTERY_PLUGGED_USB -> "USB"
|
||||
BatteryManager.BATTERY_PLUGGED_WIRELESS -> "WIRELESS"
|
||||
else -> "UNKNOWN"
|
||||
}
|
||||
} else {
|
||||
"NONE"
|
||||
.setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"getChargeState" -> {
|
||||
val isCharging = getBatteryStatus()
|
||||
val chargeType = if (isCharging) {
|
||||
val batteryIntent = registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
|
||||
val plug = batteryIntent?.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) ?: -1
|
||||
when (plug) {
|
||||
BatteryManager.BATTERY_PLUGGED_AC -> "AC"
|
||||
BatteryManager.BATTERY_PLUGGED_USB -> "USB"
|
||||
BatteryManager.BATTERY_PLUGGED_WIRELESS -> "WIRELESS"
|
||||
else -> "UNKNOWN"
|
||||
}
|
||||
result.success(mapOf("isCharging" to isCharging, "chargeType" to chargeType))
|
||||
} else {
|
||||
result.notImplemented()
|
||||
"NONE"
|
||||
}
|
||||
result.success(mapOf("isCharging" to isCharging, "chargeType" to chargeType))
|
||||
}
|
||||
// 🆕 新增分支
|
||||
"getBatteryManagerData" -> {
|
||||
try {
|
||||
result.success(BatteryManagerHelper(applicationContext).getBatteryData())
|
||||
} catch (e: Exception) {
|
||||
result.error("BM_ERROR", e.message, null)
|
||||
}
|
||||
}
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
||||
// SAF 通道
|
||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, SAF_CHANNEL)
|
||||
|
||||
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.12-all.zip
|
||||
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-9.3.1-bin.zip
|
||||
@@ -19,8 +19,8 @@ pluginManagement {
|
||||
|
||||
plugins {
|
||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||
id("com.android.application") version "8.9.1" apply false
|
||||
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
|
||||
id("com.android.application") version "9.1.0" apply false
|
||||
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
|
||||
}
|
||||
|
||||
include(":app")
|
||||
|
||||
@@ -1,3 +1,91 @@
|
||||
## [1.9.0] - 2026-10-11
|
||||
|
||||
### ✨ 新增功能
|
||||
|
||||
- **BatteryManager 实时数据接入**
|
||||
- 新增原生 `BatteryManagerHelper`,通过 Android 官方 API 读取电池端真实功率
|
||||
- 主界面充电行改为显示电池端实时功率(1 秒刷新),反映电池实际吸收的能量
|
||||
- 充电详情页拆分为两个数据源分区:
|
||||
- **BMS 日志**:协议、标定档位、实际功率、电压、电流(原有)
|
||||
- **BatteryManager(电池端)**:电池端电压、电流、功率(新增)
|
||||
- 与专业功率计(PowerZ)实测数据一致,误差在 0.02W 以内
|
||||
|
||||
### 🎨 体验优化
|
||||
|
||||
- **充电行显示格式调整**
|
||||
- 有线充电:`充电中 · PPS · 5.98W / 7.5W`(实际功率 / 标定档位)
|
||||
- 无线充电:`充电中 · 无线 · 12.3W`
|
||||
- USB 慢充:`充电中 · USB · 2.1W`
|
||||
- 瓦特单位统一为大写 `W`
|
||||
- 7.5W 等带小数的档位保留一位小数,其余整数值去掉 `.0`
|
||||
|
||||
- **字体细节优化**
|
||||
- 充电行数字与拉丁字母改用 Flyme 字体,中文字符保持 HarmonyOS Sans SC
|
||||
- 解决混合文本下的字体割裂感
|
||||
- 充电详情页所有功率数值同步应用 Flyme 字体
|
||||
|
||||
### 🐛 问题修复
|
||||
|
||||
- 修复主界面充电行在充电器接入初期显示"读取中..."后数值迟迟不刷新的问题
|
||||
- 修复详情页功率数值字体与其它行不统一的问题
|
||||
- 修复 `wired_level` 解析后标定档位显示取整误差(如 `≈8W/L-1` 修正为 `≈7.5W/L-1`)
|
||||
|
||||
### 📝 技术说明
|
||||
|
||||
- `BATTERY_PROPERTY_CURRENT_NOW` 读数为**电池端净电流**(充电器输入减去系统功耗),而非充电器输出端数据
|
||||
- 电池接近满电时数值会明显偏低(涓流阶段),属正常现象
|
||||
- 与系统状态栏显示的充电功率为不同概念,前者反映电池实际吸收,后者反映充电器输出
|
||||
|
||||
---
|
||||
|
||||
## [1.8.0] - 2026-10-11
|
||||
|
||||
### 新增
|
||||
- **夜间模式**:支持浅色 / 深色 / 跟随系统三种模式,可在右上角菜单切换
|
||||
- **主题系统重构**:统一颜色抽象,所有界面颜色由主题管理
|
||||
|
||||
### 优化
|
||||
- 深色主题下潘通色系重新调色,保证对比度
|
||||
- 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
|
||||
|
||||
### ✨ 新增功能
|
||||
|
||||
- **关于页面**
|
||||
- 右上角三点菜单新增“关于”入口
|
||||
- 展示应用 Logo、版本号、作者信息及版权声明
|
||||
- 支持一键跳转源码仓库(Gitea),便于用户反馈问题
|
||||
|
||||
- **数据反作弊能力(紧急发布)**
|
||||
- 容量数据入库前增加有效性校验,拒绝异常值污染趋势图
|
||||
- 校验规则:容量低于设计容量 60% 或高于 115% 的日志数据将被自动过滤
|
||||
- UI 层同步增加异常状态检测,容量或电压异常时相关数值自动标红警示
|
||||
- 该机制同时作用于历史日志扫描与实时数据读取,确保统计结果真实可信
|
||||
|
||||
### 🔧 问题修复
|
||||
|
||||
- 修复部分机型上 `url_launcher` 无法正常打开链接的问题(Android 11+ 包可见性适配)
|
||||
|
||||
----
|
||||
|
||||
## [1.6.0] - 2026-07-20
|
||||
|
||||
### ✨ 新增
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1789561763510" class="icon" viewBox="0 0 1282 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5901" xmlns:xlink="http://www.w3.org/1999/xlink" width="250.390625" height="200"><path d="M703.104 952h-2.272c-19.904 0-36.64-7.072-40.448-26.848L531.2 243.808l-139.392 328c-6.848 16.128-22.496 28.704-39.84 28.704H91.456A43.52 43.52 0 0 1 48 556.768a43.52 43.52 0 0 1 43.456-43.744h232.096l184.064-430.528a43.424 43.424 0 0 1 44.672-26.24 43.424 43.424 0 0 1 37.856 35.296l122.528 650.336 111.712-373.44c5.312-17.632 20.832-30.08 39.072-31.168 18.848-0.32 34.976 9.664 42.272 26.4l64.608 149.344h250.176a43.52 43.52 0 0 1 43.488 43.744 43.52 43.52 0 0 1-43.488 43.744h-278.624a43.52 43.52 0 0 1-39.808-26.4l-28.736-66.304-128.736 421.792c-5.472 18.56-22.496 22.4-41.504 22.4z m0 0" fill="#999999" p-id="5902"></path></svg>
|
||||
|
After Width: | Height: | Size: 972 B |
@@ -1,34 +0,0 @@
|
||||
**/dgph
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.moved-aside
|
||||
*.pbxuser
|
||||
*.perspectivev3
|
||||
**/*sync/
|
||||
.sconsign.dblite
|
||||
.tags*
|
||||
**/.vagrant/
|
||||
**/DerivedData/
|
||||
Icon?
|
||||
**/Pods/
|
||||
**/.symlinks/
|
||||
profile
|
||||
xcuserdata
|
||||
**/.generated/
|
||||
Flutter/App.framework
|
||||
Flutter/Flutter.framework
|
||||
Flutter/Flutter.podspec
|
||||
Flutter/Generated.xcconfig
|
||||
Flutter/ephemeral/
|
||||
Flutter/app.flx
|
||||
Flutter/app.zip
|
||||
Flutter/flutter_assets/
|
||||
Flutter/flutter_export_environment.sh
|
||||
ServiceDefinitions.json
|
||||
Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# Exceptions to above rules.
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
!default.pbxuser
|
||||
!default.perspectivev3
|
||||
@@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.flutter.flutter.app</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>13.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1 +0,0 @@
|
||||
#include "Generated.xcconfig"
|
||||
@@ -1 +0,0 @@
|
||||
#include "Generated.xcconfig"
|
||||
@@ -1,616 +0,0 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
|
||||
remoteInfo = Runner;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */,
|
||||
);
|
||||
path = RunnerTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
||||
);
|
||||
name = Flutter;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146E51CF9000F007C117D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146EF1CF9000F007C117D /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146F01CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||
97C147021CF9000F007C117D /* Info.plist */,
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
331C8080294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||
buildPhases = (
|
||||
331C807D294A63A400263BE5 /* Sources */,
|
||||
331C807F294A63A400263BE5 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
331C8086294A63A400263BE5 /* PBXTargetDependency */,
|
||||
);
|
||||
name = RunnerTests;
|
||||
productName = RunnerTests;
|
||||
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Runner;
|
||||
productName = Runner;
|
||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
331C8080294A63A400263BE5 = {
|
||||
CreatedOnToolsVersion = 14.0;
|
||||
TestTargetID = 97C146ED1CF9000F007C117D;
|
||||
};
|
||||
97C146ED1CF9000F007C117D = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
LastSwiftMigration = 1100;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||
compatibilityVersion = "Xcode 9.3";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 97C146E51CF9000F007C117D;
|
||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
97C146ED1CF9000F007C117D /* Runner */,
|
||||
331C8080294A63A400263BE5 /* RunnerTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
331C807F294A63A400263BE5 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
331C807D294A63A400263BE5 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 97C146ED1CF9000F007C117D /* Runner */;
|
||||
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C146FB1CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
97C147001CF9000F007C117D /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
249021D3217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.batteryHealth;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
331C8088294A63A400263BE5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.batteryHealth.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
331C8089294A63A400263BE5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.batteryHealth.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
331C808A294A63A400263BE5 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.batteryHealth.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147041CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
97C147061CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.batteryHealth;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
97C147071CF9000F007C117D /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.batteryHealth;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
331C8088294A63A400263BE5 /* Debug */,
|
||||
331C8089294A63A400263BE5 /* Release */,
|
||||
331C808A294A63A400263BE5 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147031CF9000F007C117D /* Debug */,
|
||||
97C147041CF9000F007C117D /* Release */,
|
||||
249021D3217E4FDB00AE95B9 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
97C147061CF9000F007C117D /* Debug */,
|
||||
97C147071CF9000F007C117D /* Release */,
|
||||
249021D4217E4FDB00AE95B9 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,101 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1510"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "331C8080294A63A400263BE5"
|
||||
BuildableName = "RunnerTests.xctest"
|
||||
BlueprintName = "RunnerTests"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
enableGPUValidationMode = "1"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Profile"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Runner.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PreviewsEnabled</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,13 +0,0 @@
|
||||
import Flutter
|
||||
import UIKit
|
||||
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-20x20@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-29x29@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-40x40@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-60x60@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-App-60x60@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-20x20@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-40x40@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-40x40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-76x76@1x.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-76x76@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"filename" : "Icon-App-1024x1024@1x.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 295 B |
|
Before Width: | Height: | Size: 406 B |
|
Before Width: | Height: | Size: 450 B |
|
Before Width: | Height: | Size: 282 B |
|
Before Width: | Height: | Size: 462 B |
|
Before Width: | Height: | Size: 704 B |
|
Before Width: | Height: | Size: 406 B |
|
Before Width: | Height: | Size: 586 B |
|
Before Width: | Height: | Size: 862 B |
|
Before Width: | Height: | Size: 862 B |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 762 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage@3x.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 68 B |
|
Before Width: | Height: | Size: 68 B |
|
Before Width: | Height: | Size: 68 B |
@@ -1,5 +0,0 @@
|
||||
# Launch Screen Assets
|
||||
|
||||
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
|
||||
|
||||
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
|
||||
@@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
|
||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="53" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="LaunchImage" width="168" height="185"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Flutter View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
@@ -1,49 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Battery Health</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>battery_health</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1 +0,0 @@
|
||||
#import "GeneratedPluginRegistrant.h"
|
||||
@@ -1,12 +0,0 @@
|
||||
import Flutter
|
||||
import UIKit
|
||||
import XCTest
|
||||
|
||||
class RunnerTests: XCTestCase {
|
||||
|
||||
func testExample() {
|
||||
// If you add code to the Runner application, consider adding tests here.
|
||||
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -3,6 +3,9 @@ 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 '../services/battery_manager_service.dart';
|
||||
|
||||
// --- 本地导入 ---
|
||||
import '../models/device_matching.dart';
|
||||
@@ -45,6 +48,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
||||
String _deviceModel = "魅族21 Pro (默认)";
|
||||
double _maxTemp = 0;
|
||||
double _minTemp = 0;
|
||||
double _batteryTempAvg = 0;
|
||||
double _maxVolt = 0;
|
||||
double _minVolt = 0;
|
||||
bool _hasData = false;
|
||||
@@ -61,6 +65,9 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
||||
int? _wiredLevel;
|
||||
bool _isWireless = false;
|
||||
DateTime? _chargingStartTime;
|
||||
double _bmPower = 0.0;
|
||||
double _bmVolt = 0.0;
|
||||
double _bmCurr = 0.0;
|
||||
|
||||
// ---------- SAF 状态 ----------
|
||||
final SafStorageService _safService = SafStorageService();
|
||||
@@ -77,6 +84,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
||||
|
||||
// 轮询定时器(15秒)
|
||||
Timer? _pollTimer;
|
||||
Timer? _bmTimer;
|
||||
|
||||
// ---------- 生命周期 ----------
|
||||
@override
|
||||
@@ -121,7 +129,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
||||
readBatteryCapacity();
|
||||
}
|
||||
});
|
||||
|
||||
_startBmPolling(); // ← 调用,不是定义
|
||||
dev.log('🔵 ========== initState 结束 ==========', name: 'BatteryHealth');
|
||||
}
|
||||
|
||||
@@ -129,6 +137,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
||||
void dispose() {
|
||||
_chargeEventSubscription?.cancel();
|
||||
_pollTimer?.cancel();
|
||||
_bmTimer?.cancel();
|
||||
_dbService.database.then((db) => db.close()).ignore();
|
||||
super.dispose();
|
||||
}
|
||||
@@ -249,6 +258,9 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
||||
_chargeCurr = 0.0;
|
||||
_wiredLevel = null;
|
||||
_chargingStartTime = null;
|
||||
_bmPower = 0.0; // 🆕
|
||||
_bmVolt = 0.0; // 🆕
|
||||
_bmCurr = 0.0; // 🆕
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -359,6 +371,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
||||
final volt = _extractVolt(lastLine);
|
||||
final (maxTemp, minTemp) = _extractTempExtremes(validLines);
|
||||
final (maxVolt, minVolt) = _extractVoltExtremes(validLines);
|
||||
final tempAvg = _extractTempAvg(validLines);
|
||||
|
||||
dev.log(
|
||||
'🔵 字段提取: cycle=$cycle, temp=$temp, volt=$volt',
|
||||
@@ -390,6 +403,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
||||
_currentCap = (validatedCap ?? _currentCap).toDouble();
|
||||
_cycleCount = cycle;
|
||||
_batteryTemp = temp;
|
||||
_batteryTempAvg = tempAvg;
|
||||
_batteryVolt = volt;
|
||||
_maxTemp = maxTemp;
|
||||
_minTemp = minTemp;
|
||||
@@ -494,6 +508,20 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
||||
return (maxTemp ?? 0, minTemp ?? 0);
|
||||
}
|
||||
|
||||
double _extractTempAvg(List<String> lines) {
|
||||
final reg = RegExp(r'tbat=(\d+)');
|
||||
double sum = 0;
|
||||
int count = 0;
|
||||
for (String line in lines) {
|
||||
final match = reg.firstMatch(line);
|
||||
if (match != null) {
|
||||
sum += double.parse(match.group(1)!);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count > 0 ? sum / count : 0;
|
||||
}
|
||||
|
||||
(double, double) _extractVoltExtremes(List<String> lines) {
|
||||
final reg = RegExp(r'vbat=(\d+)');
|
||||
double? maxVolt, minVolt;
|
||||
@@ -591,24 +619,90 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- BM 轮询(1秒) ----------
|
||||
void _startBmPolling() {
|
||||
_bmTimer?.cancel();
|
||||
_bmTimer = Timer.periodic(const Duration(seconds: 1), (_) async {
|
||||
if (!_isCharging) return;
|
||||
try {
|
||||
final d = await BatteryManagerService.fetch();
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_bmPower = d.powerW;
|
||||
_bmVolt = d.voltageV;
|
||||
_bmCurr = d.currentA;
|
||||
});
|
||||
} catch (e) {
|
||||
// 静默降级,保留上一次的值
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ---------- 显示辅助 ----------
|
||||
String _getDisplayPower() {
|
||||
if (!_isCharging) return '';
|
||||
if (_isWireless) {
|
||||
return ChargeUtils.getDisplayPowerWireless(_chargePower);
|
||||
} else {
|
||||
return ChargeUtils.getMainDisplayPowerWired(
|
||||
_chargePower,
|
||||
_wiredLevel,
|
||||
_chargeType,
|
||||
);
|
||||
}
|
||||
return ChargeUtils.getMainDisplayPowerBm(
|
||||
_bmPower,
|
||||
_wiredLevel,
|
||||
_chargeType,
|
||||
_isWireless,
|
||||
);
|
||||
}
|
||||
|
||||
String _getChargeTypeLabel() {
|
||||
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) {
|
||||
@@ -628,25 +722,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: [
|
||||
@@ -654,11 +746,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':
|
||||
@@ -678,7 +770,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
||||
);
|
||||
break;
|
||||
case 'dark_mode':
|
||||
// 夜间模式切换逻辑(1.7.0 再实现)
|
||||
_showThemePicker();
|
||||
break;
|
||||
}
|
||||
},
|
||||
@@ -688,11 +780,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('夜间模式')),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -708,9 +796,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,
|
||||
),
|
||||
),
|
||||
@@ -757,6 +845,9 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
||||
volt: _chargeVolt,
|
||||
curr: _chargeCurr,
|
||||
wiredLevel: _wiredLevel,
|
||||
bmPower: _bmPower, // 🆕
|
||||
bmVolt: _bmVolt, // 🆕
|
||||
bmCurr: _bmCurr, // 🆕
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -773,6 +864,7 @@ class _BatteryHealthPageState extends State<BatteryHealthPage> {
|
||||
child: BatteryInfoPanel(
|
||||
batteryVolt: _batteryVolt,
|
||||
batteryTemp: _batteryTemp,
|
||||
tempAvg: _batteryTempAvg,
|
||||
maxVolt: _maxVolt,
|
||||
minVolt: _minVolt,
|
||||
maxTemp: _maxTemp,
|
||||
@@ -786,19 +878,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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -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),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -87,25 +87,39 @@ class BatteryDataService {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 提取电压极值
|
||||
// 提取电压极值与平均温度
|
||||
final voltReg = RegExp(r'vbat=(\d+)');
|
||||
final tempReg = RegExp(r'tbat=(\d+)');
|
||||
double? maxVolt, minVolt;
|
||||
double tempSum = 0;
|
||||
int tempCount = 0;
|
||||
|
||||
for (String line in lines) {
|
||||
if (!line.contains('tbat=')) continue;
|
||||
final match = voltReg.firstMatch(line);
|
||||
if (match != null) {
|
||||
final v = int.parse(match.group(1)!) / 1000000;
|
||||
|
||||
final vMatch = voltReg.firstMatch(line);
|
||||
if (vMatch != null) {
|
||||
final v = int.parse(vMatch.group(1)!) / 1000000;
|
||||
if (maxVolt == null || v > maxVolt) maxVolt = v;
|
||||
if (minVolt == null || v < minVolt) minVolt = v;
|
||||
}
|
||||
|
||||
final tMatch = tempReg.firstMatch(line);
|
||||
if (tMatch != null) {
|
||||
tempSum += double.parse(tMatch.group(1)!);
|
||||
tempCount++;
|
||||
}
|
||||
}
|
||||
if (maxVolt == null || minVolt == null) continue;
|
||||
|
||||
final tempAvg = tempCount > 0 ? tempSum / tempCount : 0.0;
|
||||
|
||||
await _dbService.insertOrUpdate(
|
||||
dateStr,
|
||||
validatedCap,
|
||||
maxVolt,
|
||||
minVolt,
|
||||
tempAvg: tempAvg, // 🆕
|
||||
);
|
||||
dev.log(
|
||||
'🔵 插入数据库: $dateStr, cap=$validatedCap',
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
/// BatteryManager 实时数据(电池端:电压 / 电流 / 功率)
|
||||
class BatteryManagerData {
|
||||
final int voltageMv;
|
||||
final int currentUa;
|
||||
final double powerW;
|
||||
final double temperatureC;
|
||||
final int plugged; // 0=未插, 1=AC, 2=USB, 4=WIRELESS
|
||||
final bool isCharging;
|
||||
|
||||
const BatteryManagerData({
|
||||
required this.voltageMv,
|
||||
required this.currentUa,
|
||||
required this.powerW,
|
||||
required this.temperatureC,
|
||||
required this.plugged,
|
||||
required this.isCharging,
|
||||
});
|
||||
|
||||
factory BatteryManagerData.empty() => const BatteryManagerData(
|
||||
voltageMv: 0,
|
||||
currentUa: 0,
|
||||
powerW: 0,
|
||||
temperatureC: 0,
|
||||
plugged: 0,
|
||||
isCharging: false,
|
||||
);
|
||||
|
||||
factory BatteryManagerData.fromMap(dynamic raw) {
|
||||
if (raw is! Map) return BatteryManagerData.empty();
|
||||
return BatteryManagerData(
|
||||
voltageMv: (raw['voltageMv'] as num?)?.toInt() ?? 0,
|
||||
currentUa: (raw['currentUa'] as num?)?.toInt() ?? 0,
|
||||
powerW: (raw['powerW'] as num?)?.toDouble() ?? 0.0,
|
||||
temperatureC: (raw['temperatureC'] as num?)?.toDouble() ?? 0.0,
|
||||
plugged: (raw['plugged'] as num?)?.toInt() ?? 0,
|
||||
isCharging: raw['isCharging'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
/// 电压 V
|
||||
double get voltageV => voltageMv / 1000.0;
|
||||
|
||||
/// 电流 A
|
||||
double get currentA => currentUa / 1_000_000.0;
|
||||
}
|
||||
|
||||
class BatteryManagerService {
|
||||
static const _channel = MethodChannel('com.lxh.battery_health/charge');
|
||||
|
||||
/// 主动拉取一次
|
||||
static Future<BatteryManagerData> fetch() async {
|
||||
final result = await _channel.invokeMethod('getBatteryManagerData');
|
||||
return BatteryManagerData.fromMap(result);
|
||||
}
|
||||
}
|
||||
@@ -6,22 +6,21 @@ import 'package:path/path.dart';
|
||||
class DatabaseService {
|
||||
static Database? _database;
|
||||
static const String _tableName = 'battery_data';
|
||||
static const int _dbVersion = 2; // 🆕 1.7.1 加入 temp_avg
|
||||
|
||||
/// 获取数据库实例(单例)
|
||||
Future<Database> get database async {
|
||||
if (_database != null) return _database!;
|
||||
_database = await _initDatabase();
|
||||
return _database!;
|
||||
}
|
||||
|
||||
/// 初始化数据库
|
||||
Future<Database> _initDatabase() async {
|
||||
final dbPath = await getDatabasesPath();
|
||||
final path = join(dbPath, 'battery_health.db');
|
||||
|
||||
return await openDatabase(
|
||||
path,
|
||||
version: 1,
|
||||
version: _dbVersion,
|
||||
onCreate: (db, version) async {
|
||||
await db.execute('''
|
||||
CREATE TABLE $_tableName (
|
||||
@@ -29,6 +28,7 @@ class DatabaseService {
|
||||
capacity INTEGER NOT NULL,
|
||||
volt_max REAL NOT NULL,
|
||||
volt_min REAL NOT NULL,
|
||||
temp_avg REAL NOT NULL DEFAULT 0,
|
||||
updated_at TEXT NOT NULL
|
||||
)
|
||||
''');
|
||||
@@ -37,6 +37,15 @@ class DatabaseService {
|
||||
''');
|
||||
dev.log('✅ 数据库表创建成功', name: 'DatabaseService');
|
||||
},
|
||||
onUpgrade: (db, oldVersion, newVersion) async {
|
||||
// 🆕 1.7.1 v1 -> v2:添加 temp_avg 字段
|
||||
if (oldVersion < 2) {
|
||||
await db.execute(
|
||||
'ALTER TABLE $_tableName ADD COLUMN temp_avg REAL NOT NULL DEFAULT 0',
|
||||
);
|
||||
dev.log('✅ 数据库升级 v1->v2:已添加 temp_avg 字段', name: 'DatabaseService');
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -45,8 +54,9 @@ class DatabaseService {
|
||||
String date,
|
||||
int capacity,
|
||||
double voltMax,
|
||||
double voltMin,
|
||||
) async {
|
||||
double voltMin, {
|
||||
double tempAvg = 0, // 🆕
|
||||
}) async {
|
||||
final db = await database;
|
||||
final now = DateTime.now().toIso8601String();
|
||||
|
||||
@@ -55,9 +65,13 @@ class DatabaseService {
|
||||
'capacity': capacity,
|
||||
'volt_max': voltMax,
|
||||
'volt_min': voltMin,
|
||||
'temp_avg': tempAvg,
|
||||
'updated_at': now,
|
||||
}, conflictAlgorithm: ConflictAlgorithm.replace);
|
||||
dev.log('📝 数据已保存: $date, cap=$capacity', name: 'DatabaseService');
|
||||
dev.log(
|
||||
'📝 数据已保存: $date, cap=$capacity, tempAvg=${tempAvg.toStringAsFixed(1)}',
|
||||
name: 'DatabaseService',
|
||||
);
|
||||
}
|
||||
|
||||
/// 查询最近 N 条数据(按日期倒序)
|
||||
|
||||
@@ -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>()!;
|
||||
}
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import '../constants/charge_maps.dart';
|
||||
|
||||
class ChargeUtils {
|
||||
// ============ 无线充电(保持不变) ============
|
||||
// ============ 无线充电 ============
|
||||
static String getDisplayPowerWireless(double power) {
|
||||
if (power == 0) return '读取中...';
|
||||
const List<int> levels = [5, 7, 15, 27, 40, 50, 66];
|
||||
@@ -13,7 +13,7 @@ class ChargeUtils {
|
||||
return '≈${matchedLevel}W';
|
||||
}
|
||||
|
||||
// ============ 原有有线逻辑(保留兼容,但主界面不再直接调用) ============
|
||||
// ============ 旧的有线逻辑(保留兼容) ============
|
||||
static String getDisplayPowerWired(
|
||||
double power,
|
||||
int? wiredLevel,
|
||||
@@ -34,57 +34,81 @@ class ChargeUtils {
|
||||
return best > 0 ? '≈${best.toInt()}W' : '≈${power.round()}W';
|
||||
}
|
||||
|
||||
// ============ 🟢 1.5.0 新增:主界面显示(实际/标定) ============
|
||||
/// 示例:≈30w/65w
|
||||
// ============ 主界面:实际 / 标定(旧版) ============
|
||||
static String getMainDisplayPowerWired(
|
||||
double power,
|
||||
int? wiredLevel,
|
||||
String chargeType,
|
||||
) {
|
||||
// USB 慢充锁定 7.5W
|
||||
if (chargeType == "SDP") return "≈7.5w";
|
||||
if (chargeType == "SDP") return "≈7.5W";
|
||||
|
||||
if (power == 0) return "读取中...";
|
||||
|
||||
final actual = power.round();
|
||||
|
||||
// 有档位且能查到标定值
|
||||
if (wiredLevel != null && ChargeMaps.wiredPower.containsKey(wiredLevel)) {
|
||||
final requested = ChargeMaps.wiredPower[wiredLevel]!.round();
|
||||
return "≈${actual}w/${requested}w";
|
||||
return "≈${actual}W/${requested}W";
|
||||
}
|
||||
|
||||
// 无档位信息,仅显示实际功率
|
||||
return "≈${actual}w";
|
||||
return "≈${actual}W";
|
||||
}
|
||||
|
||||
// ============ 🟢 1.5.0 新增:二级页面标定档位显示 ============
|
||||
/// 示例:≈80w/L-10
|
||||
// ============ 主界面:BM 电池端功率 + 标定档位 ============
|
||||
/// 示例:5.98W / 7.5W、12.3W、读取中...
|
||||
static String getMainDisplayPowerBm(
|
||||
double bmPower,
|
||||
int? wiredLevel,
|
||||
String chargeType,
|
||||
bool isWireless,
|
||||
) {
|
||||
if (bmPower <= 0 || bmPower > 100) return '读取中...';
|
||||
|
||||
final powerStr = '${bmPower.toStringAsFixed(1)}W';
|
||||
|
||||
if (isWireless || chargeType == 'SDP') return powerStr;
|
||||
|
||||
if (wiredLevel != null && ChargeMaps.wiredPower.containsKey(wiredLevel)) {
|
||||
final requested = ChargeMaps.wiredPower[wiredLevel]!;
|
||||
final requestedStr = requested == requested.roundToDouble()
|
||||
? requested.toInt().toString()
|
||||
: requested.toStringAsFixed(1);
|
||||
return '$powerStr / ${requestedStr}W';
|
||||
}
|
||||
|
||||
return powerStr;
|
||||
}
|
||||
|
||||
// ============ 详情页:标定档位 ============
|
||||
/// 示例:≈80W/L-10、≈7.5W/L-1
|
||||
static String getDetailRequestedPowerWired(
|
||||
double power,
|
||||
int? wiredLevel,
|
||||
String chargeType,
|
||||
) {
|
||||
if (chargeType == "SDP") return "≈7.5w";
|
||||
if (chargeType == "SDP") return "≈7.5W";
|
||||
|
||||
if (power == 0) return "读取中...";
|
||||
|
||||
if (wiredLevel != null && ChargeMaps.wiredPower.containsKey(wiredLevel)) {
|
||||
final requested = ChargeMaps.wiredPower[wiredLevel]!.round();
|
||||
return "≈${requested}w/L-$wiredLevel";
|
||||
final requested = ChargeMaps.wiredPower[wiredLevel]!;
|
||||
final str = requested == requested.roundToDouble()
|
||||
? requested.toInt().toString()
|
||||
: requested.toStringAsFixed(1);
|
||||
return "≈${str}W/L-$wiredLevel";
|
||||
}
|
||||
|
||||
return "≈${power.round()}w";
|
||||
return "≈${power.round()}W";
|
||||
}
|
||||
|
||||
// ============ 🟢 1.5.0 新增:二级页面实际功率显示 ============
|
||||
// ============ 详情页:实际功率 ============
|
||||
static String getDetailActualPowerWired(double power, String chargeType) {
|
||||
if (chargeType == "SDP") return "≈7.5w";
|
||||
if (chargeType == "SDP") return "≈7.5W";
|
||||
if (power == 0) return "读取中...";
|
||||
return "≈${power.round()}w";
|
||||
return "≈${power.round()}W";
|
||||
}
|
||||
|
||||
// ============ 充电类型标签(保持不变) ============
|
||||
// ============ 充电类型标签 ============
|
||||
static String getChargeTypeLabel(bool isWireless, String chargeType) {
|
||||
if (isWireless) {
|
||||
return chargeType == "无线" ? "无线" : chargeType;
|
||||
|
||||
@@ -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,6 +10,7 @@ class BatteryInfoPanel extends StatelessWidget {
|
||||
final double minVolt;
|
||||
final double maxTemp;
|
||||
final double minTemp;
|
||||
final double tempAvg;
|
||||
final DataAbnormalType abnormalType;
|
||||
|
||||
const BatteryInfoPanel({
|
||||
@@ -19,24 +21,28 @@ class BatteryInfoPanel extends StatelessWidget {
|
||||
required this.minVolt,
|
||||
required this.maxTemp,
|
||||
required this.minTemp,
|
||||
this.tempAvg = 0,
|
||||
this.abnormalType = DataAbnormalType.none,
|
||||
});
|
||||
|
||||
@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,
|
||||
@@ -50,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'),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -76,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'),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -100,12 +96,14 @@ class BatteryInfoPanel extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
// ---------- 温度列 ----------
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildInfoItem(
|
||||
_buildIcon('temperature'),
|
||||
context,
|
||||
_buildIcon(context, 'temperature'),
|
||||
'温度',
|
||||
'${batteryTemp.toStringAsFixed(0)}℃',
|
||||
),
|
||||
@@ -114,45 +112,57 @@ class BatteryInfoPanel extends StatelessWidget {
|
||||
children: [
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontFamily: 'Flyme',
|
||||
fontSize: 14,
|
||||
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(0)}℃'),
|
||||
TextSpan(text: '${maxTemp.toStringAsFixed(1)}℃'),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const SizedBox(width: 6),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontFamily: 'Flyme',
|
||||
fontSize: 14,
|
||||
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(0)}℃'),
|
||||
TextSpan(text: '${minTemp.toStringAsFixed(1)}℃'),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
_buildIcon(context, 'avg', size: 14),
|
||||
const SizedBox(width: 2),
|
||||
Text(
|
||||
'${tempAvg.toStringAsFixed(1)}℃',
|
||||
style: TextStyle(
|
||||
fontFamily: 'Flyme',
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: c.textTertiary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -162,43 +172,54 @@ class BatteryInfoPanel extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildIcon(String type) {
|
||||
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: 18,
|
||||
height: 18,
|
||||
colorFilter: const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
|
||||
width: size,
|
||||
height: size,
|
||||
colorFilter: filter,
|
||||
);
|
||||
case 'temperature':
|
||||
return SvgPicture.asset(
|
||||
'assets/icons/mdi--temperature.svg',
|
||||
width: 18,
|
||||
height: 18,
|
||||
colorFilter: const ColorFilter.mode(Colors.grey, BlendMode.srcIn),
|
||||
width: size,
|
||||
height: size,
|
||||
colorFilter: filter,
|
||||
);
|
||||
case 'avg':
|
||||
return SvgPicture.asset(
|
||||
'assets/icons/avg.svg',
|
||||
width: size,
|
||||
height: size,
|
||||
colorFilter: filter,
|
||||
);
|
||||
default:
|
||||
return const Icon(Icons.help_outline, size: 18, 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),
|
||||
@@ -208,7 +229,7 @@ class BatteryInfoPanel extends StatelessWidget {
|
||||
fontFamily: 'Flyme',
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: textColor,
|
||||
color: textColor ?? c.textPrimary,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -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;
|
||||
@@ -9,6 +10,9 @@ class ChargeDetailPage extends StatelessWidget {
|
||||
final double volt;
|
||||
final double curr;
|
||||
final int? wiredLevel;
|
||||
final double bmPower;
|
||||
final double bmVolt;
|
||||
final double bmCurr;
|
||||
|
||||
const ChargeDetailPage({
|
||||
super.key,
|
||||
@@ -18,6 +22,9 @@ class ChargeDetailPage extends StatelessWidget {
|
||||
required this.volt,
|
||||
required this.curr,
|
||||
this.wiredLevel,
|
||||
this.bmPower = 0,
|
||||
this.bmVolt = 0,
|
||||
this.bmCurr = 0,
|
||||
});
|
||||
|
||||
String _getProtocolDisplay() {
|
||||
@@ -41,61 +48,71 @@ 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()),
|
||||
// ========== BMS 来源 ==========
|
||||
_buildSectionTitle(context, 'BMS 日志'),
|
||||
_buildTextRow(context, '协议', _getProtocolDisplay()),
|
||||
const Divider(),
|
||||
|
||||
if (!isWireless) ...[
|
||||
_buildTextRow('标定档位', _getRequestedDisplay()),
|
||||
_buildTextRow(
|
||||
context,
|
||||
'标定档位',
|
||||
_getRequestedDisplay(),
|
||||
valueFont: 'Flyme',
|
||||
),
|
||||
const Divider(),
|
||||
_buildTextRow('实际功率', _getActualDisplay()),
|
||||
_buildTextRow(
|
||||
context,
|
||||
'实际功率',
|
||||
_getActualDisplay(),
|
||||
valueFont: 'Flyme',
|
||||
),
|
||||
const Divider(),
|
||||
] else ...[
|
||||
_buildTextRow('功率', ChargeUtils.getDisplayPowerWireless(power)),
|
||||
_buildTextRow(
|
||||
context,
|
||||
'功率',
|
||||
ChargeUtils.getDisplayPowerWireless(power),
|
||||
valueFont: 'Flyme',
|
||||
),
|
||||
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('档位', '自动'),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// ========== BM 来源 ==========
|
||||
_buildSectionTitle(context, 'BatteryManager(电池端)'),
|
||||
_buildDetailRow(context, '电压', bmVolt, 'V'),
|
||||
const Divider(),
|
||||
_buildDetailRow(context, '电流', bmCurr, 'A'),
|
||||
const Divider(),
|
||||
bmPower > 0
|
||||
? _buildDetailRow(context, '功率', bmPower, 'W')
|
||||
: _buildTextRow(context, '功率', '读取中...'),
|
||||
const Spacer(),
|
||||
Center(
|
||||
child: Text(
|
||||
'数据来自 BMS 实时日志',
|
||||
style: TextStyle(
|
||||
fontFamily: 'HarmonyOS_Sans_SC',
|
||||
fontSize: 12,
|
||||
color: Colors.grey.shade500,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -103,8 +120,29 @@ class ChargeDetailPage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
/// 纯文本行(协议、功率、档位等)
|
||||
Widget _buildTextRow(String label, String value) {
|
||||
Widget _buildSectionTitle(BuildContext context, String title) {
|
||||
final c = context.colors;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontFamily: 'HarmonyOS_Sans_SC',
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: c.textTertiary,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTextRow(
|
||||
BuildContext context,
|
||||
String label,
|
||||
String value, {
|
||||
String valueFont = 'HarmonyOS_Sans_SC',
|
||||
}) {
|
||||
final c = context.colors;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6.0),
|
||||
child: Row(
|
||||
@@ -112,20 +150,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: valueFont,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black87,
|
||||
color: c.textPrimary,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -133,8 +171,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 +185,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,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../theme/app_colors.dart';
|
||||
|
||||
class ChargeEntry extends StatelessWidget {
|
||||
final String summary;
|
||||
@@ -14,18 +15,23 @@ class ChargeEntry extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final c = context.colors;
|
||||
return GestureDetector(
|
||||
onTap: isCharging ? onTap : null,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
summary,
|
||||
style: const TextStyle(
|
||||
fontFamily: 'HarmonyOS_Sans_SC', // 🟢 混合文本用 Harmony
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.black87,
|
||||
Flexible(
|
||||
child: RichText(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: c.textPrimary,
|
||||
),
|
||||
children: _buildSpans(summary),
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
@@ -36,7 +42,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 +52,7 @@ class ChargeEntry extends StatelessWidget {
|
||||
fontFamily: 'HarmonyOS_Sans_SC',
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.grey.shade700,
|
||||
color: c.textTertiary,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -55,4 +61,54 @@ class ChargeEntry extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 按 CJK / 非 CJK 拆分字符串,分别应用 HarmonyOS / Flyme
|
||||
List<TextSpan> _buildSpans(String text) {
|
||||
final spans = <TextSpan>[];
|
||||
if (text.isEmpty) return spans;
|
||||
|
||||
final buffer = StringBuffer();
|
||||
bool? isCJK;
|
||||
|
||||
void flush() {
|
||||
if (buffer.isEmpty) return;
|
||||
spans.add(
|
||||
TextSpan(
|
||||
text: buffer.toString(),
|
||||
style: TextStyle(
|
||||
fontFamily: (isCJK ?? false) ? 'HarmonyOS_Sans_SC' : 'Flyme',
|
||||
),
|
||||
),
|
||||
);
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
for (final rune in text.runes) {
|
||||
final cjk = _isCJKRune(rune);
|
||||
if (isCJK == null || cjk == isCJK) {
|
||||
buffer.writeCharCode(rune);
|
||||
isCJK = cjk;
|
||||
} else {
|
||||
flush();
|
||||
buffer.writeCharCode(rune);
|
||||
isCJK = cjk;
|
||||
}
|
||||
}
|
||||
flush();
|
||||
return spans;
|
||||
}
|
||||
|
||||
bool _isCJKRune(int rune) {
|
||||
// CJK 统一表意文字
|
||||
if (rune >= 0x4E00 && rune <= 0x9FFF) return true;
|
||||
// CJK 扩展 A
|
||||
if (rune >= 0x3400 && rune <= 0x4DBF) return true;
|
||||
// 中文标点(。、,:;等)
|
||||
if (rune >= 0x3000 && rune <= 0x303F) return true;
|
||||
// CJK 兼容符号
|
||||
if (rune >= 0xFE30 && rune <= 0xFE4F) return true;
|
||||
// 全角字符
|
||||
if (rune >= 0xFF00 && rune <= 0xFFEF) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -45,18 +45,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
||||
sha256: e51d50bca3217c9a9fa2b41a30e4a38971133f5f9ec7a3d57bae095007f1d28e
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
code_assets:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: code_assets
|
||||
sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
version: "1.1.3"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -65,14 +57,6 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.19.1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.7"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -160,14 +144,6 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
hooks:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: hooks
|
||||
sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -188,18 +164,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: jni
|
||||
sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f
|
||||
sha256: f038e58b4dc2c9037f50e233175086337e0b305e356d28211bf55f21c504cbd3
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "1.0.3"
|
||||
jni_flutter:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: jni_flutter
|
||||
sha256: "8b59e590786050b1cd866677dddaf76b1ade5e7bc751abe04b86e84d379d3ba6"
|
||||
sha256: b2310cdd4c18c65c081ab141a41efa94aa26c65431803703ece51996f174f351
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
version: "1.0.3"
|
||||
jni_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: jni_util
|
||||
sha256: "1ba86da04a5f2bf18fde2edb235587e70c5b0fc5bd4ba955f46b00942c3fc35f"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -232,14 +216,6 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
markdown:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -252,10 +228,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
|
||||
sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.12.19"
|
||||
version: "0.12.20"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -268,26 +244,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
|
||||
sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
objective_c:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: objective_c
|
||||
sha256: "6cb691c686fa2838c6deb34980d426145c2a5d537491cb83d463c33cdbc726ed"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "9.4.1"
|
||||
version: "1.19.0"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
|
||||
sha256: ffcf4cf3d6c0b74ac43708d9f56625506e8a68aa935abe9d267a7330f320eb5d
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
version: "3.0.0"
|
||||
path:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -321,13 +289,13 @@ packages:
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
dependency: "direct overridden"
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699"
|
||||
sha256: "6d13aece7b3f5c5a9731eaf553ff9dcbc2eff41087fd2df587fd0fed9a3eb0c4"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.6.0"
|
||||
version: "2.5.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -372,34 +340,34 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_apple
|
||||
sha256: "79dfa1df734798aa3cfdad166d3a3698c206d8813de13516ea1071b5d7e2f420"
|
||||
sha256: f49cb15a064ea9d974fc7fbb302099353b7b170d07284e86e264561579e5bcf8
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "9.4.10"
|
||||
version: "9.6.1"
|
||||
permission_handler_html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_html
|
||||
sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
|
||||
sha256: "6ea98b3f17f60d3b527f2647ed2ab4dc0f6bfe25b22cb1c363f5d8f62252f6ac"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.1.3+5"
|
||||
version: "0.1.4+1"
|
||||
permission_handler_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
|
||||
sha256: ed86a61c190258fdd65de395ea0632822e3415c1faec38eae0c31b479c28a531
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "4.3.0"
|
||||
version: "4.4.1"
|
||||
permission_handler_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_windows
|
||||
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
|
||||
sha256: caeae01858a0a7d2df67a445ac98e1ad95e55a0e77c73044f4e9b1c8c2289cbd
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.2.1"
|
||||
version: "0.2.2"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -412,10 +380,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
|
||||
sha256: a36d119c13416516a7b5913fbe8af8531e11633d784c550b2125f76c758524ec
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.1.6"
|
||||
version: "3.2.0"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -424,22 +392,6 @@ packages:
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
record_use:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: record_use
|
||||
sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -452,18 +404,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: "93ae5884a9df5d3bb696825bceb3a17590754548b5d740eba51500afc8d088f5"
|
||||
sha256: "1e12aafe408aa50da80edfd679a2a6bf63ba7ab37c7fa98286da459a757b3399"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.4.26"
|
||||
version: "2.4.28"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_foundation
|
||||
sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f"
|
||||
sha256: "2ec3934efa51e46117f23031cc141b8fc878e8525b94ec1ea4f7f586cf1b47ea"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.5.6"
|
||||
version: "2.5.7"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -513,50 +465,50 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sqflite
|
||||
sha256: "58a799e6ac17dd32fbab93813d39ed835a75ccc0f8f85b8955fe318c6712b082"
|
||||
sha256: "54ad23e2a79c846b596b6c56cdd9c867ea58c288258402316b602f78df0cbfe0"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.4.3"
|
||||
version: "2.4.4"
|
||||
sqflite_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_android
|
||||
sha256: d0548f9d7422a2dae99ec6f8b0a3074463b132d216fa5ba0d230eeefc901983b
|
||||
sha256: "805b27c6fa10d8883253795e644818fbd5c87ce665459db84fbe71326cbb5421"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.4.3"
|
||||
version: "2.4.4"
|
||||
sqflite_common:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_common
|
||||
sha256: "5bf6a55c166e73bf651ba7ec3ed486e577620e3dc8f3a9c6a258a8031b624590"
|
||||
sha256: "077e38e82c099534146a2fb31b608c2a3a4489a0f21d9af6b2f5c87b566a1ea0"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.5.11"
|
||||
version: "2.5.13"
|
||||
sqflite_darwin:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_darwin
|
||||
sha256: c86ca18b8f666bbf903924687fe21cc16fc385d086005067e26619ca530bef9f
|
||||
sha256: dbdda396f975f74d611ffd3e6fb280ee3ee4cd2319b89278533f427e0140cf0b
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.4.3+1"
|
||||
version: "2.4.4"
|
||||
sqflite_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_platform_interface
|
||||
sha256: f84939f84350d92d04416f8bc4dc52d3896aec7716cc9e80cf0146342139dc50
|
||||
sha256: c9177b2f3150ed0647b90a94307c28452fe0a5401863044216aed83addd6c7c5
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
version: "2.4.2"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
||||
sha256: "277654b3034d17ac6f9f1cb5595db011b1d5d41e8806866db28e0abaa101c490"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.12.1"
|
||||
version: "1.12.2"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -577,10 +529,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: synchronized
|
||||
sha256: "93b153dcb6a26dcddee6ca087dd634b53e38c10b5aa163e8e49501a776456153"
|
||||
sha256: "397b146f97613b83d84bdccb439bc8d0f3aebb6c1d14a9641e6f24201c490b2d"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
version: "3.4.2"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -593,10 +545,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
|
||||
sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.7.11"
|
||||
version: "0.7.12"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -617,34 +569,34 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: b413d49b73867ac08dd2f9890efd3cc11f2a0e577618d50843440a1fb3776c32
|
||||
sha256: "611e87fb320b70d1dd721dc46af89c98aceccea9b31fde49e084591414e0c610"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "6.3.32"
|
||||
version: "6.3.33"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0"
|
||||
sha256: "8faa1aab294f1ab4040b43660c887b0418d5fa4f0cffef76a484e6aa1092eb4a"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "6.4.1"
|
||||
version: "6.4.2"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a
|
||||
sha256: "10f86fef4c2c43563fa6c211ff9cf757adf4d3ab762c56bd430664a947d70cd0"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.2.2"
|
||||
version: "3.2.3"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18"
|
||||
sha256: "5e835a3b869c2d70325349c81c5a45c28e20791265b67b2669da6b08c5cd5201"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.2.5"
|
||||
version: "3.2.6"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -665,18 +617,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f"
|
||||
sha256: "6c5ad3f22cd4c38e089b81963b3cd7bb83b111b2df5dce008bb066162f42e429"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.1.5"
|
||||
version: "3.1.6"
|
||||
vector_graphics:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics
|
||||
sha256: "2306c03da2ba81724afeb589c351ebbc0aa7d86005925be8f8735856dbe5e42d"
|
||||
sha256: "9d0e3b9cb16542ad660daee871e726a10d13a93b7b5391677c3160e8f5e83935"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.2"
|
||||
version: "1.2.3"
|
||||
vector_graphics_codec:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -689,26 +641,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_compiler
|
||||
sha256: "142a9146f447d15b10bdc00e21d5f4d83e5b32bb5f8f8f5a04c75311344923a3"
|
||||
sha256: "4dca4feb77dc3ec7f6e27e49c53241eb8217f55e4f9b12599a27f8903bca5682"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.6"
|
||||
version: "1.3.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
||||
sha256: f36f9f3be64c6198714492bb455c11056e33e2f85d9a0b676a48301e44fdcf47
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
version: "2.4.2"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360"
|
||||
sha256: "5f37239c4851efcef929cea7824e76df7f2f0970aef85d66bbc430afa40e72f0"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "15.2.0"
|
||||
version: "15.3.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -753,10 +705,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
||||
sha256: f67cdd8e07d3c6329146aaef1ba043542b3134c12489f553ca9a7435d1068aea
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
version: "3.1.4"
|
||||
sdks:
|
||||
dart: ">=3.12.0 <4.0.0"
|
||||
flutter: ">=3.44.0"
|
||||
|
||||
@@ -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.0-dev.3
|
||||
version: 1.8.0
|
||||
|
||||
environment:
|
||||
sdk: ^3.9.2
|
||||
@@ -39,7 +39,7 @@ dependencies:
|
||||
flutter_svg: ^2.0.10+1
|
||||
shared_preferences: ^2.2.0
|
||||
flutter_markdown: ^0.7.0
|
||||
url_launcher: 6.3.2
|
||||
url_launcher: ^6.3.2
|
||||
android_intent_plus: ^5.2.0
|
||||
|
||||
|
||||
@@ -116,3 +116,6 @@ flutter:
|
||||
#
|
||||
# For details regarding fonts from package dependencies,
|
||||
# see https://flutter.dev/to/font-from-package
|
||||
|
||||
dependency_overrides:
|
||||
path_provider_foundation: 2.5.1
|
||||
|
Before Width: | Height: | Size: 917 B |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 20 KiB |
@@ -1,38 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
If you are serving your web app in a path other than the root, change the
|
||||
href value below to reflect the base path you are serving from.
|
||||
|
||||
The path provided below has to start and end with a slash "/" in order for
|
||||
it to work correctly.
|
||||
|
||||
For more details:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
|
||||
|
||||
This is a placeholder for base href that will be replaced by the value of
|
||||
the `--base-href` argument provided to `flutter build`.
|
||||
-->
|
||||
<base href="$FLUTTER_BASE_HREF">
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||
<meta name="description" content="A new Flutter project.">
|
||||
|
||||
<!-- iOS meta tags & icons -->
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-title" content="battery_health">
|
||||
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/png" href="favicon.png"/>
|
||||
|
||||
<title>battery_health</title>
|
||||
<link rel="manifest" href="manifest.json">
|
||||
</head>
|
||||
<body>
|
||||
<script src="flutter_bootstrap.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,35 +0,0 @@
|
||||
{
|
||||
"name": "battery_health",
|
||||
"short_name": "battery_health",
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"background_color": "#0175C2",
|
||||
"theme_color": "#0175C2",
|
||||
"description": "A new Flutter project.",
|
||||
"orientation": "portrait-primary",
|
||||
"prefer_related_applications": false,
|
||||
"icons": [
|
||||
{
|
||||
"src": "icons/Icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-maskable-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-maskable-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||