Skip to content

feat: 強化單字學習流程(搜尋、收藏、進度) - #4

Merged
github-world192 merged 2 commits into
mainfrom
github-world192-expand-app-features
Jul 9, 2026
Merged

github-world192 merged 2 commits into
mainfrom
github-world192-expand-app-features

Conversation

@github-world192

@github-world192 github-world192 commented Jul 9, 2026 •

Copy link
Copy Markdown
Owner

這個 App 目前能看單字,但缺少「學習過程」的核心能力。這次調整把單字列表升級成可查找、可追蹤、可回顧,讓使用者能更有效率地持續學習。

主要變更

  • 新增即時搜尋,快速篩出目標單字。
  • 新增收藏功能與「只看收藏」篩選,方便集中複習。
  • 新增已學習標記與進度條,點進單字詳情時自動記錄學習進度。
  • 收藏與已學習狀態使用 SharedPreferences 持久化。
  • 保留原本快取優先與離線提示機制,網路失敗時仍可使用快取資料。

其他調整

  • lib/main.dart 修正 lint 建議(super parameters、withValues)。
  • test/widget_test.dart 重寫 widget 測試,改為穩定可重現的 UI 驗證流程。
  • README.md 補上搜尋、收藏與進度追蹤功能說明。
  • pubspec.lock 更新為目前 Flutter 解析出的依賴鎖定版本。

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@vercel

vercel Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
vocabpass Ready Ready Preview, Comment Jul 9, 2026 3:14am

@coderabbitai

coderabbitai Bot commented Jul 9, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@github-world192, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 58 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0c7179b8-1c95-4400-9a92-cc05094d67d5

📥 Commits

Reviewing files that changed from the base of the PR and between ab13446 and 3e8e932.

⛔ Files ignored due to path filters (1)
  • pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • README.md
  • lib/main.dart
  • lib/vocabulary_list_screen.dart
  • test/widget_test.dart
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch github-world192-expand-app-features

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +61 to +64
setState(() {
_favoriteWords = favoriteWords.toSet();
_learnedWords = learnedWords.toSet();
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment on lines +61 to +64
setState(() {
_favoriteWords = favoriteWords.toSet();
_learnedWords = learnedWords.toSet();
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Suggested change
setState(() {
_favoriteWords = favoriteWords.toSet();
_learnedWords = learnedWords.toSet();
});
if (!mounted) {
return;
}
setState(() {
_favoriteWords = favoriteWords.toSet();
_learnedWords = learnedWords.toSet();
});

// 有快取資料,只顯示提示
_showCacheWarning();
}
_showCacheWarning();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>

@github-world192 github-world192 changed the title feat: 強化單字學習流程(搜尋/收藏/進度追蹤) feat: 強化單字學習流程(搜尋、收藏、進度) Jul 9, 2026
@github-world192
github-world192 merged commit f7b692f into main Jul 9, 2026
4 of 6 checks passed
@github-world192
github-world192 requested a review from Copilot July 9, 2026 13:49
@github-world192
github-world192 deleted the github-world192-expand-app-features branch July 9, 2026 13:49

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +145 to 149
const SnackBar(
content: Row(
children: [
Icon(Icons.offline_bolt, color: Colors.white),
SizedBox(width: 8),

This branch was successfully deployed

1 active deployment
Preview — 3e8e9320 Deployed Jul 9, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants