| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
收紧(工程化): lint 收紧至 strict-casts/strict-raw-types + 40 条扩展规则并全量清零,analyze --fatal-infos 门禁,CJK 硬编码审计棘轮接入 CI——analysis_options 启用 use_build_context_synchronously/cancel_subscriptions/avoid_print 等正确性规则与风格集(dart fix 批量修 1432 处 + 手工修 14 error/17 warning),两个高噪音规则 cascade_invocations(127)/discarded_futures(195) 注释保留待第二批;CI/安卓构建 analyze 收紧为 --fatal-infos 防劣化;audit_cjk_hardcode.py 新增 --baseline 棘轮模式(回归失败/改进自动下调),基线 68 文件 1070 行入库,CI 新增 CJK hardcode audit 步骤;附带 strict_raw_type 显式泛型、lan_edit_api_handlers ArgumentError.message 类型收窄、avoid_slow_async_io 24 处 exists()→existsSync()。flutter analyze 0 issues,services/providers/architecture/models/domain/utils/logging/data 测试全绿(壁纸 7 例失败为主分支既有,与本批无关)。 | 1 个月前 | |
HyperOS 矮高度圆角与冲突/排课 UI 对齐 库侧新增自适应圆角与表面半径作用域,修复单行卡片胶囊圆角、选择行偏上与按压高亮不一致;课程总览冲突入口简化、排课冲突导航行与关于说明字号对齐;同步文案句号清理与 v2.0.8 更新日志。 | 2 个月前 | |
收紧(工程化): lint 收紧至 strict-casts/strict-raw-types + 40 条扩展规则并全量清零,analyze --fatal-infos 门禁,CJK 硬编码审计棘轮接入 CI——analysis_options 启用 use_build_context_synchronously/cancel_subscriptions/avoid_print 等正确性规则与风格集(dart fix 批量修 1432 处 + 手工修 14 error/17 warning),两个高噪音规则 cascade_invocations(127)/discarded_futures(195) 注释保留待第二批;CI/安卓构建 analyze 收紧为 --fatal-infos 防劣化;audit_cjk_hardcode.py 新增 --baseline 棘轮模式(回归失败/改进自动下调),基线 68 文件 1070 行入库,CI 新增 CJK hardcode audit 步骤;附带 strict_raw_type 显式泛型、lan_edit_api_handlers ArgumentError.message 类型收窄、avoid_slow_async_io 24 处 exists()→existsSync()。flutter analyze 0 issues,services/providers/architecture/models/domain/utils/logging/data 测试全绿(壁纸 7 例失败为主分支既有,与本批无关)。 | 1 个月前 | |
feat(ui): polish HyperOS kit, splash screen, and settings layouts Refine HyperOS controls, page navigation, overscroll, and frosted blur across timetable, settings, import, and about flows; add Android 12+ splash layer drawable and expand related widget tests. Co-authored-by: Cursor <cursoragent@cursor.com> | 2 个月前 | |
恢复 BlackBox 调试监测并保留 HyperOS 调参面板 | 2 个月前 | |
fix(log): 并发初始化改共享 Future,修复启动窗口日志被静默丢弃 6c79e301 用「同步置位 _initialized」防重入,消除了重复的 app_logger_initialized,但代价是窗口期并发日志在开关加载前 就被 _shouldRecord 撞默认值丢弃(×3 并发时其中 2 条启动日志 丢失)。改为 _initFuture ??= _doInitialize() 共享同一初始化 Future:并发触发只跑一次(仍去重),窗口期日志等待初始化完 成、按已加载开关正常落盘。置位点移到自证事件之前,避免 debug() 递归等待自身 Future 死锁;resetForTesting 同步重置。 新增竞态回归测试:两条 info() 与初始化并发触发,修前 entry-b 被丢(红),修后全部落盘(绿)。 | 28 天前 | |
feat(ui): polish HyperOS kit, splash screen, and settings layouts Refine HyperOS controls, page navigation, overscroll, and frosted blur across timetable, settings, import, and about flows; add Android 12+ splash layer drawable and expand related widget tests. Co-authored-by: Cursor <cursoragent@cursor.com> | 2 个月前 | |
修复(云同步): 首次同步分歧不再把新用户吓退——手动「立即同步」遇云端已有数据时弹「检测到同步冲突」且文案宣称本机也有新的修改,用户看不懂反复点取消,只能瞎试出「先立即备份再同步」的绕路(用户实测反馈)。三处收口:①手动拉取冲突补上后台路径已有的空本机豁免(resolveManualPullConflictChoice:本机无用户数据时跳过弹窗直接以云端为准,对齐 webdavBackgroundPullShouldCancel 口径),全新设备/空壳快照不再被选边框拦截;②SyncConflictInfo 增加 isFirstSyncDivergence/localHasUserData 字段(带默认值),弹窗按首次分歧切换解释性文案「本机与云端数据不一致」+写明保留本机/使用云端各自后果(3 新串同步 6 arb);③冲突弹窗取消后的 toast 升级为可点 action「以本机为准备份」直达手动备份(复用 createManualBackup 锚定基线,即用户误打误撞发现的正解)。保护语义不动:先拉后传顺序、force 仅限手动、断开清基线后重连触发冲突均为刻意设计。flutter analyze 0 issues;同步相关 4 测试文件 49 例全绿(新增 3 例)。 | 28 天前 | |
修复(CJK审计): GitCode 渠道新增日志改英文键、对比卡列定义行尾注释改整行——app_update_service 42→35 回到基线(053c220a 先例),profile_compare_card 新文件 4→0;同时移除发版权限探针临时 workflow(诊断完成:GITHUB_TOKEN 建站权限已恢复,tag 流水线重跑验证中) | 1 个月前 | |
把 App 图标加回启动预热:分享图 logo 空白的另一半根因 上一版的「出图前等图片解码」只能等已经在树上的 Image,而品牌条里的 logo 走 BundledAssetImage:字节没预热时它首帧只是个空占位盒,遍历时一张图都收集不到, precache 空转——所以 logo 照样空白。 图标曾在 7b49e35c 被移出预热清单,那是因为当时只为已删除的启动品牌层预读; 品牌条同样需要它,加回。预热后品牌条首帧就是 Image.memory,两段修复才闭环。 顺带在 ImageExportCapture 类注释里写明「文档用的图必须建树首帧可解析」这条约束。 | 18 天前 | |
修复(日历同步): 清空与写入合并成一次批处理(失败不再丢已同步日程);权限申请改排队扇出,修连点后 Future 永挂 三个病根各自独立,都在「同步到系统日历」这条链路上: 1) 旧版先 resolver.delete 清空、成功后再另开一批 applyBatch 插入。insert 失败时清空已经提交且无回滚,用户之前同步好的日程被清没。改为 buildSyncOps 先构造完整批次(首条恒为清空 + N 条合法插入),同一次 applyBatch 提交 —— ContentProvider 批处理是事务,中途失败整批回滚。 批次抽成纯数据 SyncOp 列表,落库前才转 ContentProviderOperation, 使「清空与写入必须同批」这条规则能在 JVM 单测里断言。 2) 权限申请只有单个 pendingPermissionResult 槽位,连点两次按钮第二次会 覆盖第一次的 Result,Dart 侧第一个 Future 永挂。改为 PermissionRequestQueue 排队 + 单弹窗扇出:首个等待者触发系统弹窗,后来的只排队,complete 一次 把全部等待者按同一结果收束。 3) activity == null 之外补判 isFinishing / isDestroyed(销毁中的 Activity 照样 requestPermissions,回调可能永远不来);新增 onHostDestroyed() 由 MainActivity.onDestroy() 调用,把还没等到结果的等待者按未授权收束。 测试:新增 android/app/src/test/kotlin/.../CalendarSyncLogicTest.kt(8 例纯 逻辑单测,无需设备);Dart 侧补 1 例「连点两次都要 await 到结果」回归钉。 验证:flutter analyze 3 个改动文件 0 issue;calendar_sync_service_test.dart 与 liquid_glass_surface_test.dart 共 31 例全绿; gradlew :app:compileDevDebugUnitTestKotlin 编译通过。 | 12 天前 | |
feat(reminder): 单节课提醒数据模型与调度底座 | 1 个月前 | |
收紧(工程化): lint 收紧至 strict-casts/strict-raw-types + 40 条扩展规则并全量清零,analyze --fatal-infos 门禁,CJK 硬编码审计棘轮接入 CI——analysis_options 启用 use_build_context_synchronously/cancel_subscriptions/avoid_print 等正确性规则与风格集(dart fix 批量修 1432 处 + 手工修 14 error/17 warning),两个高噪音规则 cascade_invocations(127)/discarded_futures(195) 注释保留待第二批;CI/安卓构建 analyze 收紧为 --fatal-infos 防劣化;audit_cjk_hardcode.py 新增 --baseline 棘轮模式(回归失败/改进自动下调),基线 68 文件 1070 行入库,CI 新增 CJK hardcode audit 步骤;附带 strict_raw_type 显式泛型、lan_edit_api_handlers ArgumentError.message 类型收窄、avoid_slow_async_io 24 处 exists()→existsSync()。flutter analyze 0 issues,services/providers/architecture/models/domain/utils/logging/data 测试全绿(壁纸 7 例失败为主分支既有,与本批无关)。 | 1 个月前 | |
fix(import): 硬化教务导入与冲突/情侣同步语义 覆盖导入清空日程;冲突按实际周判断;Bridge requestId 消毒;仓库脚本官方源优先;情侣 WebDAV 双槽位;周表达式括号奇偶收窄。 | 2 个月前 | |
修复: prefer_initializing_formals 误改公开构造函数签名致库外按名传参编译失败——5 处 this._私有字段改回可选参数+?? 兜底(timetable_provider.enableLiveActivitySync 测试 84 处、app_update_service.releaseApiRequestTimeout、warehouse_import_preferences_service.secureStorage 测试 2 处、couple/webdav_sync_credentials_store.storage DI 能力),保留公开参数名。flutter analyze 0 issues,services/providers/architecture/data/utils/logging/models/domain 测试全绿 | 1 个月前 | |
feat(MUT-27,MUT-36,MUT-54): commit completed schedule task and transfer work | 1 个月前 | |
功能(课表配色): 导入后随时一键重刷全课表颜色的核心管线——课程不再只能靠重新导入换色。新增 course_recolor.dart 纯逻辑层: 重刷分组键改按共享课程名(与课程组编辑页同口径,维持「同名同色」不变式,不再沿用导入期的 name+teacher 键)、固定种子批次(同种子同课程列表逐色一致,是「切回上一套」的确定性基础)、导入原色快照记录(逐组存 color/textColor,含手工挑过的颜色,永远有路可回);applyRandomImportCourseColors 增加 groupKeyBuilder 可选参(默认不变,导入路径零影响)。新增按课表 profile 作用域隔离的方案历史持久化服务(种子/快照两类记录+导航指向,上限 20 套丢最旧并同步前移指向,坏 JSON/坏记录兜底)。TimetableProvider 新增 applyCourseRecolors 按 id 对位覆盖 color/textColor 并持久化+通知+更新桌面部件,无变化返回 0 不通知,其余字段不动。测试: 同名同色/种子确定性/文字色开关/深色组生效/快照往返含新课程保色/JSON 往返与坏数据、历史往返/作用域隔离/超限前移/坏数据跳过、provider 覆盖与持久化重读共 21 项 | 1 个月前 | |
收紧(工程化): lint 收紧至 strict-casts/strict-raw-types + 40 条扩展规则并全量清零,analyze --fatal-infos 门禁,CJK 硬编码审计棘轮接入 CI——analysis_options 启用 use_build_context_synchronously/cancel_subscriptions/avoid_print 等正确性规则与风格集(dart fix 批量修 1432 处 + 手工修 14 error/17 warning),两个高噪音规则 cascade_invocations(127)/discarded_futures(195) 注释保留待第二批;CI/安卓构建 analyze 收紧为 --fatal-infos 防劣化;audit_cjk_hardcode.py 新增 --baseline 棘轮模式(回归失败/改进自动下调),基线 68 文件 1070 行入库,CI 新增 CJK hardcode audit 步骤;附带 strict_raw_type 显式泛型、lan_edit_api_handlers ArgumentError.message 类型收窄、avoid_slow_async_io 24 处 exists()→existsSync()。flutter analyze 0 issues,services/providers/architecture/models/domain/utils/logging/data 测试全绿(壁纸 7 例失败为主分支既有,与本批无关)。 | 1 个月前 | |
收紧(工程化): lint 收紧至 strict-casts/strict-raw-types + 40 条扩展规则并全量清零,analyze --fatal-infos 门禁,CJK 硬编码审计棘轮接入 CI——analysis_options 启用 use_build_context_synchronously/cancel_subscriptions/avoid_print 等正确性规则与风格集(dart fix 批量修 1432 处 + 手工修 14 error/17 warning),两个高噪音规则 cascade_invocations(127)/discarded_futures(195) 注释保留待第二批;CI/安卓构建 analyze 收紧为 --fatal-infos 防劣化;audit_cjk_hardcode.py 新增 --baseline 棘轮模式(回归失败/改进自动下调),基线 68 文件 1070 行入库,CI 新增 CJK hardcode audit 步骤;附带 strict_raw_type 显式泛型、lan_edit_api_handlers ArgumentError.message 类型收窄、avoid_slow_async_io 24 处 exists()→existsSync()。flutter analyze 0 issues,services/providers/architecture/models/domain/utils/logging/data 测试全绿(壁纸 7 例失败为主分支既有,与本批无关)。 | 1 个月前 | |
新增 debug 深链与真机 QA 脚本,修复深链误走导入与未知路由断言 | 2 个月前 | |
接入(天气): Dart 侧接上原生定位通道,拿不到就退 IP 估算并如实标注 上一提交(5834e945)只加了 Kotlin 通道,Dart 侧还在走 geolocator,所以真机仍然 「转圈到失败」。这次把 Dart 侧接上,并补上用户拍板的 IP 估算兜底。 - device_location_service.dart 重写取位置那一段: · DeviceLocationSource 的第四个方法从 getCurrentPosition(LocationSettings) / getLastKnownPosition() 收敛成一个 getCurrentFix() → DeviceFix?。坐标有多个 来源(原生通道 / geolocator 兜底 / 原生内部缓存),用同一个轻量值类型收敛, 测试里造假件不必凑齐 Position 的十个字段。 · NativeDeviceLocationSource 调原生通道;**只有通道本身故障**(未注册 / 解码 失败)才兜底 geolocator,且只兜一次——null 是「没拿到」这个正常结果,不能 在 Dart 侧再等一轮,否则预算翻倍(12 秒 + 12 秒)。 · 顺序:权限/开关 → 实时定位(原生通道:网络优先、12 秒总预算、内部缓存兜底) → 网络 IP 估算 → 才失败。上一版把「系统缓存」放最前当首选,方向错了:用户 点「使用当前位置」要的是现在在哪,缓存只该在前面的实时定位拿不到时兜底, 否则换了城市仍会停在旧定位。lastKnownMaxAge 那套缓存策略整段删除。 · 估算只在实时定位返回 null 时走;实时定位**抛异常**不走估算——异常是流程坏了, 再悄悄估算一次会把真正的故障盖掉。同理「有坐标但反查失败」也不退化成估算。 · timeout 的含义随之变为「实时定位与估算都没拿到可用位置」。 - weather_service.dart:BigDataCloud 的 reverse-geocode-client 不带坐标时就是 IP 定位,所以 networkGeocode() 与 reverseGeocode 共用同一个接口和 _parseLocation 解析,只是不传 latitude/longitude。零新增依赖、零新增数据源。 - 估算结果必须如实标注,不许冒充真实定位: DeviceLocationOutcome.estimated → WeatherProvider.lastLocateWasEstimated → 两处界面成功后多弹一句 weatherLocationEstimated(六语言)。 - 测试跟上新契约: · helpers_location_stub.dart 的假件只暴露 fix(null = 拿不到)、estimatesTo 与 delay;positionCalls 改名 fixCalls。 · device_location_service_test.dart 重写:删掉 6 条「系统缓存优先」用例(缓存 策略已不在 Dart 侧),补三条「不该走的路」——实时定位成功时不发 IP 估算请求、 通道抛异常时不退到估算、有坐标但反查失败时不退到估算。 · 两个页面测试各加一对估算提示用例:真实定位成功时 findsNothing(对照组), 实时定位拿不到时 findsOneWidget。只测「估算时出现」的话,把 estimated 写死 成 true 也能通过,那样提示就变成狼来了。 验证:flutter analyze 全仓无 issue;上述五个测试文件 16 + 36 + 34 + 121 + 5 全绿; CJK 硬编码棘轮与三条笔记校验脚本均通过。原生通道本身尚未在真机上跑过(本机跑不了 安卓构建),首次真机测试要看 weather_location_ok 里的 source 与 elapsedMs。 | 16 天前 | |
重构(日志页): 应用日志查看页回归纯阅读器——记录开关+折叠「查看与排序」卡住在头部扩展区撑掉大半屏,且扩展区高度一变 body 顶部测量缓存 inset 跟不上,收起后留出一大片空白;头部扩展区只留恒定高度的等级筛选条(chips 自带计数,删除冗余「显示 x/y」行),查看/排序收进应用栏 tune 弹层(对齐 talker 3.x 取消筛选面板改内联的方向),「记录应用日志」开关迁往「设置→诊断与日志」(开关是配置、查看页只阅读,配置类开关不受该页「功能入口不收」原则限制),记录关闭时列表顶保留一行历史日志提示;删除随之失效的折叠态持久化,测试补「开关不得回到本页」回归锚点 | 1 个月前 | |
feat(reminder): 单节课提醒数据模型与调度底座 | 1 个月前 | |
修复作息规则与地点匹配体验 | 2 个月前 | |
收紧(工程化): lint 收紧至 strict-casts/strict-raw-types + 40 条扩展规则并全量清零,analyze --fatal-infos 门禁,CJK 硬编码审计棘轮接入 CI——analysis_options 启用 use_build_context_synchronously/cancel_subscriptions/avoid_print 等正确性规则与风格集(dart fix 批量修 1432 处 + 手工修 14 error/17 warning),两个高噪音规则 cascade_invocations(127)/discarded_futures(195) 注释保留待第二批;CI/安卓构建 analyze 收紧为 --fatal-infos 防劣化;audit_cjk_hardcode.py 新增 --baseline 棘轮模式(回归失败/改进自动下调),基线 68 文件 1070 行入库,CI 新增 CJK hardcode audit 步骤;附带 strict_raw_type 显式泛型、lan_edit_api_handlers ArgumentError.message 类型收窄、avoid_slow_async_io 24 处 exists()→existsSync()。flutter analyze 0 issues,services/providers/architecture/models/domain/utils/logging/data 测试全绿(壁纸 7 例失败为主分支既有,与本批无关)。 | 1 个月前 | |
fix: 落实 PR #45 评审收尾——CJK 棘轮基线补齐、无用 import 清除与可观测性一致性修复 - tool/cjk_hardcode_baseline.txt: 补 app_sync_snapshot_service 1→2、新增 webdav_sync_service:1,修复 CJK 棘轮门禁必红的阻塞项(实测 audit --baseline exit 0) - webdav_sync_service: 移除未使用的 flutter/foundation import(CI --fatal-infos 下 unused_import 会挂) - live_settings_subpages: 图片清理失败告警从 assert(debugPrint) 改为 AppLogService.warn(英文文案不触发棘轮)+ 自兜底,release 可观测 - app_log_service: 连续写失败告警 == 改 % 取模节流,长磁盘满故障不再永久静默 - holiday_service: 后台刷新 catchError 内 warn 加自兜底,与其余失败路径一致 - settings_holiday: 保存/删除 catch 从 HolidayCustomSaveException 放宽到 Object,任何异常不得伪装成保存成功;技术详情落日志,用户只见本地化文案 | 1 个月前 | |
功能(桌面卡片-情侣绑定): 各卡片绑定管理新增「情侣课表」合并视图。绑定哨兵 couple-merged(虚拟视图,非真实课表):快照=我的当前课表+TA 课表按周偏移映射合并,同行程(同时段同名)按我的那份去重(与 App 内情侣覆盖层同口径),全部按情侣三色(我/TA/一起)着色;学期/节假日/考试/外观锚定我方。点击分流与 TA 绑定一致→打开情侣覆盖层;TA 解绑/被删回落「跟随当前课表」。TA 导入/周偏移/三色/解绑后立即重推绑定卡片专属快照(跳过 scheduleSnapshot)。绑定页在已导入 TA 课时同时提供「情侣课表」与「TA的课表」选项,6 语言文案。新增路由分流 2 例、合并快照 4 例、绑定页选项 1 例测试;analyze 0 issues,相关 33 测试通过。 | 25 天前 | |
fix: 授权后重排小组件刷新并区分授权页跳转结果反馈 | 1 个月前 | |
feat(小组件): 课程色贯穿(色条 + 课程名/状态文字)并给三档总开关 Issue #28 定案的「色条管识别、字色管贯穿」,加一个用户能一键回到旧观感的开关。 ## 渲染 - 今日六个卡型(2×2 主卡 / 2×2 迷你列表 / 2×4 / 4×4 / 4×1 横条 / 4×2 横宽卡) 在课程名前加课程色竖条:3dp 宽、圆角、高度随行,用白名单 LinearLayout 承载(部分 ROM 的 RemoteViews 拒载裸 View/Space,会静默不画)。 - 课程名与状态胶囊文字换成课程色的可读版本;胶囊底色/圆角与描边不动, 时间、地点、周数、倒计时等次要信息保持中性灰。 - 渐变背景例外:主标题保持白字(5.17~5.56:1),只加色条——换成课程色 最坏只有 3.27:1,为「贯穿」把主标题对比度砍半不划算。 ## 颜色算法(钳相对亮度 Y,不钳 HSL 的 L) WCAG 对比度算的是 Y = 0.2126R'+0.7152G'+0.0722B',绿色通道占 71.5%、蓝色 只占 7.2%。同一个 HSL 的 L 在不同色相下实际亮度差三倍以上:L=0.55 的黄绿 接近白、同 L 的蓝紫接近黑。所以「把 L 压到某值」在冷色区等于没做、暖色区 压过头。这里在 Y 上钳制再二分反解 L,色相与饱和度全程不动。 钳制是单向的:浅卡只压暗、深卡只提亮,绝不反向把颜色拉回带内——双向钳制 会把浅卡上的深色课程提亮,那正好朝底色靠(#334155 被提亮后对 #F8FAFC 只有 5.4:1,原色 10.4:1)。 实测 104 色全色板:浅底色条最低 3.17:1、渐变底 3.40:1、深底色条 4.85:1; 浅底文字对胶囊底最低 5.79:1(现状固定灰字 #64748B 仅 3.94:1);色相漂移 0.00°。 ## 开关(用户要求:能回到之前的样式,或只开条) 一个三档总开关,不是多个独立开关——「回到之前的样子」必须一次点到位: - 关闭:色条与文字全不渲染,回到加色前配色 - 仅色条:只加竖条,文字保持中性色 - 色条 + 文字:完整贯穿(默认) ## 数据通路(两条都要改,否则 90% 的卡片没颜色) Kotlin 的实时计算通路是主力,但 WidgetSourceCourse 此前根本没有 color 字段。 四处补齐:WidgetSourceCourse.color + parseSourceCourses 读 optString("color") + toWidgetCourseInfo 带上 + parseCourse 兼容老快照;档位字段双写(profile settings 的 widgetCourseAccentMode + 快照的 courseAccentMode),两条通路行为 一致,不会出现「设置页关了、桌面还彩色」。 ## 兜底 课程色字段归一 sanitizeColorField:空/"null"/长度不符一律空串,渲染侧约定 空串 = 无课程色(不画条、文字回落中性色),老备份与第三方数据源天然安全。 ## 测试 - 新增 lib/utils/widget_course_accent.dart 纯函数 + test/utils/ 覆盖全色板 (对比度、单向性、色相漂移、缺色兜底),15 例。 - Kotlin 侧 CourseWidgetAccent.kt 同公式,android/app/src/test 覆盖同款断言 13 例(CI 的 gradle-jvm-tests 会跑)。 - 补快照透传、设置档位往返、settings_reset 恢复默认三组回归。 - 六语言 l10n 同步(zh/zh-HK/zh-TW/en/ja/ko)。 ## 版本 v2.1.1.8 已 tag,按 docs/RELEASE.md「已发版禁止追加」写入下一版 docs/releases/v2.1.1.9.md,pubspec 2.1.1-9+131,changelog 回退列表补齐。 flutter analyze 0 issues;flutter test 1694 例全绿;hyperos 审计 strict 通过; CJK 硬编码审计与基线持平;Kotlin 全量编译通过 + JVM 单测 13/18 通过。 | 26 天前 | |
feat(ics): 一键同步课表到系统日历(ICS 导出页新增入口) ICS 导出页新增「同步到系统日历」:在系统日历里创建专属日历 「轻屿课表·{课表名}」,把当前所选时间范围的日程写进去;再次同步覆盖上次 写入的日程。假期中的课程默认不写(沿用「跳过节假日课程」开关),首次同步 请求日历读写权限(不随启动索取)。 - Android 侧新增 CalendarSync.kt:MethodChannel 读写专属本地日历 + 运行时权限申请,MainActivity 注册通道与权限回调,Manifest 声明 READ_CALENDAR / WRITE_CALENDAR。 - Dart 侧新增 CalendarSyncService 封装通道调用;ics_export_service 增加 同步所需的日程构造与覆盖写入。 - l10n 11 个文件补同步弹窗文案(确认/标题/正文/日历名,6 语言)。 注:本批 l10n 同时带上一个材质标签键 liquidGlassDispersionLabel(「色散」), 它与下面的玻璃改动同批产出,无法按文件拆开,随本次一并入库。 - 测试:calendar_sync_service_test(新)、ics_export_screen_sync_test(新)、 ics_export_service_test、ics_export_screen_test。 | 14 天前 | |
重构(领域层): 三个 service 重复的 _startOfWeek 收口到 WeekCalculator——ics_import/import_week_alignment/unified_transfer 各删一份私有实现,行为不变(阶段1 WeekCalculator 收尾) | 1 个月前 | |
把 App 图标加回启动预热:分享图 logo 空白的另一半根因 上一版的「出图前等图片解码」只能等已经在树上的 Image,而品牌条里的 logo 走 BundledAssetImage:字节没预热时它首帧只是个空占位盒,遍历时一张图都收集不到, precache 空转——所以 logo 照样空白。 图标曾在 7b49e35c 被移出预热清单,那是因为当时只为已删除的启动品牌层预读; 品牌条同样需要它,加回。预热后品牌条首帧就是 Image.memory,两段修复才闭环。 顺带在 ImageExportCapture 类注释里写明「文档用的图必须建树首帧可解析」这条约束。 | 18 天前 | |
功能(并行改动收编): 导入课程随机配色按组选择(马卡龙/活泼/深色系分组+偏好存储+导入页选择器+测试)、上课前快捷动作自动执行与直播更新调度(Android)——并行会话未提交快照整体入库,分析零错误 | 1 个月前 | |
重构(领域层): 三个 service 重复的 _startOfWeek 收口到 WeekCalculator——ics_import/import_week_alignment/unified_transfer 各删一份私有实现,行为不变(阶段1 WeekCalculator 收尾) | 1 个月前 | |
收紧(工程化): lint 收紧至 strict-casts/strict-raw-types + 40 条扩展规则并全量清零,analyze --fatal-infos 门禁,CJK 硬编码审计棘轮接入 CI——analysis_options 启用 use_build_context_synchronously/cancel_subscriptions/avoid_print 等正确性规则与风格集(dart fix 批量修 1432 处 + 手工修 14 error/17 warning),两个高噪音规则 cascade_invocations(127)/discarded_futures(195) 注释保留待第二批;CI/安卓构建 analyze 收紧为 --fatal-infos 防劣化;audit_cjk_hardcode.py 新增 --baseline 棘轮模式(回归失败/改进自动下调),基线 68 文件 1070 行入库,CI 新增 CJK hardcode audit 步骤;附带 strict_raw_type 显式泛型、lan_edit_api_handlers ArgumentError.message 类型收窄、avoid_slow_async_io 24 处 exists()→existsSync()。flutter analyze 0 issues,services/providers/architecture/models/domain/utils/logging/data 测试全绿(壁纸 7 例失败为主分支既有,与本批无关)。 | 1 个月前 | |
新增局域网浏览器编辑课表及 Android 前台保活 Co-authored-by: Cursor <cursoragent@cursor.com> | 3 个月前 | |
完善局域网 Web 控制台与表格导入(路线图 P0–P2) - LAN API:表格导入、周次表达式解析、合并备份、批量删课、同步当前周 - Web:表格/合并导入、周次表达式编辑、课程库批量删除、离线字体 - App:LanEditScreen 连接二维码(qr_flutter)、前台服务与 MainActivity 调整 - 表格导入与周次解析加固及 xlsx 测试夹具 - 文档:2026-06-29-lan-edit-web-roadmap.md | 3 个月前 | |
feat: 统一迁移入口并接入预览撤销流程 | 1 个月前 | |
收紧(工程化): lint 收紧至 strict-casts/strict-raw-types + 40 条扩展规则并全量清零,analyze --fatal-infos 门禁,CJK 硬编码审计棘轮接入 CI——analysis_options 启用 use_build_context_synchronously/cancel_subscriptions/avoid_print 等正确性规则与风格集(dart fix 批量修 1432 处 + 手工修 14 error/17 warning),两个高噪音规则 cascade_invocations(127)/discarded_futures(195) 注释保留待第二批;CI/安卓构建 analyze 收紧为 --fatal-infos 防劣化;audit_cjk_hardcode.py 新增 --baseline 棘轮模式(回归失败/改进自动下调),基线 68 文件 1070 行入库,CI 新增 CJK hardcode audit 步骤;附带 strict_raw_type 显式泛型、lan_edit_api_handlers ArgumentError.message 类型收窄、avoid_slow_async_io 24 处 exists()→existsSync()。flutter analyze 0 issues,services/providers/architecture/models/domain/utils/logging/data 测试全绿(壁纸 7 例失败为主分支既有,与本批无关)。 | 1 个月前 | |
局域网编辑:保持开启状态对齐,优化网址展示与点格聚焦时段 离开页面时用服务侧 retain 标志避免误停;停服时同步关闭前台通知。访问地址左右分栏无框、HyperOS 复制按钮。课表点进时优先展示并高亮对应时间段。 | 2 个月前 | |
收紧(工程化): lint 收紧至 strict-casts/strict-raw-types + 40 条扩展规则并全量清零,analyze --fatal-infos 门禁,CJK 硬编码审计棘轮接入 CI——analysis_options 启用 use_build_context_synchronously/cancel_subscriptions/avoid_print 等正确性规则与风格集(dart fix 批量修 1432 处 + 手工修 14 error/17 warning),两个高噪音规则 cascade_invocations(127)/discarded_futures(195) 注释保留待第二批;CI/安卓构建 analyze 收紧为 --fatal-infos 防劣化;audit_cjk_hardcode.py 新增 --baseline 棘轮模式(回归失败/改进自动下调),基线 68 文件 1070 行入库,CI 新增 CJK hardcode audit 步骤;附带 strict_raw_type 显式泛型、lan_edit_api_handlers ArgumentError.message 类型收窄、avoid_slow_async_io 24 处 exists()→existsSync()。flutter analyze 0 issues,services/providers/architecture/models/domain/utils/logging/data 测试全绿(壁纸 7 例失败为主分支既有,与本批无关)。 | 1 个月前 | |
优化局域网编辑与数据传输稳定性 Made-with: Proma | 1 个月前 | |
局域网编辑写操作绑定 profileId/session,active 不一致返回 409 | 2 个月前 | |
收紧(工程化): lint 收紧至 strict-casts/strict-raw-types + 40 条扩展规则并全量清零,analyze --fatal-infos 门禁,CJK 硬编码审计棘轮接入 CI——analysis_options 启用 use_build_context_synchronously/cancel_subscriptions/avoid_print 等正确性规则与风格集(dart fix 批量修 1432 处 + 手工修 14 error/17 warning),两个高噪音规则 cascade_invocations(127)/discarded_futures(195) 注释保留待第二批;CI/安卓构建 analyze 收紧为 --fatal-infos 防劣化;audit_cjk_hardcode.py 新增 --baseline 棘轮模式(回归失败/改进自动下调),基线 68 文件 1070 行入库,CI 新增 CJK hardcode audit 步骤;附带 strict_raw_type 显式泛型、lan_edit_api_handlers ArgumentError.message 类型收窄、avoid_slow_async_io 24 处 exists()→existsSync()。flutter analyze 0 issues,services/providers/architecture/models/domain/utils/logging/data 测试全绿(壁纸 7 例失败为主分支既有,与本批无关)。 | 1 个月前 | |
功能(超级岛): 展开详情逐字段自定义(显隐+顺序)+ 课前快捷操作失败 Toast。展开态此前 9 行详情(阶段/简称/进度/状态/时间/地点/老师/下节课/备注)固定顺序硬编码在 LiveUpdateService,用户无法裁剪。新增 LiveExpandedDetailField 枚举 + LiveDisplaySettings.expandedDetailFields(null=全显示,空列表=全隐藏,顺序即行序),课前/课中下课双档各一组,课中档未单独设置时回退课前;Flutter payload islandConfig.expandedDetailFields → MethodChannel → Intent putStringArrayListExtra → LiveUpdateService expandedDetailLineList 按序拼行,前后台路径一致。设置页「展开详情」分组:上下箭头排序+开关+已隐藏分区+恢复默认。全关空正文时 BigTextStyle 回退 summaryText→contentText→title,避免可展开空通知。同步补上 8b9aef9a 遗留的 QuickAction 失败 Toast 三处接线(取消静音/免打扰失败时立即可见提示,后台 startActivity 在 Android 10+ 常被拦)。老数据无新 key → null → 全显示,无迁移。新增 parseExpandedDetailFields 3 例 + 设置模型 4 例;analyze 0 issues,相关 Flutter 53 例与 Kotlin LiveUpdate*LogicTest 全过。 | 25 天前 | |
收紧(工程化): lint 收紧至 strict-casts/strict-raw-types + 40 条扩展规则并全量清零,analyze --fatal-infos 门禁,CJK 硬编码审计棘轮接入 CI——analysis_options 启用 use_build_context_synchronously/cancel_subscriptions/avoid_print 等正确性规则与风格集(dart fix 批量修 1432 处 + 手工修 14 error/17 warning),两个高噪音规则 cascade_invocations(127)/discarded_futures(195) 注释保留待第二批;CI/安卓构建 analyze 收紧为 --fatal-infos 防劣化;audit_cjk_hardcode.py 新增 --baseline 棘轮模式(回归失败/改进自动下调),基线 68 文件 1070 行入库,CI 新增 CJK hardcode audit 步骤;附带 strict_raw_type 显式泛型、lan_edit_api_handlers ArgumentError.message 类型收窄、avoid_slow_async_io 24 处 exists()→existsSync()。flutter analyze 0 issues,services/providers/architecture/models/domain/utils/logging/data 测试全绿(壁纸 7 例失败为主分支既有,与本批无关)。 | 1 个月前 | |
修复(超级岛): 展开详情关掉的字段不再被原生补齐回来 设置页「展开详情」关掉某一项 = 把它从名单里删掉,但原生 parseExpandedDetailFields 把「没提到的字段」一律当成老版本/传输截断,按默认顺序补回末尾,于是任何单项隐藏 都不生效(真机复现:课中/下课档只留 4 项,下课提醒仍多出「简称」「备注」两行, 且总排在用户顺序之后);同一原因也让设置页预览与真机不一致。 改为用「写法版本号」区分两种语义: - 快照 settings 子树新增 liveExpandedDetailSchemaVersion(Dart 侧 kLiveExpandedDetailSchemaVersion,原生 EXPANDED_DETAIL_SCHEMA_VERSION 同值); - 版本 >= 当前 -> 只清洗(丢未知项、去重、保序),没提到 = 用户关掉,原样生效; - 版本缺失/更老(老快照)-> 保持原补齐语义,升级后展开态不变样; - payload 路径同一次安装内天然同版本,走默认参数、不补齐; - key 缺失仍回默认全显示顺序,空数组仍表示全部隐藏。 验证:LiveUpdateSchedulerLogicTest 33 例全过(含新增「当前版本保持隐藏」「老发送方 仍补齐」);新增 test/services/miui_live_activities_service_test.dart(2 例,含 与原生常量的同值守卫);flutter analyze 无 issue。 | 19 天前 | |
收紧(工程化): lint 收紧至 strict-casts/strict-raw-types + 40 条扩展规则并全量清零,analyze --fatal-infos 门禁,CJK 硬编码审计棘轮接入 CI——analysis_options 启用 use_build_context_synchronously/cancel_subscriptions/avoid_print 等正确性规则与风格集(dart fix 批量修 1432 处 + 手工修 14 error/17 warning),两个高噪音规则 cascade_invocations(127)/discarded_futures(195) 注释保留待第二批;CI/安卓构建 analyze 收紧为 --fatal-infos 防劣化;audit_cjk_hardcode.py 新增 --baseline 棘轮模式(回归失败/改进自动下调),基线 68 文件 1070 行入库,CI 新增 CJK hardcode audit 步骤;附带 strict_raw_type 显式泛型、lan_edit_api_handlers ArgumentError.message 类型收窄、avoid_slow_async_io 24 处 exists()→existsSync()。flutter analyze 0 issues,services/providers/architecture/models/domain/utils/logging/data 测试全绿(壁纸 7 例失败为主分支既有,与本批无关)。 | 1 个月前 | |
截屏提示分享干净课表图(Android 14 官方回调) 截屏后浮一条胶囊提示,点了才把课表渲染成一张干净图走系统分享面板。 此前只能手动截屏,截出来的是「屏幕」:带 App 顶栏、玻璃球、底部坞、壁纸。 - 原生通道 com.mutx163.qingyu/screen_capture:注册 Activity.ScreenCaptureCallback,注册收 onStart、注销收 onStop(官方要求 回调只在 Activity STARTED 期间注册,放 configureFlutterEngine 会崩); SDK 判断必须内联写,抽成函数会让 lint 的 NewApi 跟丢,而 release 的 lintVitalRelease 把它当错误;Manifest 加 DETECT_SCREEN_CAPTURE(普通权限, 安装即授予,拿不到截图内容)。 - ScreenCaptureService(Dart):广播流 + 引用计数。监听是进程级的、发起方 是页面,页面前后重建时若「谁走谁注销」会把新来者的监听一起关掉。 - 离屏渲染机制从统计导出抽出为中性件 ImageExportCapture,统计分享改为调用 它(对外行为逐字不变),课表分享复用同一套切片/编码坑位处理。 - TimetableExportDocument:周视图复用屏内 TimetableWeekPreview,必须显式 给 heightBudget(否则按一屏的 MediaQuery 排版),并清掉壁纸(离屏宿主 采不到底面,实时玻璃会塌成裸 tint;顺带掐掉异步采样带来的不确定); TimetableWeekPreview 新增 showFloatingBackToCurrentWeek 以在图上关掉 「回本周」浮钮。日视图另写当天课程列表文档 —— 屏内日视图全是 _TimetableScreenState 的私有方法且主体可滚动,搬不动也不适合当分享图。 - 课表主页:截屏事件只在本人盖在最上面时响应,冷却 6s,提示复用现成的 磨砂胶囊;菜单加 shareTimetable 入口,由主页拦截以带上当前可见周与 周/日视图。 - 设置:开关放「课表页面」(与长按空白格添加同组同理由),平台不支持则不 展示;SettingsResetScope.timetablePage 逐字段清单同步纳入。 - 文案进 6 份 arb 并重新 gen-l10n;新增测试 12 例(截屏服务 5、导出文档 4、 设置模型 3),另在 settings_reset_test 加两处归属断言。 | 18 天前 | |
fix: 修复评审确认的编译错误与同步链路连带破坏 评审意见核实与修复(均已在 head 上复现属实): 1. holiday_service:补回误删的 _prefs 缓存字段(Undefined name 编译失败) 2. app_sync_snapshot_service:适配 loadCustomHolidays 可空签名; 收集快照遇本地损坏时中止并抛 HolidayCustomSaveException, 严禁兜底空列表上传覆盖云端好数据(同步链路均有 rollback/错误兜底) 3. holiday_service_test:remaining.first 在可空值上改用 ?. 解引用 4. app_log_service:连续写失败 debugPrint 移出 assert,release 可见 (磁盘满场景恰是 release 最需观测的路径) 5. holiday_service:clearCache 的 warn 与 saveCustomHolidays 的 error 日志调用自兜底,避免二次异常掩盖原异常/带崩调用方 6. spreadsheet_import_service:合并自相矛盾的 on FormatException+catch(_) 7. webdav_sync_service:孤儿备份删除失败由 assert(debugPrint) 改为 AppLogService.warn,release 可观测 8. settings_holiday:toast 改用通用本地化 saveFailed 文案, 避免英文技术详情透出给用户;live_settings_subpages 去掉多余 foundation import(material 已导出,消除 CI --fatal-infos info) 验证:flutter analyze 0 error(仅余 main 既有 2 条无关 info); holiday/snapshot/webdav/spreadsheet/applog/dataflow 相关 121 测试全过 | 1 个月前 | |
修复(统计): 学期进度改按天精确计算,开学前显示 0% 而非预支第一周 - 开学前(今天早于开学日)新增 beforeStart 状态:进度 0%、周数 0/N、文案「还未开学,尚未上课」——原实现把开学前日期兜底成第 1 周并整周计入已上,导致没开学就显示 8% - 学期中按天累计:完整周整周计,当前周只算开学日及之后、今天及之前实际发生的课时,不再周一早上就把整周预支为「已上」;「截至」日期从未来的本周日改为真实今天 - 明细行改为「截至第 N 周,已上 X 节 / 共 Y 节」;无开学日期回落按周估算口径并注明;学期结束后收满 100% - SemesterProgress 新增 phase 枚举驱动进度卡分态展示;进度计算支持注入 now 便于测试;7 条单测覆盖开学前/周中/开学日周中/结束边界 | 1 个月前 | |
截屏提示分享干净课表图(Android 14 官方回调) 截屏后浮一条胶囊提示,点了才把课表渲染成一张干净图走系统分享面板。 此前只能手动截屏,截出来的是「屏幕」:带 App 顶栏、玻璃球、底部坞、壁纸。 - 原生通道 com.mutx163.qingyu/screen_capture:注册 Activity.ScreenCaptureCallback,注册收 onStart、注销收 onStop(官方要求 回调只在 Activity STARTED 期间注册,放 configureFlutterEngine 会崩); SDK 判断必须内联写,抽成函数会让 lint 的 NewApi 跟丢,而 release 的 lintVitalRelease 把它当错误;Manifest 加 DETECT_SCREEN_CAPTURE(普通权限, 安装即授予,拿不到截图内容)。 - ScreenCaptureService(Dart):广播流 + 引用计数。监听是进程级的、发起方 是页面,页面前后重建时若「谁走谁注销」会把新来者的监听一起关掉。 - 离屏渲染机制从统计导出抽出为中性件 ImageExportCapture,统计分享改为调用 它(对外行为逐字不变),课表分享复用同一套切片/编码坑位处理。 - TimetableExportDocument:周视图复用屏内 TimetableWeekPreview,必须显式 给 heightBudget(否则按一屏的 MediaQuery 排版),并清掉壁纸(离屏宿主 采不到底面,实时玻璃会塌成裸 tint;顺带掐掉异步采样带来的不确定); TimetableWeekPreview 新增 showFloatingBackToCurrentWeek 以在图上关掉 「回本周」浮钮。日视图另写当天课程列表文档 —— 屏内日视图全是 _TimetableScreenState 的私有方法且主体可滚动,搬不动也不适合当分享图。 - 课表主页:截屏事件只在本人盖在最上面时响应,冷却 6s,提示复用现成的 磨砂胶囊;菜单加 shareTimetable 入口,由主页拦截以带上当前可见周与 周/日视图。 - 设置:开关放「课表页面」(与长按空白格添加同组同理由),平台不支持则不 展示;SettingsResetScope.timetablePage 逐字段清单同步纳入。 - 文案进 6 份 arb 并重新 gen-l10n;新增测试 12 例(截屏服务 5、导出文档 4、 设置模型 3),另在 settings_reset_test 加两处归属断言。 | 18 天前 | |
修复(桌面小组件): 统计快照不再只在打开统计页时才生成——桌面「课程统计 2×2 / 2×4 / 统计横条 4×1」此前唯一的写入点是统计页 build() 里的内联计算,用户从不进统计页时这三个组件永远停在「暂无课程数据」。 - 把内联计算收敛为 StatsWidgetSnapshot.fromCourses 唯一入口,统计页与课表侧共用同一口径; - 在 _liveSyncHomeWidgetSnapshot 入口追加 _liveSyncStatsWidgetSnapshot,冷启动、回前台、课表变更三条路径都会随今日快照一起推送统计快照,无课时清空原生侧避免残留旧数据; - syncSnapshot 增加按内容去重(统计页每次重建都会调用,避免重复跨端写入),clearSnapshot 后重置签名; - 新增 test/services/stats_widget_snapshot_test.dart 覆盖空课表、与 StatisticsService 逐项一致、去重与清空后重推三点。 | 1 个月前 | |
修复(存储): 空数据判定双侧归一化并排除自动回填的 activeTimeSchemeId——fromJson 菜单回填与 scheme 回填使单空 profile 恒判非空、迁移引导永不弹出(2114 起存量缺陷,非 2116 回归;补 isAppDataEffectivelyEmpty 首批测试) | 1 个月前 | |
修复(CJK审计): 鸣谢名单 GitCode 主候选两行调试日志改英文——abb3dbdd 新增的 8 行使 support_creator_service 棘轮计数 7→8 回归,调试日志为开发者向非用户可见,改英文后计数 6 并自动下调基线 | 26 天前 | |
修复(并发门闩): SyncOperationGate 空闲快路径同步启动动作体,修复周视图跳转三连挂 五路合并后 flutter test 挂 4 处周次相关用例,根因:runExclusive 是 async,即便门空闲也会把动作体推迟到 await previous 的微任务之后;且上一任持有者创建于 tester.runAsync(真实 async 区)时,其完成回调是真实微任务,FakeAsync 的 pump 永远清不到——widget 测试里排队中的 setCurrentWeek 永远轮不到执行(周视图 back-to-current-week/swipe 三用例 currentWeek 卡在旧值),单元测试锚定的「先同步改内存状态并 notify,再等持久化」语义(PR#45 提交信息自称保持,实现却违背)也一并破坏。 修复:新增 _tailSettled 标记跟踪队列空闲态(Future 查不到已完成状态,持有者释放时仅当自己仍是队尾才置回),空闲时直接在调用方同步 runZoned 启动动作体,完成后再放行后续排队者;忙时排队语义原样保留;再入分支改 Future.sync 保持同步抛出转失败 Future 的旧语义;快路径派生 Future 加 ignore() 防动作体失败被二次上报为 unhandled error。 测试:timetable_provider_profiles_test 的 setCurrentWeek 同步性用例需先经公开 runMutationExclusive 空操作排空 initialize 遗留的后台延迟加载(否则走排队路径,锚定语义不适用),加注释说明。 | 1 个月前 | |
重构(闹钟): 设这节课闹钟改为写入系统时钟每周重复闹钟 - 新增 SystemAlarm 原生通道(ACTION_SET_ALARM / SHOW_ALARMS + SET_ALARM 权限与时钟应用包可见性),写入「轻屿 · 课程名」每周重复闹钟 - 弹层改为快捷提前量 / 自定义响点两种方式,写入前确认真实响点、提前量与上课周次,响点跨午夜时星期跟随真实响铃日 - 课程操作弹窗仅在课程未开课时显示闹钟入口;旧「课程×日期」本地通知提醒保留兼容并提供取消入口 - 新增 classAlarmSkipUi 设置项持久化并随云同步(默认关);四语补齐确认弹窗文案 | 1 个月前 | |
截屏提示分享干净课表图(Android 14 官方回调) 截屏后浮一条胶囊提示,点了才把课表渲染成一张干净图走系统分享面板。 此前只能手动截屏,截出来的是「屏幕」:带 App 顶栏、玻璃球、底部坞、壁纸。 - 原生通道 com.mutx163.qingyu/screen_capture:注册 Activity.ScreenCaptureCallback,注册收 onStart、注销收 onStop(官方要求 回调只在 Activity STARTED 期间注册,放 configureFlutterEngine 会崩); SDK 判断必须内联写,抽成函数会让 lint 的 NewApi 跟丢,而 release 的 lintVitalRelease 把它当错误;Manifest 加 DETECT_SCREEN_CAPTURE(普通权限, 安装即授予,拿不到截图内容)。 - ScreenCaptureService(Dart):广播流 + 引用计数。监听是进程级的、发起方 是页面,页面前后重建时若「谁走谁注销」会把新来者的监听一起关掉。 - 离屏渲染机制从统计导出抽出为中性件 ImageExportCapture,统计分享改为调用 它(对外行为逐字不变),课表分享复用同一套切片/编码坑位处理。 - TimetableExportDocument:周视图复用屏内 TimetableWeekPreview,必须显式 给 heightBudget(否则按一屏的 MediaQuery 排版),并清掉壁纸(离屏宿主 采不到底面,实时玻璃会塌成裸 tint;顺带掐掉异步采样带来的不确定); TimetableWeekPreview 新增 showFloatingBackToCurrentWeek 以在图上关掉 「回本周」浮钮。日视图另写当天课程列表文档 —— 屏内日视图全是 _TimetableScreenState 的私有方法且主体可滚动,搬不动也不适合当分享图。 - 课表主页:截屏事件只在本人盖在最上面时响应,冷却 6s,提示复用现成的 磨砂胶囊;菜单加 shareTimetable 入口,由主页拦截以带上当前可见周与 周/日视图。 - 设置:开关放「课表页面」(与长按空白格添加同组同理由),平台不支持则不 展示;SettingsResetScope.timetablePage 逐字段清单同步纳入。 - 文案进 6 份 arb 并重新 gen-l10n;新增测试 12 例(截屏服务 5、导出文档 4、 设置模型 3),另在 settings_reset_test 加两处归属断言。 | 18 天前 | |
fix(transfer): 差异对比按档案作用域隔离,修复跨档案同 ID 互相覆盖 课程/考试/任务/排课的对比键改为 jsonEncode([profileId, id]) 结构化编码,免疫分隔符别名注入;TransferEntityChange 新增 profileId 并在描述与序列化中携带,多档案同 ID 条目不再合并误报。 | 1 个月前 | |
修复(传输): 全量备份包允许跨课表重复实体 ID,修「二维码发送全部数据」无反应根因 「导入为新课表」与伙伴课表导入都会保留来源实体 ID,本地全量数据因此 可以合法地出现跨 profile 重复 ID;此前 TransferPackage 构造器对非云通道 强制全局唯一,buildFullPackage 直接抛 transfer_course_id_duplicate, 被 UI 层吞掉表现为点击无反应。现全量包(isFullBackup)与云通道同规则: 仅要求 profile 内唯一(导入侧全量包走整体替换,重复 ID 不会污染按 ID 合并)。profile 内重复仍拒绝,原有测试保持通过。 | 1 个月前 | |
优化局域网编辑与数据传输稳定性 Made-with: Proma | 1 个月前 | |
feat(ui): polish HyperOS kit, splash screen, and settings layouts Refine HyperOS controls, page navigation, overscroll, and frosted blur across timetable, settings, import, and about flows; add Android 12+ splash layer drawable and expand related widget tests. Co-authored-by: Cursor <cursoragent@cursor.com> | 2 个月前 | |
feat(时间模板分享): 时间模板页与备份页新增分享入口 - unified_transfer_service: buildCurrentPackage 支持 selectedTimeSchemeIds - 时间模板管理页: 每个模板菜单新增「分享」- 系统分享文件 / 二维码 - 数据备份与迁移页: 新增「导出时间模板」按钮 - 单测 + 备份页/widget 测试 | 25 天前 | |
feat: add WEBDAV cloud sync and broaden external imports Introduce Jianguoyun WEBDAV backup/sync with secure credentials, lifecycle pull, and settings UI. Extend Android share/view intents and startup routing for ICS, backup JSON, CSV, and XLSX imports. Co-authored-by: Cursor <cursoragent@cursor.com> | 2 个月前 | |
重构(壁纸): 全局历史的迁移/并集下沉到 service,Provider 行数棘轮只 +5 发版前全量测试暴露真门禁:test/architecture/dependency_guards_test.dart 的 「timetable_provider.dart 行数棘轮:只减不增」——本批只有 修复(壁纸)…历史改全局 那个提交动过该文件(+69),而 193f1068 时它正好 4455 = 基线。 按仓库「god class 不再堆积、拆分归阶段 3」的方向,把逻辑整体挪出: - 迁移与导入后并集(含完成标记、错误日志、按 profile 收集镜像)→ WallpaperHistoryService.migrateProfilesOnce / mergeImportedProfiles; - 「所有 profile 当前壁纸路径」白名单 → 纯函数 inUseWallpaperPaths(Iterable<TimetableSettings>)(utils/wallpaper_history.dart), 设置页与恢复默认两处调用点改为直接传各自需要的 settings 列表 (恢复默认仍排除当前 profile)。 Provider 侧只剩两条一行调用入口(+1 import、+2 调用行、+2 注释行 = +5), 按该测试自带约定同步基线 4455 → 4460 并写明原因。 验证:flutter analyze 无 issue;data/architecture/wallpaper 相关 5 个测试文件 36 例全过(含棘轮用例)。 | 19 天前 | |
feat(import): 注入 v1/v2 双桥兼容垫片,适配上游 shiguang_warehouse 协议 v2 上游已于 2026-08-23 将桥接对象从 AndroidBridge* 更名为 window.shiguangBridge*。宿主完成 v1 桥实现后追加双向别名(新增 warehouse_bridge_compat.dart 常量,wrappedScript 中插值),使同一注入环境同时兼容 v1/v2 适配脚本;补三组单元测试锁定别名与防插值约束。详见 docs/plans/2026-08-23-upstream-v2-bridge-compat-plan.md A 层。 | 1 个月前 | |
修复: prefer_initializing_formals 误改公开构造函数签名致库外按名传参编译失败——5 处 this._私有字段改回可选参数+?? 兜底(timetable_provider.enableLiveActivitySync 测试 84 处、app_update_service.releaseApiRequestTimeout、warehouse_import_preferences_service.secureStorage 测试 2 处、couple/webdav_sync_credentials_store.storage DI 能力),保留公开参数名。flutter analyze 0 issues,services/providers/architecture/data/utils/logging/models/domain 测试全绿 | 1 个月前 | |
教务导入:本会话执行日志可查看、导出与清空 记录 bridge 与 WebView console,学校列表与登录页菜单均可打开日志页。 Co-authored-by: Cursor <cursoragent@cursor.com> | 2 个月前 | |
合并(main): 解决 storage_service/holiday_service/settings_holiday 冲突——课程读取保留条目级容错(PR 修复),假期保存与 UI 失败反馈采用 main 的 HolidayCustomSaveException 包装实现 | 1 个月前 | |
| 24 天前 | ||
新增(天气): Open-Meteo 服务与本地缓存(日视图课卡天气 · 第 2 步) - lib/services/weather_service.dart 预报端点(逐小时温度/降水概率/降水量/降雪量/天气码,回溯 1 天、窗口 16 天) 与地理编码端点(language=zh,中文城市名可用)。 照 holiday_service 的范式:client 可注入、只有非共享 client 才 close、 10 秒超时、失败一律返回 null/空列表并落 AppLogService.warn(自身 catchError 兜底),绝不向上抛——天气是装饰性信息,故障不该让界面报错。 显式用 utf8.decode(bodyBytes) 而不是 response.body:中文城市名一旦落到 latin1 兜底解码就成乱码。 加可选 timeout 参数,让超时路径能被快速、确定性地测到。 - lib/services/weather_preferences.dart 设备本地配置:开关(默认关)、所选城市、预报缓存。 刻意不进 TimetableSettings——那份会随 profile 进备份与云同步 payload, 而「所在城市」是设备属性(两台设备一台杭州一台成都,同步一个必然错一台)。 - lib/models/weather_forecast.dart 补 fromOpenMeteoResponse:厂商把 6 个平行数组放在 hourly 子对象里且不返回 抓取时刻。放在模型里而非服务里,是为了让「列式数组怎么读」只有一份实现。 经纬度取响应回填的格点中心,判「缓存是不是这个城市的」时不会因格点偏移误判。 - 测试 23 条:字段解析、请求参数、非 200/网络异常/超时/畸形 JSON/缺 hourly 块 全部降级为 null、地理编码中文不乱码且跳过畸形条目、关键字不足两字符不发请求、 缓存往返与损坏数据降级。 验证:flutter analyze 无 issue;flutter test 23 条全绿。 | 16 天前 | |
接入(天气): Dart 侧接上原生定位通道,拿不到就退 IP 估算并如实标注 上一提交(5834e945)只加了 Kotlin 通道,Dart 侧还在走 geolocator,所以真机仍然 「转圈到失败」。这次把 Dart 侧接上,并补上用户拍板的 IP 估算兜底。 - device_location_service.dart 重写取位置那一段: · DeviceLocationSource 的第四个方法从 getCurrentPosition(LocationSettings) / getLastKnownPosition() 收敛成一个 getCurrentFix() → DeviceFix?。坐标有多个 来源(原生通道 / geolocator 兜底 / 原生内部缓存),用同一个轻量值类型收敛, 测试里造假件不必凑齐 Position 的十个字段。 · NativeDeviceLocationSource 调原生通道;**只有通道本身故障**(未注册 / 解码 失败)才兜底 geolocator,且只兜一次——null 是「没拿到」这个正常结果,不能 在 Dart 侧再等一轮,否则预算翻倍(12 秒 + 12 秒)。 · 顺序:权限/开关 → 实时定位(原生通道:网络优先、12 秒总预算、内部缓存兜底) → 网络 IP 估算 → 才失败。上一版把「系统缓存」放最前当首选,方向错了:用户 点「使用当前位置」要的是现在在哪,缓存只该在前面的实时定位拿不到时兜底, 否则换了城市仍会停在旧定位。lastKnownMaxAge 那套缓存策略整段删除。 · 估算只在实时定位返回 null 时走;实时定位**抛异常**不走估算——异常是流程坏了, 再悄悄估算一次会把真正的故障盖掉。同理「有坐标但反查失败」也不退化成估算。 · timeout 的含义随之变为「实时定位与估算都没拿到可用位置」。 - weather_service.dart:BigDataCloud 的 reverse-geocode-client 不带坐标时就是 IP 定位,所以 networkGeocode() 与 reverseGeocode 共用同一个接口和 _parseLocation 解析,只是不传 latitude/longitude。零新增依赖、零新增数据源。 - 估算结果必须如实标注,不许冒充真实定位: DeviceLocationOutcome.estimated → WeatherProvider.lastLocateWasEstimated → 两处界面成功后多弹一句 weatherLocationEstimated(六语言)。 - 测试跟上新契约: · helpers_location_stub.dart 的假件只暴露 fix(null = 拿不到)、estimatesTo 与 delay;positionCalls 改名 fixCalls。 · device_location_service_test.dart 重写:删掉 6 条「系统缓存优先」用例(缓存 策略已不在 Dart 侧),补三条「不该走的路」——实时定位成功时不发 IP 估算请求、 通道抛异常时不退到估算、有坐标但反查失败时不退到估算。 · 两个页面测试各加一对估算提示用例:真实定位成功时 findsNothing(对照组), 实时定位拿不到时 findsOneWidget。只测「估算时出现」的话,把 estimated 写死 成 true 也能通过,那样提示就变成狼来了。 验证:flutter analyze 全仓无 issue;上述五个测试文件 16 + 36 + 34 + 121 + 5 全绿; CJK 硬编码棘轮与三条笔记校验脚本均通过。原生通道本身尚未在真机上跑过(本机跑不了 安卓构建),首次真机测试要看 weather_location_ok 里的 source 与 elapsedMs。 | 16 天前 | |
fix(webdav): 状态码文本识别补标准线格式 HTTP/1.1 401 6e24480 收紧正则消除路径数字误判时,http\s+ 分支无法匹配 "HTTP/1.1 401 Unauthorized" 这类最常见线格式(http 后是 /), 未被 SDK 包包装的认证错误退化为通用失败。新增 https?/x.y 前缀 分支,两处正则同步更新并补测试。 说明:timetable_screen.dart 与 glass_dock_wallpaper_repro_test.dart 的工作区改动属于其他并行任务,未包含在本提交。 | 1 个月前 | |
fix(webdav): 状态码文本识别补标准线格式 HTTP/1.1 401 6e24480 收紧正则消除路径数字误判时,http\s+ 分支无法匹配 "HTTP/1.1 401 Unauthorized" 这类最常见线格式(http 后是 /), 未被 SDK 包包装的认证错误退化为通用失败。新增 https?/x.y 前缀 分支,两处正则同步更新并补测试。 说明:timetable_screen.dart 与 glass_dock_wallpaper_repro_test.dart 的工作区改动属于其他并行任务,未包含在本提交。 | 1 个月前 | |
加固课表与考试数据解析边界并优化同步触发 课程/考试 fromJson 规范化星期、节次、周次与时间; ICS 识别 INTERVAL=2 双周;导入结束统一通知云同步; 实况日程快照改用日历周;补充对应单元测试。 Co-authored-by: Cursor <cursoragent@cursor.com> | 2 个月前 | |
feat: 统一迁移入口并接入预览撤销流程 | 1 个月前 | |
修复: prefer_initializing_formals 误改公开构造函数签名致库外按名传参编译失败——5 处 this._私有字段改回可选参数+?? 兜底(timetable_provider.enableLiveActivitySync 测试 84 处、app_update_service.releaseApiRequestTimeout、warehouse_import_preferences_service.secureStorage 测试 2 处、couple/webdav_sync_credentials_store.storage DI 能力),保留公开参数名。flutter analyze 0 issues,services/providers/architecture/data/utils/logging/models/domain 测试全绿 | 1 个月前 | |
修复(云同步): 首次同步分歧不再把新用户吓退——手动「立即同步」遇云端已有数据时弹「检测到同步冲突」且文案宣称本机也有新的修改,用户看不懂反复点取消,只能瞎试出「先立即备份再同步」的绕路(用户实测反馈)。三处收口:①手动拉取冲突补上后台路径已有的空本机豁免(resolveManualPullConflictChoice:本机无用户数据时跳过弹窗直接以云端为准,对齐 webdavBackgroundPullShouldCancel 口径),全新设备/空壳快照不再被选边框拦截;②SyncConflictInfo 增加 isFirstSyncDivergence/localHasUserData 字段(带默认值),弹窗按首次分歧切换解释性文案「本机与云端数据不一致」+写明保留本机/使用云端各自后果(3 新串同步 6 arb);③冲突弹窗取消后的 toast 升级为可点 action「以本机为准备份」直达手动备份(复用 createManualBackup 锚定基线,即用户误打误撞发现的正解)。保护语义不动:先拉后传顺序、force 仅限手动、断开清基线后重连触发冲突均为刻意设计。flutter analyze 0 issues;同步相关 4 测试文件 49 例全绿(新增 3 例)。 | 28 天前 | |
fix(import): 硬化教务导入与冲突/情侣同步语义 覆盖导入清空日程;冲突按实际周判断;Bridge requestId 消毒;仓库脚本官方源优先;情侣 WebDAV 双槽位;周表达式括号奇偶收窄。 | 2 个月前 | |
收紧(工程化): lint 收紧至 strict-casts/strict-raw-types + 40 条扩展规则并全量清零,analyze --fatal-infos 门禁,CJK 硬编码审计棘轮接入 CI——analysis_options 启用 use_build_context_synchronously/cancel_subscriptions/avoid_print 等正确性规则与风格集(dart fix 批量修 1432 处 + 手工修 14 error/17 warning),两个高噪音规则 cascade_invocations(127)/discarded_futures(195) 注释保留待第二批;CI/安卓构建 analyze 收紧为 --fatal-infos 防劣化;audit_cjk_hardcode.py 新增 --baseline 棘轮模式(回归失败/改进自动下调),基线 68 文件 1070 行入库,CI 新增 CJK hardcode audit 步骤;附带 strict_raw_type 显式泛型、lan_edit_api_handlers ArgumentError.message 类型收窄、avoid_slow_async_io 24 处 exists()→existsSync()。flutter analyze 0 issues,services/providers/architecture/models/domain/utils/logging/data 测试全绿(壁纸 7 例失败为主分支既有,与本批无关)。 | 1 个月前 | |
功能(桌面卡片-情侣绑定): 各卡片绑定管理新增「情侣课表」合并视图。绑定哨兵 couple-merged(虚拟视图,非真实课表):快照=我的当前课表+TA 课表按周偏移映射合并,同行程(同时段同名)按我的那份去重(与 App 内情侣覆盖层同口径),全部按情侣三色(我/TA/一起)着色;学期/节假日/考试/外观锚定我方。点击分流与 TA 绑定一致→打开情侣覆盖层;TA 解绑/被删回落「跟随当前课表」。TA 导入/周偏移/三色/解绑后立即重推绑定卡片专属快照(跳过 scheduleSnapshot)。绑定页在已导入 TA 课时同时提供「情侣课表」与「TA的课表」选项,6 语言文案。新增路由分流 2 例、合并快照 4 例、绑定页选项 1 例测试;analyze 0 issues,相关 33 测试通过。 | 25 天前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 1 个月前 | ||
| 2 个月前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 2 个月前 | ||
| 28 天前 | ||
| 2 个月前 | ||
| 28 天前 | ||
| 1 个月前 | ||
| 18 天前 | ||
| 12 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 16 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 25 天前 | ||
| 1 个月前 | ||
| 26 天前 | ||
| 14 天前 | ||
| 1 个月前 | ||
| 18 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 3 个月前 | ||
| 3 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 1 个月前 | ||
| 25 天前 | ||
| 1 个月前 | ||
| 19 天前 | ||
| 1 个月前 | ||
| 18 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 18 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 26 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 18 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 25 天前 | ||
| 2 个月前 | ||
| 19 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 1 个月前 | ||
| 24 天前 | ||
| 16 天前 | ||
| 16 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 2 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 28 天前 | ||
| 2 个月前 | ||
| 1 个月前 | ||
| 25 天前 |