Skip to content

feat: simplify onboarding to 3 steps with permission UX improvements#71

Closed
hubo1989 wants to merge 3 commits into
mainfrom
Easeofuse
Closed

feat: simplify onboarding to 3 steps with permission UX improvements#71
hubo1989 wants to merge 3 commits into
mainfrom
Easeofuse

Conversation

@hubo1989
Copy link
Copy Markdown
Owner

@hubo1989 hubo1989 commented Mar 26, 2026

Summary

  • Reduce onboarding from 4 steps to 3 by removing the engine configuration step (PaddleOCR/MTranServer setup is available in Settings)
  • Add permission purpose descriptions so users understand why each permission is needed
  • Add "Skip for Now" button on permissions step with timeout hint after 30s polling
  • Add menu bar location guidance on the completion page
  • Show permission warning on completion page if user skipped permissions

Changes

  • OnboardingViewModel: 3-step structure, removed configuration properties/methods, added skipPermissions() and permissionCheckTimedOut
  • OnboardingPermissionsStepView: Permission subtitle descriptions, skip button, timeout hint
  • OnboardingCompleteStepView: Menu bar hint, skipped permissions warning
  • OnboardingComponents: OnboardingPermissionRow now accepts subtitle parameter
  • AppSettings: Added userSkippedPermissions persisted flag
  • Localization: Added 6 new strings (zh-Hans + en), removed 30+ configuration/paddleocr related strings
  • Deleted: OnboardingConfigurationStepView.swift (199 lines removed)

Test plan

  • Clear ScreenTranslate.onboardingCompleted in UserDefaults, relaunch app
  • Verify 3-step flow: Welcome → Permissions → Complete
  • Verify permission purpose descriptions display correctly
  • Verify "Skip for Now" button completes onboarding without permissions
  • Verify timeout hint appears after 30s on permissions step
  • Verify completion page shows menu bar hint and permission warning when applicable
  • Verify zh-Hans and en localizations are correct

Summary by CodeRabbit

发布说明

  • 新功能

    • 允许用户在引导期间“暂时跳过”权限请求并在完成时显示警告。
    • 添加权限检查超时提示与权限项补充说明。
  • 改进

    • 精简引导流程(移除可选配置步骤),并将引导窗口高度略微缩小以优化布局。
    • 跳过权限的选择会被保存至设置,完成页新增菜单栏使用提示与相关文案更新。

Reduce onboarding from 4 steps to 3 by removing the engine configuration
step (PaddleOCR/MTranServer setup moved to Settings). Add permission
purpose descriptions, skip-for-now option with timeout hint, and menubar
location guidance on completion page.
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 26, 2026

Warning

Rate limit exceeded

@hubo1989 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 11 minutes and 20 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ad55171-1c07-4e96-8c39-7dbc0c802ce5

📥 Commits

Reviewing files that changed from the base of the PR and between 26c5fba and 037263d.

📒 Files selected for processing (6)
  • ScreenTranslate/Features/Onboarding/OnboardingComponents.swift
  • ScreenTranslate/Features/Onboarding/OnboardingView.swift
  • ScreenTranslate/Features/Onboarding/OnboardingWindowController.swift
  • ScreenTranslate/Models/AppSettings.swift
  • ScreenTranslate/Resources/en.lproj/Localizable.strings
  • ScreenTranslate/Resources/zh-Hans.lproj/Localizable.strings
📝 Walkthrough

Walkthrough

精简引导流程为 3 步:移除配置/PaddleOCR 步骤,新增权限跳过逻辑与超时检测;在完成页显示菜单栏提示与权限未授予警告;更新相关视图、视图模型、本地化与持久化设置,窗口高度由 620 调整为 520。

Changes

Cohort / File(s) Summary
Onboarding core & window
ScreenTranslate/Features/Onboarding/OnboardingView.swift, ScreenTranslate/Features/Onboarding/OnboardingViewModel.swift, ScreenTranslate/Features/Onboarding/OnboardingWindowController.swift
移除可选配置步骤(totalSteps 4→3);新增 hasSkippedPermissionspermissionCheckTimedOut 状态与 skipPermissions() 方法;调整权限轮询超时逻辑;窗口高度 620→520。
Permissions & completion views
ScreenTranslate/Features/Onboarding/OnboardingPermissionsStepView.swift, ScreenTranslate/Features/Onboarding/OnboardingCompleteStepView.swift
权限步骤新增 permissionCheckTimedOut 输入与 onSkip 回调,替换导航按钮为自定义按钮组并增加“跳过权限”;完成页增加 menubar 提示行与在 hasSkippedPermissions == true 时显示权限警告块(图标+文字+样式)。
Removed configuration UI
ScreenTranslate/Features/Onboarding/OnboardingConfigurationStepView.swift
完全移除整个配置步骤视图及其 PaddleOCR/翻译测试相关子视图与逻辑。
Reusable components
ScreenTranslate/Features/Onboarding/OnboardingComponents.swift
OnboardingPermissionRow 增加 subtitle 参数并在标题下方以 caption 显示(保持原有授权/未授权行逻辑)。
Settings & localization
ScreenTranslate/Models/AppSettings.swift, ScreenTranslate/Resources/.../Localizable.strings
新增持久化布尔 userSkippedPermissions;新增权限超时提示、权限副标题、完成页 menubar 提示与权限警告等本地化键;移除与配置/PaddleOCR 及旧导航文案相关的本地化键。
Preview window timer refactor
ScreenTranslate/Features/Preview/PreviewWindow.swift
将 image-size 计数器与定时器提升为实例属性(lastImageSizeCounterimageSizeTimer),调整回调早期返回逻辑与计数比较位置。

