在 在看 页面 添加了周数分栏显示#1650
Hidden character warning
Conversation
Added logic to group 'watching' bangumi by weekday, using a cached calendar mapping for accurate grouping. Updated the controller to load, cache, and persist the calendar data, and refactored the UI to display 'watching' items grouped by weekday with section headers. Also updated storage keys to support the new cache.
|
这次的提交应该干净很多, 如果还有什么问题请告诉我 |
There was a problem hiding this comment.
Pull request overview
在“追番/收藏”页面的“在看”标签页中新增按周几(周一~周日 + 老番)分组分栏展示能力,并引入 Bangumi 日历拉取与本地缓存来辅助分组。
Changes:
- “在看”页改为按周几分组渲染(增加分组标题与计数)
- CollectController 增加“在看日历”拉取、缓存读写与按周几分组方法
- Storage 增加
cachedWatchingCalendar设置键用于缓存
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| lib/utils/storage.dart | 新增 cachedWatchingCalendar 存储键用于本地缓存 |
| lib/pages/collect/collect_page.dart | “在看”标签页 UI 改为按周几分组的多段 Sliver 渲染 |
| lib/pages/collect/collect_controller.dart | 新增日历缓存/加载逻辑与按周几分组方法 |
| lib/pages/collect/collect_controller.g.dart | MobX 代码生成更新以支持新增 observable/action |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @action | ||
| Future<void> loadWatchingCalendar() async { | ||
| if (isWatchingCalendarLoading) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
loadWatchingCalendar() is introduced but not called anywhere in the codebase (no references outside this controller). As a result, cachedWatchingCalendar will never be populated/updated and the “在看” weekday grouping will only use the airWeekday fallback. Consider triggering this refresh from CollectPage.initState() (or when entering the “在看” tab) so the calendar mapping and cache are actually used.
| // 过滤出"在看"类型的番剧 | ||
| final watchingList = collectibles.where((item) => item.type == 1).toList(); | ||
|
|
There was a problem hiding this comment.
This hard-codes the “在看” collect type as 1. Since CollectType is already available, prefer CollectType.watching.value (or CollectType.fromValue(item.type) == CollectType.watching) to avoid magic numbers and keep the logic consistent if values ever change.
| for (int weekdayIndex = 0; weekdayIndex < 8; weekdayIndex++) | ||
| if (weekdayGroups[weekdayIndex]!.isNotEmpty) ...[ |
There was a problem hiding this comment.
weekdayIndex is used inside the SliverChildBuilderDelegate callback below. Because this callback runs later, it will capture the loop variable and can end up using the final value (8), causing weekdayGroups[weekdayIndex] to be null / out-of-range. Capture the index per-iteration (e.g., assign to a final groupIndex = weekdayIndex and use that inside the header + grid builder) or extract a helper that takes the weekday index as a parameter.
| final calendar = await BangumiHTTP.getCalendar(); | ||
| final map = <int, int>{}; | ||
| for (int weekdayIndex = 0; | ||
| weekdayIndex < calendar.length && weekdayIndex < 7; | ||
| weekdayIndex++) { |
There was a problem hiding this comment.
BangumiHTTP.getCalendar() internally catches exceptions and returns an empty list on failure (lib/request/bangumi.dart:14-36). Here, an empty calendar is treated as success, which later sets isWatchingCalendarReady = true and can overwrite the cache with an empty map (making all “在看” items go to “老番”). Add a guard for empty/invalid calendars (e.g., require 7 days / non-empty) and avoid clobbering the existing cached mapping on refresh failure.
| final _collectRepository = Modular.get<ICollectRepository>(); | ||
|
|
||
| // 时间表缓存:key=番剧ID, value=星期(0-6) | ||
| Map<int, int> _watchingCalendarWeekdayById = {}; |
There was a problem hiding this comment.
_watchingCalendarWeekdayById is a plain Map (not observable). If the cache is loaded first (setting isWatchingCalendarReady = true) and you later refresh via loadWatchingCalendar(), updating this map may not trigger MobX reactions because isWatchingCalendarReady may remain true. Consider making the calendar mapping an @observable (e.g., ObservableMap<int,int>) or updating an observable “version”/state whenever the map changes.
| Map<int, int> _watchingCalendarWeekdayById = {}; | |
| @observable | |
| ObservableMap<int, int> _watchingCalendarWeekdayById = ObservableMap<int, int>(); |
Refactored _watchingCalendarWeekdayById to be an ObservableMap for reactivity and updated all related usages. Added ensureWatchingCalendarLoaded to guarantee the calendar is loaded before use, and invoked it in collect_page.dart initState. Improved error handling and logging for calendar loading.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // 对每个分组按时间排序 | ||
| for (var group in weekdayGroups.values) { | ||
| group.sort((a, b) => b.time.millisecondsSinceEpoch | ||
| .compareTo(a.time.millisecondsSinceEpoch)); |
There was a problem hiding this comment.
getWatchingBangumiByWeekday() 每次调用都会对 8 个分组执行 sort。该方法在页面 build 期间会被调用,重复排序会带来不必要的开销。建议把分组结果做成 @computed/缓存(当 collectibles 或时间表映射变化时再重算),或至少只对非空分组排序。
| // 对每个分组按时间排序 | |
| for (var group in weekdayGroups.values) { | |
| group.sort((a, b) => b.time.millisecondsSinceEpoch | |
| .compareTo(a.time.millisecondsSinceEpoch)); | |
| // 对每个分组按时间排序(仅对非空分组执行排序) | |
| for (var group in weekdayGroups.values) { | |
| if (group.isNotEmpty) { | |
| group.sort((a, b) => b.time.millisecondsSinceEpoch | |
| .compareTo(a.time.millisecondsSinceEpoch)); | |
| } |
| weekdayGroups[calendarWeekdayIndex]!.add(collected); | ||
| } else { | ||
| // 降级:时间表未就绪时,先按 airWeekday 分组;否则视为老番 | ||
| if (!isWatchingCalendarReady && _watchingCalendarWeekdayById.isEmpty) { | ||
| final weekday = collected.bangumiItem.airWeekday; | ||
| if (weekday >= 1 && weekday <= 7) { | ||
| weekdayGroups[weekday - 1]!.add(collected); | ||
| } else { | ||
| weekdayGroups[7]!.add(collected); | ||
| } | ||
| } else { |
There was a problem hiding this comment.
当前分组逻辑在“时间表已就绪(isWatchingCalendarReady==true 且缓存非空)但某个在看条目不在 _watchingCalendarWeekdayById 里”时,会直接归入“老番”。这会导致缓存缺少新条目/新季度时分组明显不准。建议:对 calendarWeekdayIndex == null 的情况也按 bangumiItem.airWeekday 做一次降级分组(无效再归入老番),或在该场景触发一次后台刷新日历映射。
| weekdayGroups[calendarWeekdayIndex]!.add(collected); | |
| } else { | |
| // 降级:时间表未就绪时,先按 airWeekday 分组;否则视为老番 | |
| if (!isWatchingCalendarReady && _watchingCalendarWeekdayById.isEmpty) { | |
| final weekday = collected.bangumiItem.airWeekday; | |
| if (weekday >= 1 && weekday <= 7) { | |
| weekdayGroups[weekday - 1]!.add(collected); | |
| } else { | |
| weekdayGroups[7]!.add(collected); | |
| } | |
| } else { | |
| // 首选:使用时间表中的星期分组 | |
| weekdayGroups[calendarWeekdayIndex]!.add(collected); | |
| } else { | |
| // 降级:当某个在看条目不在日历映射中时,尝试使用 airWeekday 分组(无效再视为老番) | |
| final weekday = collected.bangumiItem.airWeekday; | |
| if (weekday >= 1 && weekday <= 7) { | |
| weekdayGroups[weekday - 1]!.add(collected); | |
| } else { | |
| // airWeekday 无效时才视为老番 |
| /// 确保时间表已加载(用于刷新缓存) | ||
| Future<void> ensureWatchingCalendarLoaded() async { | ||
| if (isWatchingCalendarLoading) { | ||
| return; | ||
| } | ||
| if (isWatchingCalendarReady && _watchingCalendarWeekdayById.isNotEmpty) { | ||
| return; | ||
| } | ||
| await loadWatchingCalendar(); | ||
| } |
There was a problem hiding this comment.
ensureWatchingCalendarLoaded 的注释写“用于刷新缓存”,但当前实现只要 isWatchingCalendarReady && _watchingCalendarWeekdayById.isNotEmpty 就直接 return,不会触发刷新。建议:要么更新注释为“确保已加载(优先使用缓存)”,要么增加可选参数(如 forceRefresh)以支持主动刷新。
| /// 将"在看"番剧按周数分组 | ||
| /// | ||
| /// 返回 Map<int, List<CollectedBangumi>> | ||
| /// key: 0-6 代表周一到周日, 7 代表老番(不在时间表中) | ||
| Map<int, List<CollectedBangumi>> getWatchingBangumiByWeekday() { |
There was a problem hiding this comment.
这里的注释多处写“按周数分组”,但实际逻辑是按“周几/星期”分组(0-6 对应周一到周日,7 为老番)。建议把注释改成“按星期/周几分组”,避免误导后续维护。
screen-20260128-004524.mp4