Prepare 0.7.9 with decisive Dock tap transitions

This commit is contained in:
david1465833828
2026-10-28 19:37:04 +08:00
parent 23c1a58ca3
commit 8713bce0ee
9 changed files with 85 additions and 9 deletions
+2 -2
View File
@@ -1,10 +1,10 @@
# TPSchedule # TPSchedule
当前Android版本0.7.8+34:未选中灰色、选中蓝色,增强乳白透射与滑块对图标本身的折射,见[本次记录](docs/tpschedule-0.7.8-dock-symbol-optics.md)。构建33:修复缓存仍在但系统触发信息丢失时跳过提醒重建的问题,保留启动/暖启动恢复前的诊断;Android 16深度Doze及rare分组测试已实际投递,vivo几小时长待机根因仍待新诊断确认。见[本次记录](docs/tpschedule-0.7.8-reminder-idle.md)。构建32:点按先放大再弹跳、底座方向跟随、边缘外溢及柔软光泽,见[本次记录](docs/tpschedule-0.7.8-dock-bloom.md)。构建31提供滑块移动中持续Q弹、前缘牵拉和弹性跟随,玻璃材质减薄,见[本次记录](docs/tpschedule-0.7.8-dock-drag.md)。构建30提供增强点按挤压回弹、整条Dock随拖动方向弹动、图标到位动画及乳白折射光泽,见[本次记录](docs/tpschedule-0.7.8-dock-spring.md)。构建29提供Dock点按/拖动弹性与Android平板横竖屏、分屏适配,见[本次验证记录](docs/tpschedule-0.7.8-dock-tablet.md)。构建28已提前建立通知类别、区分通知总开关和类别状态,见[通知排查记录](docs/tpschedule-0.7.8-notification-permissions.md)。用户手机已通过开启通知权限并重测确认恢复后台通知。Dock乳白透光层和边缘折射继续保留,见[材质优化记录](docs/tpschedule-0.7.8-dock-refinement.md)。本科/研究生HTML反馈见[0.7.8功能记录](docs/tpschedule-0.7.8-validation.md)及[反馈服务说明](server/feedback/html-diagnostic-update.md),更新管理后台见[部署说明](server/updates/README.md)。 当前Android版本0.7.9+35:点按更快到位,缩短回弹和页面过渡,见[发布记录](docs/tpschedule-0.7.9-release.md)。构建34:未选中灰色、选中蓝色,增强乳白透射与滑块对图标本身的折射,见[本次记录](docs/tpschedule-0.7.8-dock-symbol-optics.md)。构建33:修复缓存仍在但系统触发信息丢失时跳过提醒重建的问题,保留启动/暖启动恢复前的诊断;Android 16深度Doze及rare分组测试已实际投递,vivo几小时长待机根因仍待新诊断确认。见[本次记录](docs/tpschedule-0.7.8-reminder-idle.md)。构建32:点按先放大再弹跳、底座方向跟随、边缘外溢及柔软光泽,见[本次记录](docs/tpschedule-0.7.8-dock-bloom.md)。构建31提供滑块移动中持续Q弹、前缘牵拉和弹性跟随,玻璃材质减薄,见[本次记录](docs/tpschedule-0.7.8-dock-drag.md)。构建30提供增强点按挤压回弹、整条Dock随拖动方向弹动、图标到位动画及乳白折射光泽,见[本次记录](docs/tpschedule-0.7.8-dock-spring.md)。构建29提供Dock点按/拖动弹性与Android平板横竖屏、分屏适配,见[本次验证记录](docs/tpschedule-0.7.8-dock-tablet.md)。构建28已提前建立通知类别、区分通知总开关和类别状态,见[通知排查记录](docs/tpschedule-0.7.8-notification-permissions.md)。用户手机已通过开启通知权限并重测确认恢复后台通知。Dock乳白透光层和边缘折射继续保留,见[材质优化记录](docs/tpschedule-0.7.8-dock-refinement.md)。本科/研究生HTML反馈见[0.7.8功能记录](docs/tpschedule-0.7.8-validation.md)及[反馈服务说明](server/feedback/html-diagnostic-update.md),更新管理后台见[部署说明](server/updates/README.md)。
0.7.0补充:考试页查询类型与卡片保持16像素间距;反馈问题和建议可自选附带最近10分钟的登录/读取/提醒诊断日志。默认不发送,不含密码、Cookie或课表内容,单独作为邮件文本附件。服务端需按[日志附件更新说明](server/feedback/diagnostic-log-update.md)手动更新;真实学校登录及SMTP未由本次离线测试代替验证。玻璃取样偏移仍在调查,未纳入本次修复结论。 0.7.0补充:考试页查询类型与卡片保持16像素间距;反馈问题和建议可自选附带最近10分钟的登录/读取/提醒诊断日志。默认不发送,不含密码、Cookie或课表内容,单独作为邮件文本附件。服务端需按[日志附件更新说明](server/feedback/diagnostic-log-update.md)手动更新;真实学校登录及SMTP未由本次离线测试代替验证。玻璃取样偏移仍在调查,未纳入本次修复结论。
学生课表 APP,Flutter 实现,支持电子科技大学研究生和本科生系统。Android 0.7.8+34,Android 7.0 及以上。 学生课表 APP,Flutter 实现,支持电子科技大学研究生和本科生系统。Android 0.7.9+35,Android 7.0 及以上。
使用用户提供的原始 SVG 图标,蓝色渐变、黄色日历框及白色笔画保持一致;启动画面使用相同配色。0.5.1修复重复启动页闪烁:初始化期间保留原生启动屏,数据就绪后直接显示课表首帧,不再叠加Flutter品牌页或淡出动画。Android12+ 原生启动屏使用同色纯蓝背景及图标,旧版采用蓝色渐变。 使用用户提供的原始 SVG 图标,蓝色渐变、黄色日历框及白色笔画保持一致;启动画面使用相同配色。0.5.1修复重复启动页闪烁:初始化期间保留原生启动屏,数据就绪后直接显示课表首帧,不再叠加Flutter品牌页或淡出动画。Android12+ 原生启动屏使用同色纯蓝背景及图标,旧版采用蓝色渐变。
+1 -1
View File
@@ -1,6 +1,6 @@
# Android 首版验证记录 # Android 首版验证记录
当前版本为0.7.8+34,灰蓝导航、乳白透射及图标折射见[本次记录](tpschedule-0.7.8-dock-symbol-optics.md)。构建33的提醒恢复与待机诊断见[本次记录](tpschedule-0.7.8-reminder-idle.md)。构建32的点按放大、外溢及柔软材质见[本次记录](tpschedule-0.7.8-dock-bloom.md)。构建31的移动中Q弹、牵拉及减薄见[本次记录](tpschedule-0.7.8-dock-drag.md)。构建30的点按/方向弹动及乳白材质见[本次记录](tpschedule-0.7.8-dock-spring.md)。构建29的Dock弹性与Android平板验证见[本次记录](tpschedule-0.7.8-dock-tablet.md)。构建28的通知权限恢复、通道初始化及真实后台触发见[通知记录](tpschedule-0.7.8-notification-permissions.md)。Dock乳白透光材质见[优化记录](tpschedule-0.7.8-dock-refinement.md)。本科/研究生HTML反馈及签名、备案信息见[0.7.8功能记录](tpschedule-0.7.8-validation.md)。应用更新检查与后台说明见[0.7.6记录](tpschedule-0.7.6-updates.md)。本科考试兼容的验证见[0.7.5记录](tpschedule-0.7.5-validation.md)。两例真实课表缺失字段问题待新页面定位。本科接入记录见[0.7.0记录](tpschedule-0.7.0-validation.md)。下文为首版历史记录。 当前版本为0.7.9+35,点按节奏及发布验证见[本次记录](tpschedule-0.7.9-release.md)。构建34的灰蓝导航、乳白透射及图标折射见[本次记录](tpschedule-0.7.8-dock-symbol-optics.md)。构建33的提醒恢复与待机诊断见[本次记录](tpschedule-0.7.8-reminder-idle.md)。构建32的点按放大、外溢及柔软材质见[本次记录](tpschedule-0.7.8-dock-bloom.md)。构建31的移动中Q弹、牵拉及减薄见[本次记录](tpschedule-0.7.8-dock-drag.md)。构建30的点按/方向弹动及乳白材质见[本次记录](tpschedule-0.7.8-dock-spring.md)。构建29的Dock弹性与Android平板验证见[本次记录](tpschedule-0.7.8-dock-tablet.md)。构建28的通知权限恢复、通道初始化及真实后台触发见[通知记录](tpschedule-0.7.8-notification-permissions.md)。Dock乳白透光材质见[优化记录](tpschedule-0.7.8-dock-refinement.md)。本科/研究生HTML反馈及签名、备案信息见[0.7.8功能记录](tpschedule-0.7.8-validation.md)。应用更新检查与后台说明见[0.7.6记录](tpschedule-0.7.6-updates.md)。本科考试兼容的验证见[0.7.5记录](tpschedule-0.7.5-validation.md)。两例真实课表缺失字段问题待新页面定位。本科接入记录见[0.7.0记录](tpschedule-0.7.0-validation.md)。下文为首版历史记录。
日期:2026-10-13。测试环境:Flutter 3.47.7 / Dart 3.13.5 / JDK 17;Android 16 API 36,Pixel 7 模拟器,1080×2400。首版版本 0.1.0+1,包 ID com.example.hepan_everyday,最低 Android 7.0(API 24)。 日期:2026-10-13。测试环境:Flutter 3.47.7 / Dart 3.13.5 / JDK 17;Android 16 API 36,Pixel 7 模拟器,1080×2400。首版版本 0.1.0+1,包 ID com.example.hepan_everyday,最低 Android 7.0(API 24)。
+26
View File
@@ -0,0 +1,26 @@
# TPSchedule 0.7.9 发布记录
日期:2026-10-28。Android 版本 0.7.9,构建号 35,包名 com.tpschedule.app。
## 本次调整
点按 Dock 时更快抵达目标,减少到位后的摆动:位置弹簧刚度/阻尼由 350/20 调整为 620/36,玻璃放大和回弹周期由 620ms 收短为 420ms。页面淡入/平移从 330ms 收短为 240ms。点按仍有轻微回弹,连续反向点按保持位置和尺寸连续。
拖动弹簧、持续 Q 弹、方向牵拉、按住放大、图标到位动画、乳白材质、图标折射和灰蓝选中状态沿用上一版。保留 Android 平板适配及构建 33 的提醒恢复/诊断改进。vivo 几小时待机漏提醒尚未确认彻底解决,不将它写为已修复的发布承诺。
## 验证
- Flutter 全量 331 项测试通过;静态分析无问题;正式 APK 构建通过。
- 新增速度回归:点按 160ms 时滑块已接近目标;480ms 时额外光学层退出、尺寸和位置恢复。
- 新增页面回归:240ms 加一帧以内旧页退出,重新切回保留 TextField 内部编辑状态。以旧 330ms 配置复核失败,新配置通过。
- 既有快速反向点按、边缘外溢、拖动牵拉、光学像素和减少动态效果测试通过。
- 独立审查未发现需要修复的缺陷;查看实际 Flutter 渲染的点按和拖动序列。未新增真机性能结论。
- APK 证书与上一版逐字节核对,MD5 保持 78 DE 91 19 AD 14 72 7F A1 C5 E5 E4 E6 81 45 EE,公钥模数、原私钥、备案号及 18 项登记冻结材料保持。
## 发布
安装包为 TPSchedule-0.7.9.apk,源码为 TPSchedule-0.7.9-source.zip。使用同签名覆盖安装。旧 APK 与旧源码包保持原文件。
更新后台 https://app.glowtps.cn/update 填写版本 0.7.9、构建号 35,上传本次 APK 到已有文件托管处后,将真实公开 HTTPS 下载链接填入后台。无需更新服务端代码。发布说明见安装包旁的 TPSchedule-0.7.9-更新发布说明.md。
本地已准备发布产物,未访问服务器执行上传或修改线上发布记录。
+2 -2
View File
@@ -1,3 +1,3 @@
const appVersion = '0.7.8'; const appVersion = '0.7.9';
const appBuildNumber = 34; const appBuildNumber = 35;
const appFilingNumber = '蜀ICP备2025169276号-5A'; const appFilingNumber = '蜀ICP备2025169276号-5A';
+2 -2
View File
@@ -35,7 +35,7 @@ class _GlassDockState extends State<GlassDock> with TickerProviderStateMixin {
); );
late final AnimationController _tap = AnimationController( late final AnimationController _tap = AnimationController(
vsync: this, vsync: this,
duration: const Duration(milliseconds: 620), duration: const Duration(milliseconds: 420),
); );
late final AnimationController _sway = AnimationController.unbounded( late final AnimationController _sway = AnimationController.unbounded(
vsync: this, vsync: this,
@@ -212,7 +212,7 @@ class _GlassDockState extends State<GlassDock> with TickerProviderStateMixin {
_motion.animateWith( _motion.animateWith(
SpringSimulation( SpringSimulation(
springyTap springyTap
? const SpringDescription(mass: 1, stiffness: 350, damping: 20) ? const SpringDescription(mass: 1, stiffness: 620, damping: 36)
: const SpringDescription(mass: 1, stiffness: 360, damping: 26), : const SpringDescription(mass: 1, stiffness: 360, damping: 26),
_position, _position,
index.toDouble(), index.toDouble(),
+1 -1
View File
@@ -12,7 +12,7 @@ class TabDeck extends StatefulWidget {
class _TabDeckState extends State<TabDeck> with SingleTickerProviderStateMixin { class _TabDeckState extends State<TabDeck> with SingleTickerProviderStateMixin {
late final AnimationController _motion = AnimationController( late final AnimationController _motion = AnimationController(
vsync: this, vsync: this,
duration: const Duration(milliseconds: 330), duration: const Duration(milliseconds: 240),
value: 1, value: 1,
); );
int? _outgoing; int? _outgoing;
+1 -1
View File
@@ -1,7 +1,7 @@
name: hepan_everyday name: hepan_everyday
description: TPSchedule 学生课表 description: TPSchedule 学生课表
publish_to: none publish_to: none
version: 0.7.8+34 version: 0.7.9+35
environment: environment:
sdk: ^3.13.5 sdk: ^3.13.5
dependencies: dependencies:
+24
View File
@@ -11,6 +11,30 @@ import 'navigation_test.dart' show uiController;
void main() { void main() {
setUpAll(tzdata.initializeTimeZones); setUpAll(tzdata.initializeTimeZones);
testWidgets(
'tap reaches its page promptly and finishes the glass pulse within 480ms',
(tester) async {
await tester.pumpWidget(_dock());
await tester.pumpAndSettle();
final lens = find.byType(GlassRefraction).last;
final rest = tester.getSize(lens);
final target = tester.getCenter(find.byIcon(Icons.assignment_rounded)).dx;
await tester.tap(find.byIcon(Icons.assignment_rounded));
await tester.pump();
await tester.pump(const Duration(milliseconds: 160));
expect((tester.getCenter(lens).dx - target).abs(), lessThan(7));
for (var i = 0; i < 20; i++) {
await tester.pump(const Duration(milliseconds: 16));
}
expect(
find.byKey(const ValueKey('dock-symbol-refraction')),
findsNothing,
);
expect(tester.getSize(lens).width, closeTo(rest.width, 0.5));
expect(tester.getCenter(lens).dx, closeTo(target, 0.6));
await tester.pumpAndSettle();
},
);
testWidgets( testWidgets(
'moving lens refracts symbols above the icon row and releases cleanly', 'moving lens refracts symbols above the icon row and releases cleanly',
(tester) async { (tester) async {
+26
View File
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:hepan_everyday/widgets/glass_dock.dart'; import 'package:hepan_everyday/widgets/glass_dock.dart';
import 'package:hepan_everyday/widgets/tab_deck.dart';
import 'package:hepan_everyday/app/hepan_app.dart'; import 'package:hepan_everyday/app/hepan_app.dart';
import 'package:hepan_everyday/features/timetable/timetable_page.dart'; import 'package:hepan_everyday/features/timetable/timetable_page.dart';
import 'package:timezone/data/latest.dart' as tzdata; import 'package:timezone/data/latest.dart' as tzdata;
@@ -9,6 +10,31 @@ import 'navigation_test.dart' show uiController;
void main() { void main() {
setUpAll(tzdata.initializeTimeZones); setUpAll(tzdata.initializeTimeZones);
testWidgets(
'tab content finishes within one frame of 240ms and retains page state',
(tester) async {
Widget deck(int index) => MaterialApp(
home: Scaffold(
body: TabDeck(
index: index,
children: const [TextField(), Text('新页面')],
),
),
);
await tester.pumpWidget(deck(0));
await tester.enterText(find.byType(TextField), '保留内容');
FocusManager.instance.primaryFocus?.unfocus();
await tester.pumpWidget(deck(1));
await tester.pump(); // Start the transition clock before advancing it.
await tester.pump(const Duration(milliseconds: 240));
await tester.pump(const Duration(milliseconds: 16));
expect(find.byType(TextField), findsNothing);
expect(find.text('新页面'), findsOneWidget);
await tester.pumpWidget(deck(0));
await tester.pumpAndSettle();
expect(find.text('保留内容'), findsOneWidget);
},
);
testWidgets('only the selected tab is blue, including during glass travel', ( testWidgets('only the selected tab is blue, including during glass travel', (
tester, tester,
) async { ) async {