| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
解耦(泳道A 5/7): webdav 三件与统一传输摘除 provider 反向依赖 改了什么:unified_transfer_service 定义 34 成员 UnifiedTransferPort; app_sync_snapshot_service 定义 12 成员 AppSyncTimetablePort,刻意不 extends 统一传输端口(app_sync 自己只用 12 个,白背 24 个正是 honest-scope 点名的 端口虚胖);两个宿主适配器住 lib/providers/。webdav_sync_service 与 coordinator 对 provider 零成员访问,只改类型名。转手给统一传输走独立参数 transferPort,由组合根 main.dart 把同一个 provider 装配成两个镜头分别注入, 谁都不替对方背多余成员。 为什么:services 层不得反向 import providers/timetable_provider.dart。 provider 主文件零改动(3835 行不变,棘轮 3837 余量守住);applyToProvider 的 「快照→应用→回滚同一次持锁」不变量靠适配器一行透传 runMutationExclusive 保住; reloadFromStorageAfterExternalApply 是动作不是读快照,适配器原样转发。 lan_edit_provider_host 的 5 处转手用私有内联适配器 _LanEditTransferPortAdapter, 不 import lib/providers/——否则这条边只是换个目标,边数不减反增。 验证:dart analyze lib test → 0 error;transfer 族 11+29、webdav/app_sync 族 65、 lan_edit 族 42 条测试全绿;screens_size_ratchet 5 条绿;dep_graph 实测 services→providers 6→2(本轮消 unified_transfer / app_sync / webdav 两件共 4 条)。 | 7 天前 | |
解耦(泳道A 3/7): couple_webdav_service 摘除 provider 反向依赖 改了什么:服务定义 8 成员窄端口 CoupleWebdavTimetableHost(initialize/ hasPartnerBinding/importPartnerTimetable/activeProfile/courses/ scheduleItems/settings/currentWeek),pull/upload 两方法改收端口实例; 宿主适配器 CoupleWebdavProviderAccess 新建于 lib/providers/; couple_timetable_settings_screen 两个调用点一行注入(连接 sheet 不碰 provider,零改动;无测试直测 pull/upload,本刀无测试改动)。 为什么:services 层不得反向 import providers/timetable_provider.dart。 provider 主文件一行未动。活读语义保留:拉取路径「先下载、后判绑定、 再导入」与上传路径「先查凭证、后 initialize、再活读五字段」的读取 时机逐点不变(适配器是一行转发 getter,不是快照)。 验证:couple_webdav_disconnect_resilience_test 与 credentials_keystore_test 各 2 条全绿(--timeout 60s);两道架构守卫全绿;dart analyze 改动 3 文件 0 issue;dep_graph services→providers 计边 10→9(本次消除 couple_webdav_service)。 违规边变化:10→9。 | 8 天前 | |
解耦(泳道A 2/7): import_time_scheme_restore_point 摘除 provider 反向依赖 改了什么:恢复点定义 4 成员窄端口 ImportTimeSchemeRestoreHost(settings 快照读 / timeSchemes 活读 / updateTimetableSettings / deleteTimeScheme), capture(ImportTimeSchemeRestoreHost host) 改收端口实例;宿主适配器 ImportRestoreProviderAccess 新建于 lib/providers/;四个导入屏(AI 图 / ICS / 表格 / 教务)与测试的调用点改为一行注入适配器。 为什么:services 层不得反向 import providers/timetable_provider.dart。 provider 主文件一行未动;恢复时序(先删「导入补齐」副本、再整份写回 设置;删除逐条独立 try、失败不上抛)与捕获语义(settings 快照、 schemeIds 差集)逐行保持。 验证:import_time_scheme_restore_point_test 3 条全绿(--timeout 60s); 两道架构守卫全绿;dart analyze 改动 7 文件 0 issue;dep_graph services→providers 计边 11→10(本次消除 import_time_scheme_restore_point)。 违规边变化:11→10。 | 8 天前 | |
解耦(泳道A 4/7): live_testing 双件摘除 provider 反向依赖 端口由服务自己定义(LiveTestingFixtureHost 11 成员 / LiveTestingTriggerHost 17 成员 + fixtureHost 转发),适配器住 lib/providers/(providers→services 合法 方向),调用点构造注入。trigger 需要夹具时经端口成员 fixtureHost 拿,服务层 不再 import providers/。dep_graph 实测 services→providers 9→7(合计 68→66)。 | 7 天前 | |
解耦(泳道A 4/7): live_testing 双件摘除 provider 反向依赖 端口由服务自己定义(LiveTestingFixtureHost 11 成员 / LiveTestingTriggerHost 17 成员 + fixtureHost 转发),适配器住 lib/providers/(providers→services 合法 方向),调用点构造注入。trigger 需要夹具时经端口成员 fixtureHost 拿,服务层 不再 import providers/。dep_graph 实测 services→providers 9→7(合计 68→66)。 | 7 天前 | |
refactor(provider): 界面运行时偏好走 services 端口(providers→ui 清零) TimetableProvider 之前直接 import 两条 ui/ 文件,只为把两个设置值推进界面层 全局状态: - ui/hyperos/hyperos_overscroll.dart 的 hyperosSetEdgeHapticsEnabled(边缘触感); - ui/hyperos_motion_bridge.dart 的 applyHyperosUserTransitionSpeed(转场速度)。 改为经 services/ui_runtime_prefs.dart 的端口推送: providers→services 与 ui→services 都是合法方向,依赖真正倒过来 —— 不是把 import 挪进某个免疫判定的目录把账做平(裁定 R1)。做法与 services/timetable_settings_writer.dart 的 applyEdgeHaptics 端口同型。 真正的实现由 ui/hyperos_motion_bridge.dart 在 configureHyperosMotionFromAndroid() 里注册。**注册顺序无关**:端口记住最后一次入参,注册时补发——冷启动时首页 先建、provider 先推,而暖机作业跑在首帧之后;不补发的话用户上次关掉的边缘 触感会在那段时间短暂恢复默认开。这条由 test/services/ui_runtime_prefs_test.dart 钉住(咬合探针已做:把补发删掉 → 3 条用例立即红)。 行数棘轮:provider 3835 → 3834(**下降**,基线 3837 未动、未抬)。 本次改动只是把 5 处调用点换成端口名 + 换 1 行 import,没有新增状态机。 dep_graph 实测 providers→ui 2→0。 行为等价:两个 setter 的语义逐字保留(触感直接透传、速度由 AndroidAnimationScaleService 自己 clamp 0.5~2.5)。 | 7 天前 | |
解耦(泳道A 5/7): webdav 三件与统一传输摘除 provider 反向依赖 改了什么:unified_transfer_service 定义 34 成员 UnifiedTransferPort; app_sync_snapshot_service 定义 12 成员 AppSyncTimetablePort,刻意不 extends 统一传输端口(app_sync 自己只用 12 个,白背 24 个正是 honest-scope 点名的 端口虚胖);两个宿主适配器住 lib/providers/。webdav_sync_service 与 coordinator 对 provider 零成员访问,只改类型名。转手给统一传输走独立参数 transferPort,由组合根 main.dart 把同一个 provider 装配成两个镜头分别注入, 谁都不替对方背多余成员。 为什么:services 层不得反向 import providers/timetable_provider.dart。 provider 主文件零改动(3835 行不变,棘轮 3837 余量守住);applyToProvider 的 「快照→应用→回滚同一次持锁」不变量靠适配器一行透传 runMutationExclusive 保住; reloadFromStorageAfterExternalApply 是动作不是读快照,适配器原样转发。 lan_edit_provider_host 的 5 处转手用私有内联适配器 _LanEditTransferPortAdapter, 不 import lib/providers/——否则这条边只是换个目标,边数不减反增。 验证:dart analyze lib test → 0 error;transfer 族 11+29、webdav/app_sync 族 65、 lan_edit 族 42 条测试全绿;screens_size_ratchet 5 条绿;dep_graph 实测 services→providers 6→2(本轮消 unified_transfer / app_sync / webdav 两件共 4 条)。 | 7 天前 | |
修(天气): 坐标取整把「同一城市」判定打穿——升级用户永远丢缓存、日视图反复请求 ## 问题 8d81dd0c(隐私清单 #3)让出网与落盘坐标统一取整到 2 位小数。但 WeatherLocation. samePlaceTolerance 仍是 1e-4(≈11 米),而取整误差最大 0.005(≈550 米)—— 差 50 倍。 内存里的位置(initialize() 从 prefs 原样读回,升级用户是 5 位小数)与缓存预报里的 坐标(取整后的 2 位)直接相减,差值 0.00365 > 1e-4,于是 matchesLocation / isSamePlaceAs 恒判「不是同一个城市」。 后果不是理论上的: 1. 升级用户每次冷启动都丢弃磁盘缓存(_forecast 被置 null),白等一次网络; 2. _shouldRefresh() 里有一条 !forecast.matchesLocation(_location) 就 return true, 判否即恒为真 —— 日视图每张卡重建都可能重发请求,一天 8 次的 TTL 设计被绕开。 8d81dd0c 注释里「多刷一次、一次自愈」的假设只对「用户重新选一次城市」成立; 对「什么都不做只升级」不成立 —— 那条路径上没有任何东西会把旧位置改写成取整精度。 顺带解释 weather_provider_test 那 6 条常红:4 条是断言取整前的值(测试滞后,行为本身 正确),2 条正是这个 bug(同城判定失效导致请求次数变多)。之前被统一记成「测试没跟上 实现」,掩盖了后半截。 ## 改法 在比较处统一精度(不改存储、不放大容差): - coarsenCoordinate 提到横切层 lib/utils/coordinate_precision.dart(唯一真源), WeatherService.coarsenCoordinate 保留为一行转发的公开别名,调用点/测试无感。 放 utils 的理由:models 要用它,而 models→services 是反向依赖会被守卫拦。 - 新增 WeatherLocation.coarsened()。 - isSamePlaceAs() / matchesLocation() 改为两边都取整后再比(三种精度组合都成立)。 - WeatherProvider.initialize() 读回位置后取整;setLocation() 入口先规范化, 比对与落盘都用规范化后的那份。 不选「放大容差到 0.02」:那是把「同城」放宽到 2 公里,切校区不刷新,是新的功能错误。 ## 验证 - weather_provider_test 6 红 → 43 全绿;新增 test/models/weather_location_precision_test (6 条)钉住跨精度判定。 - 天气相关 5 个测试文件 146 条全绿;test/architecture/ 50 条全绿;analyze 改动文件 0 issue。 - 咬合探针:把 isSamePlaceAs / matchesLocation 的比较分别改回裸值,对应用例立即红 (Expected: true / Actual: <false>),还原后干净。 - 未验:真机「升级用户首次冷启动即有天气」(需一份旧格式 prefs)、日视图长时间挂起后 的请求次数(需日志计数)。 | 7 天前 | |
月视图:页面、月网格局件、入口与文案 新增页面 lib/screens/month_view_screen.dart 与 lib/widgets/timetable/month_view/ (month_grid / month_day_cell / month_day_agenda),与既有 day_view/ 同构拆分: 渲染层不读 provider、不取数,判定结果由域逻辑带入。 交互按系统日历心智:整月网格 + 翻月 PageView;点某天在页面下方展开当日 议程(再点收起),点议程行进对应编辑页(课程/考试/日程,与日视图一致); 顶栏「回到本月」仅在翻离当前月时出现。翻月不自动选中日。 密度取舍:格子约 50dp、一天最多十几节课,故一格只画圆点(课程按自身色 去重封顶 3 颗、考试红点、日程强调点)+ 假期「休」/调休「班」小字, 不画课程名——「是什么」在当日议程里看。月格子不画天气(实时数据会过期, 且本仓已为「三个显示面不同步」付过两次学费)。 入口:八宫格目录加 monthView 条目 + 登记玻璃坞内嵌页(kInlineDockPages / kHomeCatalogPages),坞常驻、页内切换不丢翻月与选中日状态;用户可自行在 底栏编辑器里把它钉进底栏。 l10n:15 个新串写入六份 ARB 并重新 gen-l10n(含无障碍朗读的计数标签)。 无新增第三方依赖。 | 8 天前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 7 天前 | ||
| 8 天前 | ||
| 8 天前 | ||
| 7 天前 | ||
| 7 天前 | ||
| 7 天前 | ||
| 7 天前 | ||
| 7 天前 | ||
| 8 天前 |