Sequence Diagram(s)

sequenceDiagram
  participant User as "用户"
  participant View as "OnboardingView / Step Views"
  participant VM as "OnboardingViewModel"
  participant Sys as "系统权限 检查/API"
  participant Settings as "AppSettings (持久化)"

  User->>View: 触发请求权限或点击“跳过权限”
  View->>VM: 请求检查/轮询权限或调用 onSkip()
  VM->>Sys: 请求/轮询权限状态
  Sys-->>VM: 返回权限已授予/未授予
  alt 超时(30s)
    VM->>View: 设置 permissionCheckTimedOut = true
  end
  alt 用户选择跳过
    VM->>Settings: 设置 userSkippedPermissions = true
    VM->>View: 标记 hasSkippedPermissions 并 完成引导
  else 权限授予
    VM->>View: 允许继续下一步
  end
Loading

估计代码审查工作量

🎯 4 (Complex) | ⏱️ ~45 minutes

可能相关的拉取请求

概述

此拉取请求简化了引导流程,从4步减少至3步。移除了可选配置步骤,添加了权限跳过功能,并在完成步骤中显示权限警告。更新了UI组件以支持权限超时提示和跳过按钮,同时调整了本地化文案和应用窗口大小。

变更

引导流程与视图模型
OnboardingView.swift, OnboardingViewModel.swift, OnboardingWindowController.swift
移除配置步骤,将总步数从4减至3;添加权限跳过状态与超时检测;修改权限检查流程(删除PaddleOCR管理、翻译测试等);减少窗口高度从620至520;修改完成行为以仅持久化跳过权限状态。
引导步骤视图
OnboardingPermissionsStepView.swift, OnboardingCompleteStepView.swift, OnboardingConfigurationStepView.swift
为权限步骤添加超时提示与跳过按钮;在完成步骤显示菜单栏提示与权限警告;完全移除配置步骤视图及其嵌套的PaddleOCR配置部分。
可复用组件
OnboardingComponents.swift
扩展OnboardingPermissionRow以支持副标题显示,用于说明权限用途。
应用设置与本地化
AppSettings.swift, en.lproj/Localizable.strings, zh-Hans.lproj/Localizable.strings
添加userSkippedPermissions持久化设置;新增权限超时提示、权限副标题、菜单栏提示与权限警告的本地化字符串;移除配置步骤、PaddleOCR相关与通用导航按钮的旧有文案。

诗歌

🐰✨ 我在草丛里跳又跳,
三步路程更轻巧,
权限难来可先绕,
菜单栏里再去找,
胡萝卜庆祝新流程喵!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题清晰准确地概括了变更的主要内容——将onboarding流程从4步简化到3步,并改进权限相关的UX。
Docstring Coverage ✅ Passed Docstring coverage is 90.91% which is sufficient. The required threshold is 80.00%.

✏️ 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 Easeofuse

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

@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)
ScreenTranslate/Resources/en.lproj/Localizable.strings (1)

545-547: 可选:优化权限副标题语义一致性与可读性。

当前文案可用,但 capture & translateOCR text recognition 的表达稍显口语/重复,建议统一为更自然的产品文案。

建议文案(可选)
-"onboarding.permission.screen.recording.subtitle" = "For capturing screen content for OCR text recognition";
+"onboarding.permission.screen.recording.subtitle" = "Required to capture screen content for OCR.";

