feat: 強化單字學習流程(搜尋、收藏、進度) - #4
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 58 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (4)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 20dc1900a2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| setState(() { | ||
| _favoriteWords = favoriteWords.toSet(); | ||
| _learnedWords = learnedWords.toSet(); | ||
| }); |
There was a problem hiding this comment.
Guard async word-state loads before updating state
If the user opens a vocabulary level and navigates back before SharedPreferences.getInstance() finishes, this newly added async path still calls setState after the State has been disposed, which can throw setState() called after dispose() and interrupt the app. The network success path already checks mounted; add the same guard before updating _favoriteWords/_learnedWords after the await.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
2 issues found and verified against the latest diff
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="lib/vocabulary_list_screen.dart">
<violation number="1" location="lib/vocabulary_list_screen.dart:61">
P2: Leaving this screen during startup can trigger `setState() called after dispose()` while loading saved favorites/learned words. Add a `mounted` guard after the SharedPreferences await before updating state.</violation>
<violation number="2" location="lib/vocabulary_list_screen.dart:128">
P2: Manual refresh can leave the screen stuck on the loading spinner when cached data exists and the network returns a non-200 response. This branch shows the cache warning but never clears `_isLoading`; the catch branch has the same path, so consider resetting loading before showing cached data.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| setState(() { | ||
| _favoriteWords = favoriteWords.toSet(); | ||
| _learnedWords = learnedWords.toSet(); | ||
| }); |
There was a problem hiding this comment.
P2: Leaving this screen during startup can trigger setState() called after dispose() while loading saved favorites/learned words. Add a mounted guard after the SharedPreferences await before updating state.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/vocabulary_list_screen.dart, line 61:
<comment>Leaving this screen during startup can trigger `setState() called after dispose()` while loading saved favorites/learned words. Add a `mounted` guard after the SharedPreferences await before updating state.</comment>
<file context>
@@ -43,11 +50,33 @@ class _VocabularyListScreenState extends State<VocabularyListScreen> {
+ final prefs = await SharedPreferences.getInstance();
+ final favoriteWords = prefs.getStringList(_favoriteWordsKey) ?? <String>[];
+ final learnedWords = prefs.getStringList(_learnedWordsKey) ?? <String>[];
+ setState(() {
+ _favoriteWords = favoriteWords.toSet();
+ _learnedWords = learnedWords.toSet();
</file context>
| setState(() { | |
| _favoriteWords = favoriteWords.toSet(); | |
| _learnedWords = learnedWords.toSet(); | |
| }); | |
| if (!mounted) { | |
| return; | |
| } | |
| setState(() { | |
| _favoriteWords = favoriteWords.toSet(); | |
| _learnedWords = learnedWords.toSet(); | |
| }); |
| // 有快取資料,只顯示提示 | ||
| _showCacheWarning(); | ||
| } | ||
| _showCacheWarning(); |
There was a problem hiding this comment.
P2: Manual refresh can leave the screen stuck on the loading spinner when cached data exists and the network returns a non-200 response. This branch shows the cache warning but never clears _isLoading; the catch branch has the same path, so consider resetting loading before showing cached data.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At lib/vocabulary_list_screen.dart, line 128:
<comment>Manual refresh can leave the screen stuck on the loading spinner when cached data exists and the network returns a non-200 response. This branch shows the cache warning but never clears `_isLoading`; the catch branch has the same path, so consider resetting loading before showing cached data.</comment>
<file context>
@@ -94,54 +119,44 @@ class _VocabularyListScreenState extends State<VocabularyListScreen> {
- // 有快取資料,只顯示提示
- _showCacheWarning();
- }
+ _showCacheWarning();
}
} catch (e) {
</file context>
There was a problem hiding this comment.
Pull request overview
此 PR 將單字列表從「純瀏覽」升級為「可搜尋、可收藏、可追蹤學習進度」的學習流程,並以 SharedPreferences 將收藏/已學習狀態持久化,讓使用者能更有效率地回顧與累積進度。
Changes:
- 在單字列表加入即時搜尋、只看收藏篩選、收藏切換,以及已學習進度統計/進度條。
- 點進單字詳情前自動標記為已學習,並將收藏/學習狀態持久化到 SharedPreferences。
- 更新 widget 測試流程與 README 說明,同步提交新的依賴鎖定版本。
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| lib/vocabulary_list_screen.dart | 新增搜尋/收藏/學習進度邏輯與 UI,並以 SharedPreferences 持久化狀態 |
| lib/main.dart | 套用 lint 相關調整(super parameters、色彩 API 調整) |
| test/widget_test.dart | 重寫 widget 測試,改為可重現的 UI 驗證 |
| README.md | 補充搜尋、收藏、進度追蹤功能說明 |
| pubspec.lock | 更新依賴鎖檔版本與 SDK metadata |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const SnackBar( | ||
| content: Row( | ||
| children: [ | ||
| Icon(Icons.offline_bolt, color: Colors.white), | ||
| SizedBox(width: 8), |
這個 App 目前能看單字,但缺少「學習過程」的核心能力。這次調整把單字列表升級成可查找、可追蹤、可回顧,讓使用者能更有效率地持續學習。
主要變更
其他調整
lib/main.dart修正 lint 建議(super parameters、withValues)。test/widget_test.dart重寫 widget 測試,改為穩定可重現的 UI 驗證流程。README.md補上搜尋、收藏與進度追蹤功能說明。pubspec.lock更新為目前 Flutter 解析出的依賴鎖定版本。