Skip to content

Refactor toast notifications and update settings UI#4

Merged
Merack merged 5 commits into
mainfrom
dev
Jun 6, 2026
Merged

Refactor toast notifications and update settings UI#4
Merack merged 5 commits into
mainfrom
dev

Conversation

@Merack
Copy link
Copy Markdown
Owner

@Merack Merack commented Jun 6, 2026

主要改动

本次PR包含以下核心改进:

1. 统一Toast提示封装

  • 创建 ToastUtil 工具类,统一管理所有Toast提示
  • 替换所有 Get.snackbar() 调用为 ToastUtil.show()
  • 使用原生 fluttertoast 替代自定义snackbar,更符合系统UI设计
  • 自动处理超长路径截断,避免Android系统toast被裁剪

涉及文件:

  • lib/page/main/controller.dart
  • lib/page/setting/controller.dart
  • lib/page/setting/state.dart
  • lib/page/setting/widgets/*
  • lib/page/sound_settings/controller.dart
  • lib/utils/toast_util.dart (新文件)

2. 优化设置页面布局

  • 重组设置分组结构,提高逻辑清晰度
  • 将"番茄时钟设置"移至顶部(始终显示,供用户预先配置)
  • 合并"显示设置"为"显示与行为",将"自动开始下一个"选项移入
  • 微休息设置与随机提示音设置合并

3. 调整默认计时模式

  • 默认计时模式改为 pomodoro (番茄时钟)
  • 调整首页模式选择器UI顺序,番茄时钟优先显示

4. 依赖更新

  • 新增: fluttertoast: ^9.1.0
  • 更新Flutter最低版本: ^3.41.0

变更统计

  • 新增: 1个新文件 (toast_util.dart)
  • 修改: 11个文件
  • 核心逻辑: 无变化,仅代码优化和UI重组

Summary by CodeRabbit

  • New Features

    • Reorganized Settings page with dedicated Pomodoro timer configuration section at the top.
    • Improved notification system with toast messages for better user feedback.
  • Changes

    • Default timer mode is now set to Pomodoro.
    • Notification style updated throughout the app for consistency.
  • Chores

    • Added fluttertoast library dependency.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 6, 2026

Too many files changed? Review this PR in Change Stack to see how the pieces fit before you dive in.

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a ToastUtil wrapper around the fluttertoast library and systematically replaces Get.snackbar notifications across the application with toast-based feedback. The default timer mode is switched from random_break to pomodoro, and the settings page layout is reorganized to reflect this priority.

Changes

Toast Notification Refactor and Settings Reorganization

Layer / File(s) Summary
Toast utility infrastructure
lib/utils/toast_util.dart, pubspec.yaml
Introduces ToastUtil class with a static show method that wraps Fluttertoast.showToast, re-exports Toast length constants for caller convenience, and adds the fluttertoast ^9.1.0 dependency.
Replace snackbars with toasts in core controllers
lib/page/main/controller.dart, lib/page/setting/controller.dart, lib/page/setting/state.dart
Imports ToastUtil and converts snackbar calls to toast notifications in back-press handling, settings validation/save/reset flows, backup/restore status messages, and micro-break interval validation. Backup success paths now shorten the displayed file path by splitting on /0/.
Replace snackbars with toasts in settings widgets
lib/page/setting/widgets/data_settings.dart, lib/page/setting/widgets/developer_settings.dart, lib/page/setting/widgets/permission_settings.dart, lib/page/sound_settings/controller.dart
Imports ToastUtil and updates DataSettings, DeveloperSettings, PermissionSettings, and SoundSettingsController to show user feedback via toast notifications for database reset, test data generation, permission denial, and audio/sound errors.
Default timer mode and settings page reorganization
lib/config/storage_keys.dart, lib/page/home/view.dart, lib/page/setting/view.dart
Changes default timer mode constant from 'random_break' to 'pomodoro', reorders timer mode chips in home page so pomodoro appears first, and reorganizes settings sections to place pomodoro settings near the top and group display/behavior toggles together.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Toast to the refactor, hooray!
Gone are snackbars cluttering the way,
Now pomodoros take the lead,
Fresh toasts rise to suit each need,
Settings aligned, brighter than before!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: refactoring toast notifications (replacing Get.snackbar with ToastUtil throughout multiple files) and updating the settings UI layout (reorganizing sections, reordering components).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

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 and usage tips.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a unified ToastUtil wrapper using the fluttertoast package to replace Get.snackbar notifications across the app. It also changes the default timer mode to Pomodoro, reorders the home page mode chips, and reorganizes the settings page layout. Feedback is provided to improve the robustness of the backup path truncation logic and to enhance the user experience in settings validation by using error messages instead of silently overriding conflicting interval inputs.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +272 to +273
// 原生 Toast 对超长无空格路径会截断,只展示外部存储根(/0/)之后的关键路径
final shownPath = backupPath.split('/0/').last;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

使用 split('/0/').last 来截断备份路径可能不够健壮。如果路径中包含其他带有 /0/ 的片段(例如 Android 应用私有存储路径 /data/user/0/... 或用户创建的名为 0 的文件夹),它会进行错误的分割,从而导致显示不完整或具有误导性的路径。

更健壮的方法是专门检查并移除标准的 Android 外部存储根路径前缀(/storage/emulated/0/)。

Suggested change
// 原生 Toast 对超长无空格路径会截断,只展示外部存储根(/0/)之后的关键路径
final shownPath = backupPath.split('/0/').last;
// 原生 Toast 对超长无空格路径会截断,只展示外部存储根(/storage/emulated/0/)之后的关键路径
final shownPath = backupPath.startsWith('/storage/emulated/0/')
? backupPath.replaceFirst('/storage/emulated/0/', '')
: backupPath;

Comment on lines 138 to 142
if (microBreakIntervalMinMinutes.value > microBreakIntervalMaxMinutes.value) {
microBreakIntervalMinMinutes.value = microBreakIntervalMaxMinutes.value;
microBreakIntervalMinController.text = microBreakIntervalMinMinutes.value.toString();
Get.snackbar(
'设置已调整',
'最小间隔不能大于最大间隔,已调整为相同值',
snackPosition: SnackPosition.TOP,
barBlur: 100,
duration: Duration(seconds: 2),
);
ToastUtil.show('设置已调整', '最小间隔不能大于最大间隔,已调整为相同值');
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

在失去焦点时静默覆盖用户的输入并弹出 Toast 提示,可能会给用户带来非常挫败的体验。例如,当用户想要同时调大最小和最大间隔(例如在当前最大间隔为 5 的情况下,将最小间隔改为 10,最大间隔改为 15),一旦他们编辑完最小间隔并切换焦点到最大间隔输入框时,他们的输入就会被强制重置回 5

相比于自动调整数值并弹出 Toast,更好的做法是设置一个验证错误信息(microBreakIntervalMinError)并将表单标记为无效(isValid = false)。这样可以允许用户在保存前自然地编辑这两个字段并解决冲突。

      if (microBreakIntervalMinMinutes.value > microBreakIntervalMaxMinutes.value) {
        microBreakIntervalMinError.value = '最小间隔不能大于最大间隔';
        isValid = false;
      }

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
lib/utils/toast_util.dart (1)

14-24: ⚡ Quick win

Consider handling edge cases for empty title or message.

The current logic concatenates title and message with a newline when title is non-empty. If a caller provides a non-empty title but an empty message, the toast will display with a trailing newline (e.g., "Title\n"). While all current call sites provide both parameters, defensive handling would improve robustness.

🛡️ Suggested defensive implementation
 static void show(
   String title,
   String message, {
   Toast toastLength = Toast.LENGTH_SHORT,
 }) {
+  final displayMsg = title.isEmpty 
+      ? message 
+      : (message.isEmpty ? title : '$title\n$message');
   Fluttertoast.showToast(
-    msg: title.isEmpty ? message : '$title\n$message',
+    msg: displayMsg,
     toastLength: toastLength,
     gravity: ToastGravity.TOP,
   );
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/utils/toast_util.dart` around lines 14 - 24, The show method concatenates
title and message unconditionally when title is non-empty, which can produce a
trailing newline if message is empty; update the ToastUtil.show implementation
to build the toast text defensively: use title alone when message.isEmpty, use
message alone when title.isEmpty, and use '$title\n$message' only when both are
non-empty before calling Fluttertoast.showToast (reference the static show
function and the Fluttertoast.showToast call and parameters toastLength and
gravity).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@lib/utils/toast_util.dart`:
- Around line 14-24: The show method concatenates title and message
unconditionally when title is non-empty, which can produce a trailing newline if
message is empty; update the ToastUtil.show implementation to build the toast
text defensively: use title alone when message.isEmpty, use message alone when
title.isEmpty, and use '$title\n$message' only when both are non-empty before
calling Fluttertoast.showToast (reference the static show function and the
Fluttertoast.showToast call and parameters toastLength and gravity).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 04acd83a-c814-4188-b61c-94fa91680ffa

📥 Commits

Reviewing files that changed from the base of the PR and between 2403734 and d6edbae.

⛔ Files ignored due to path filters (1)
  • pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • lib/config/storage_keys.dart
  • lib/page/home/view.dart
  • lib/page/main/controller.dart
  • lib/page/setting/controller.dart
  • lib/page/setting/state.dart
  • lib/page/setting/view.dart
  • lib/page/setting/widgets/data_settings.dart
  • lib/page/setting/widgets/developer_settings.dart
  • lib/page/setting/widgets/permission_settings.dart
  • lib/page/sound_settings/controller.dart
  • lib/utils/toast_util.dart
  • pubspec.yaml

@Merack Merack merged commit 2cf3757 into main Jun 6, 2026
2 checks passed
@Merack Merack deleted the dev branch June 6, 2026 07:14
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.

1 participant