-"onboarding.permission.accessibility.subtitle" = "For registering global shortcuts to trigger capture & translate from any app";
+"onboarding.permission.accessibility.subtitle" = "Required to register global shortcuts for capture and translation in any app.";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ScreenTranslate/Resources/en.lproj/Localizable.strings` around lines 545 -
547, The permission subtitle strings are inconsistent and slightly informal;
update the values for "onboarding.permission.screen.recording.subtitle",
"onboarding.permission.accessibility", and
"onboarding.permission.accessibility.subtitle" to use consistent, user-facing
product language (e.g., replace "For capturing screen content for OCR text
recognition" with "Capture screen content for text recognition", change
"Accessibility" only if needed to a matched label like "Accessibility
permission", and replace "For registering global shortcuts to trigger capture &
translate from any app" with "Enable global shortcuts to capture and translate
from any app") so the tone and phrasing are concise and uniform across keys.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@ScreenTranslate/Resources/en.lproj/Localizable.strings`:
- Around line 545-547: The permission subtitle strings are inconsistent and
slightly informal; update the values for
"onboarding.permission.screen.recording.subtitle",
"onboarding.permission.accessibility", and
"onboarding.permission.accessibility.subtitle" to use consistent, user-facing
product language (e.g., replace "For capturing screen content for OCR text
recognition" with "Capture screen content for text recognition", change
"Accessibility" only if needed to a matched label like "Accessibility
permission", and replace "For registering global shortcuts to trigger capture &
translate from any app" with "Enable global shortcuts to capture and translate
from any app") so the tone and phrasing are concise and uniform across keys.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f8e6c20c-226c-4a5b-b4d0-78e536426c4b

📥 Commits

Reviewing files that changed from the base of the PR and between 40e49a5 and de2fe88.

📒 Files selected for processing (10)
  • ScreenTranslate/Features/Onboarding/OnboardingCompleteStepView.swift
  • ScreenTranslate/Features/Onboarding/OnboardingComponents.swift
  • ScreenTranslate/Features/Onboarding/OnboardingConfigurationStepView.swift
  • ScreenTranslate/Features/Onboarding/OnboardingPermissionsStepView.swift
  • ScreenTranslate/Features/Onboarding/OnboardingView.swift
  • ScreenTranslate/Features/Onboarding/OnboardingViewModel.swift
  • ScreenTranslate/Features/Onboarding/OnboardingWindowController.swift
  • ScreenTranslate/Models/AppSettings.swift
  • ScreenTranslate/Resources/en.lproj/Localizable.strings
  • ScreenTranslate/Resources/zh-Hans.lproj/Localizable.strings
💤 Files with no reviewable changes (1)
  • ScreenTranslate/Features/Onboarding/OnboardingConfigurationStepView.swift

Move lastCounter and timer references to class properties to avoid
sending non-Sendable values across isolation boundaries.
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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ScreenTranslate/Features/Preview/PreviewWindow.swift`:
- Around line 15-19: The imageSizeTimer is never invalidated, causing a resource
leak; update PreviewWindow to invalidate and nil out imageSizeTimer when the
preview is closed or the object is deallocated by adding cleanup in
closePreview() (call imageSizeTimer?.invalidate(); imageSizeTimer = nil) and/or
implement deinit to perform the same invalidation so the timer stops running
when the window is closed or PreviewWindow is released.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a0469503-18e7-46c4-a32f-27355acade12

📥 Commits

Reviewing files that changed from the base of the PR and between de2fe88 and 26c5fba.

📒 Files selected for processing (1)
  • ScreenTranslate/Features/Preview/PreviewWindow.swift

Comment on lines +15 to +19
/// Timer for observing image size changes
private var imageSizeTimer: Timer?

/// Tracks the last image size change counter value
private var lastImageSizeCounter: Int = 0
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Timer 未被清理导致资源泄漏。

imageSizeTimer 被创建后从未被 invalidate。当窗口关闭或释放时,定时器仍会继续运行(虽然因为 [weak self] 不会崩溃,但会持续消耗资源)。

建议添加 deinit 或在 closePreview() 中清理定时器:

🛠️ 建议修复方案
     /// Tracks the last image size change counter value
     private var lastImageSizeCounter: Int = 0

+    deinit {
+        imageSizeTimer?.invalidate()
+        imageSizeTimer = nil
+    }
+
     // MARK: - Initialization

或者在 closePreview() 中添加清理逻辑:

     `@MainActor`
     func closePreview() {
+        imageSizeTimer?.invalidate()
+        imageSizeTimer = nil
         // Delay state modification to avoid "Modifying state during view update" warning
         DispatchQueue.main.async { [weak self] in
             self?.viewModel.hide()
         }
         close()
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ScreenTranslate/Features/Preview/PreviewWindow.swift` around lines 15 - 19,
The imageSizeTimer is never invalidated, causing a resource leak; update
PreviewWindow to invalidate and nil out imageSizeTimer when the preview is
closed or the object is deallocated by adding cleanup in closePreview() (call
imageSizeTimer?.invalidate(); imageSizeTimer = nil) and/or implement deinit to
perform the same invalidation so the timer stops running when the window is
closed or PreviewWindow is released.

- Fix button calling both requestAction and openSettingsAction (caused
  wrong permission dialog to appear)
- Increase window height from 520 to 580 to fit all content
- Defer Keychain access on launch to avoid prompt during onboarding
- Add note about removing and re-adding app for permission changes
@hubo1989 hubo1989 closed this Mar 26, 2026
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