Skip to content

feat(galgame): 新增首屏教程引导与进度持久化#1179

Merged
wehos merged 25 commits into
Project-N-E-K-O:mainfrom
MomiJiSan:feat/galgame-tutorial-guide
May 7, 2026
Merged

feat(galgame): 新增首屏教程引导与进度持久化#1179
wehos merged 25 commits into
Project-N-E-K-O:mainfrom
MomiJiSan:feat/galgame-tutorial-guide

Conversation

@MomiJiSan
Copy link
Copy Markdown
Contributor

@MomiJiSan MomiJiSan commented May 6, 2026

变更说明

为 galgame 插件新增首屏教程引导,将原有固定 4 步引导扩展为动态 4-7 步,并增加教程进度持久化能力。用户首次进入插件时可以按依赖安装、游戏窗口选择、截图校准、开始识别等步骤完成基础配置。

主要改动

  • 新增教程进度存储键 tutorial_progress
    • GET /plugin/{plugin_id}/ui-api/tutorial/status
    • POST /plugin/{plugin_id}/ui-api/tutorial/progress
    • DXcam 截图依赖安装
    • 启动或恢复游戏
    • 刷新窗口
    • 选择游戏窗口
    • 校准截图区域
    • 开始识别
  • 依赖已就绪或当前平台不支持自动安装时,自动跳过对应依赖步骤
  • 从引导页点击 RapidOCR / DXcam 安装时:
    • 自动退出 onboarding
    • 展开高级设置
    • 打开依赖安装模块
    • 切换到对应安装页签
    • 滚动到安装面板
  • 高级设置中新增“重新打开设置引导”入口
  • 增强 localStorage 容错,避免受限 WebView / 隐私模式中断初始化或安装流程
  • 补充中英文教程引导文案
  • 调整引导步骤布局,适配动态 4-7 步展示

验证

  • i18n JSON 解析通过
  • uv run python -m pytest plugin\tests\unit\plugins\test_galgame_service.py

Summary by CodeRabbit

  • 文档

    • 新增中文“快速开始”指南,涵盖 OCR/截图后端选择、模型下载与配置、窗口检测与校准、识别模式与常见问题。
  • 新功能

    • 支持 RapidOCR 模型一键下载(含校验、进度、重试与错误提示)及相应安装任务 UI。
    • 服务端/客户端同步的教程进度持久化与公开 API,支持查询、保存、重置首-run 引导状态。
  • 本地化

    • 扩展首-run、安装与下载相关多语言文案(中/英/日/韩/俄)。
  • 样式 / 布局

    • 优化首-run 响应式布局,新增重置教程与下载按钮等界面元素。

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2e3d4f90-c1ab-4420-8117-1d4d37f560f4

📥 Commits

Reviewing files that changed from the base of the PR and between 744b622 and 5adecdf.

📒 Files selected for processing (6)
  • plugin/plugins/galgame_plugin/i18n/ui/en.json
  • plugin/plugins/galgame_plugin/i18n/ui/ja.json
  • plugin/plugins/galgame_plugin/i18n/ui/ko.json
  • plugin/plugins/galgame_plugin/i18n/ui/ru.json
  • plugin/plugins/galgame_plugin/rapidocr_support.py
  • plugin/plugins/galgame_plugin/static/main.js
🚧 Files skipped from review as they are similar to previous changes (5)
  • plugin/plugins/galgame_plugin/rapidocr_support.py
  • plugin/plugins/galgame_plugin/i18n/ui/ja.json
  • plugin/plugins/galgame_plugin/i18n/ui/en.json
  • plugin/plugins/galgame_plugin/i18n/ui/ko.json
  • plugin/plugins/galgame_plugin/static/main.js

Walkthrough

新增首-run 教程进度持久化与 RapidOCR 模型发现/下载支持,扩展后端安装路由与插件入口,前端首-run/onboarding 与本地存储抽象、i18n 文案、样式与测试,并加入中文快速开始文档喵。

Changes

Tutorial Onboarding + RapidOCR Models

Layer / File(s) Summary
Plugin manifest
plugin/plugins/galgame_plugin/plugin.toml
新增 plugin.ui 快速开始条目并调整 RapidOCR 默认配置为 lang_type="japan", ocr_version="PP-OCRv4", model_type="mobile"
Data Shape / Store Keys
plugin/plugins/galgame_plugin/models.py, plugin/plugins/galgame_plugin/store.py
新增 STORE_TUTORIAL_PROGRESS 并在 GalgameStore 中添加 load_tutorial_progress()save_tutorial_progress(),用于持久化教程进度。
Backend routes / API
plugin/plugins/galgame_plugin/install_routes.py
在后端注册 rapidocr_models install-kind 并新增 rapidocr-models start/latest/get/stream 路由;实现 /ui-api/tutorial/status/ui-api/tutorial/progress 端点,包含读写封装与归一化规则。
RapidOCR core
plugin/plugins/galgame_plugin/rapidocr_support.py
引入模型注册表与候选命名解析、required_rapidocr_model_files/missing_rapidocr_model_filesinspect_rapidocr_installation 扩展以及异步 download_rapidocr_models(.part 下载、SHA-256 校验、进度回调与任务状态写入)。
Plugin entry / Install kinds
plugin/plugins/galgame_plugin/__init__.py, plugin/plugins/galgame_plugin/install_tasks.py
在插件中加入 _rapidocr_models_lockgalgame_download_rapidocr_models 入口;将 rapidocr_models 添加到 INSTALL_KINDS 并处理同步与错误/刷新逻辑。
Frontend logic
plugin/plugins/galgame_plugin/static/main.js
新增本地存储抽象(storageGet/Set/Remove)、tutorial API 常量與超时、fetchTutorialProgress/saveTutorialProgress/resetTutorialGuide、首-run 计算/渲染重构、downloadRapidOcrModelsrestoreRapidOcrModelsState、以及持久化 install task id 與 skip 标志。
Frontend markup
plugin/plugins/galgame_plugin/static/index.html
新增 resetTutorialBtn(高级设置)與 rapidocrModelsDownloadBtn(RapidOCR 安装面板)按钮。
Frontend styles
plugin/plugins/galgame_plugin/static/style.css
首-run 步骤改为响应式 auto-fill 网格,新增两栏/单栏断点与 .advanced-guide-row 对齐样式。
I18n
plugin/plugins/galgame_plugin/i18n/ui/*.json
在多语言包中新增/扩展大量首-run、安装与 RapidOCR 缺失模型下载相关键(ui.first_run.*ui.install.rapidocr.download_models.*、bundled/unavailable、pyautogui、flash hint、ui.common.none_value 等)。
Docs
plugin/plugins/galgame_plugin/docs/quickstart.md
新增中文“快速开始”文档,覆盖 OCR 引擎/模型、截图后端、窗口选择/校准、识别模式、诊断面板与常见问题。
Tests
plugin/tests/unit/plugins/test_galgame_ocr_reader.py
新增测试分支以强制覆盖 legacy RapidOCR 安装检测路径(通过 monkeypatch 找不到 bundling spec)。

Sequence Diagram

sequenceDiagram
    participant User as "用户"
    participant UI as "前端(UI)"
    participant Server as "后端(API)"
    participant Store as "持久化(Store)"
    participant Local as "本地存储"

    User->>UI: 打开插件首次运行
    UI->>Server: GET /plugin/{id}/ui-api/tutorial/status
    Server->>Store: 读取 tutorial_progress
    Store-->>Server: 返回进度
    Server-->>UI: 返回进度 JSON
    UI->>Local: 读取 skip 标志
    Local-->>UI: 返回 skip 值

    alt 未完成 且 未跳过
        UI->>User: 显示入门引导
        User->>UI: 触发安装/校准/下载模型
        UI->>Local: persist 安装任务 id / skip 标志
        UI->>Server: POST /plugin/{id}/ui-api/tutorial/progress
        Server->>Store: 写入 tutorial_progress
        Store-->>Server: 确认保存
        Server-->>UI: 返回成功
        UI->>Server: POST /plugin/{id}/ui-api/rapidocr-models (start)
        Server->>Server: 调度 download_rapidocr_models 任务
        Server-->>UI: 返回 task id
        UI->>Server: GET /.../rapidocr-models/{task_id}/stream
        Server->>UI: SSE 流式推送下载进度事件
    else 已完成 或 已跳过
        UI->>UI: 隐藏入门引导,显示主面板
    end

    User->>UI: 点击重置教程
    UI->>Local: 清除 skip 标志
    UI->>Server: POST /plugin/{id}/ui-api/tutorial/progress (reset)
    Server->>Store: 重置持久化进度
    Store-->>Server: 确认
    Server-->>UI: 返回成功
    UI->>UI: 重新显示入门引导
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • wehos 喵

Poem

新手引导亮晶晶,模型下载稳当行喵,
前后端同步小爪印,进度保存不迷路喵,
文案样式都更新,重置再来心安稳喵,
校验哈希护文件,失败重试不慌张喵,
快速开始一键起步,游玩助手陪你喵。

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR标题「feat(galgame): 新增首屏教程引导与进度持久化」准确反映了本次变更的核心目标,涵盖了教程引导系统与进度持久化两大主要功能点。
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.


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

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

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: 6fea55aa42

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +1703 to +1704
const shouldHideOnboarding = advancedOpen || allDone || readyToStart;
const shouldHideMainGuide = advancedOpen || allDone;
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 Allow reset flow to actually reopen onboarding

Do not force-hide onboarding when advanced settings are open during the reset flow. reset_tutorial is triggered from the Advanced Settings panel, but renderFirstRunGuide immediately hides #onboardingView whenever advancedOpen is true, so the just-reset guide disappears again on the next refresh and the “Reopen Setup Guide” action appears non-functional unless users manually close Advanced Settings first.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

已经在 renderFirstRunGuideforceShowOnboarding 守住了喵:line 1758 if (shouldHideOnboarding && !forceShowOnboarding)、line 1769、line 1788 都加了 !forceShowOnboarding 短路,resetTutorialGuide() 会同时把 forceShowOnboarding=trueonboardingDismissed=falseclearSkipOnboarding(),所以即使 advancedOpen 仍然是 true,下一帧渲染也不会被自动条件再吃掉了。Codex 当时看到的代码已经过迭代,标记 resolved。

Copy link
Copy Markdown
Contributor

@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: 5

🧹 Nitpick comments (2)
plugin/plugins/galgame_plugin/static/style.css (2)

178-178: ⚡ Quick win

auto-fill 可能产生幽灵空列,建议改为 auto-fit 喵~

.first-run-steps 使用 auto-fill 时,若当前步骤数(4–7 步)少于容器能容纳的列数,多余的空列轨道会被保留并占据布局空间,导致已有步骤卡片无法自动拉伸填满行宽。换成 auto-fit 后,空轨道会被折叠,各步骤卡片均匀撑满容器,视觉效果更整齐喵!

✨ 建议修改
-  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
+  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));

同样的问题也存在于第 1874 行的 .onboarding-steps 喵。

🤖 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 `@plugin/plugins/galgame_plugin/static/style.css` at line 178, Replace the
grid-template-columns value using auto-fill with auto-fit for the selectors
mentioned: change grid-template-columns: repeat(auto-fill, minmax(180px, 1fr))
to use repeat(auto-fit, minmax(180px, 1fr)) so that .first-run-steps and
.onboarding-steps collapse empty grid tracks and let step cards stretch to fill
the row evenly; update both occurrences (the rule for .first-run-steps and the
rule for .onboarding-steps) accordingly.

1819-1821: ⚡ Quick win

1100px 断点把 .onboarding-steps 强制为单列,时机太早了喵~

.onboarding-card 的宽度被限制在 min(640px, calc(100vw - 32px)),因此即使在 1100px 的视口下卡片仍为 640px 宽,repeat(auto-fill/fit, minmax(180px, 1fr)) 本可容纳约 3 列。在这个断点就把步骤强制为 1fr(单列),会让 4–7 个步骤在桌面宽屏上也变成一列超长列表,体验有点糟糕喵。

建议把这条规则改为跟随卡片自身的响应临界点(约 ≤640px),而不是跟随整体布局的 1100px 断点喵:

✨ 建议修改
`@media` (max-width: 1100px) {
  .capture-profile-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .ocr-pipeline-steps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .first-run-guide {
    grid-template-columns: 1fr 1fr;
  }

- .onboarding-steps {
-   grid-template-columns: 1fr;
- }

  .first-run-actions {
    grid-column: 1 / -1;
    justify-content: flex-start;
  }
}

+@media (max-width: 640px) {
+  .onboarding-steps {
+    grid-template-columns: 1fr;
+  }
+}
🤖 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 `@plugin/plugins/galgame_plugin/static/style.css` around lines 1819 - 1821, 当前在
1100px 断点将 .onboarding-steps 强制为单列会在宽屏上把本可展示多列的步骤压成超长单列;把这条规则移出/删除该 1100px
媒体查询并改为在与卡片自身响应阈值一致的断点(约 max-width:640px 或跟随 .onboarding-card 的 min(640px,
calc(100vw - 32px)) 临界点)下才将 .onboarding-steps 的 grid-template-columns 设为
1fr,这样可以保留 repeat(auto-fill/fit, minmax(180px, 1fr)) 在 >640px
时的多列布局并仅在卡片变窄时切换为单列。
🤖 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.

Inline comments:
In `@plugin/plugins/galgame_plugin/docs/quickstart.md`:
- Line 3: Update the opening sentence in quickstart.md ("三步设置 OCR 截图识别,让猫娘陪你一起玩
Galgame。") to correctly reflect the number of subsequent sections—either change
it to "按步骤完成配置 OCR 截图识别,让猫娘陪你一起玩 Galgame。" or to "九步完成配置 OCR 截图识别,让猫娘陪你一起玩
Galgame。" so the header matches the actual content; locate and edit that exact
string in plugin/plugins/galgame_plugin/docs/quickstart.md.

In `@plugin/plugins/galgame_plugin/install_routes.py`:
- Around line 583-587: 当前 _tutorial_progress_path 函数直接读写文件绕过了统一的持久层,导致与已有的
STORE_TUTORIAL_PROGRESS 和 GalgameStore.load_tutorial_progress /
GalgameStore.save_tutorial_progress 分叉;请删除或不再使用 _tutorial_progress_path
的直接文件读写逻辑,改为通过 GalgameStore(调用 GalgameStore.load_tutorial_progress 和
GalgameStore.save_tutorial_progress,并使用 STORE_TUTORIAL_PROGRESS
作为键或标识)来加载和保存教程进度,确保所有读写都走同一套 Store 接口以避免状态不一致。
- Around line 601-612: The helper _write_tutorial_progress currently swallows
all exceptions (logging only) which lets save_tutorial_progress always return
success; change the flow so failures are propagated and reported: make
_write_tutorial_progress raise the caught exception (or return a boolean/error)
instead of only logging (retain logger.warning with exc_info), and update
save_tutorial_progress to catch that error and return an explicit failure result
(ok: false) to the frontend; apply the same fix to the other copy of this logic
referenced around the second occurrence (the other
_write_tutorial_progress/save_tutorial_progress usage).

In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 6637-6657: saveTutorialProgress currently reads
latestTutorialProgress then merges and posts, causing race conditions when
called concurrently; serialize saves by introducing a per-module pending promise
or mutex used inside saveTutorialProgress so each call awaits the previous save
before merging and posting, and always re-read/merge against the up-to-date
latestTutorialProgress (the in-memory variable) immediately before
JSON.stringify and fetch; reference saveTutorialProgress and
latestTutorialProgress to locate where to await the prior pending save, perform
the final merge, then send and update latestTutorialProgress.
- Around line 1703-1725: The onboarding is being immediately hidden by the
automatic conditions (readyToStart/allDone) after resetTutorialGuide() triggers
a refresh; introduce a force-show flag (e.g., forceShowOnboarding) that
resetTutorialGuide() sets to true and have the visibility checks respect it by
excluding it from the hide branches: update the
shouldHideOnboarding/shouldHideMainGuide checks used in the onboardingView and
node hide logic to only hide when !forceShowOnboarding (for example: if
(shouldHideOnboarding && !forceShowOnboarding) and if (shouldHideMainGuide &&
!forceShowOnboarding)); ensure resetTutorialGuide() sets forceShowOnboarding =
true and that the normal dismiss/close flows clear forceShowOnboarding (e.g.,
when onboardingDismissed becomes true or user explicitly closes) so manual
reopen works as intended while preserving existing functions like
readSkipOnboarding(), onboardingDismissed, node, stepsNode,
latestTutorialProgress and saveTutorialProgress.

---

Nitpick comments:
In `@plugin/plugins/galgame_plugin/static/style.css`:
- Line 178: Replace the grid-template-columns value using auto-fill with
auto-fit for the selectors mentioned: change grid-template-columns:
repeat(auto-fill, minmax(180px, 1fr)) to use repeat(auto-fit, minmax(180px,
1fr)) so that .first-run-steps and .onboarding-steps collapse empty grid tracks
and let step cards stretch to fill the row evenly; update both occurrences (the
rule for .first-run-steps and the rule for .onboarding-steps) accordingly.
- Around line 1819-1821: 当前在 1100px 断点将 .onboarding-steps
强制为单列会在宽屏上把本可展示多列的步骤压成超长单列;把这条规则移出/删除该 1100px 媒体查询并改为在与卡片自身响应阈值一致的断点(约
max-width:640px 或跟随 .onboarding-card 的 min(640px, calc(100vw - 32px)) 临界点)下才将
.onboarding-steps 的 grid-template-columns 设为 1fr,这样可以保留 repeat(auto-fill/fit,
minmax(180px, 1fr)) 在 >640px 时的多列布局并仅在卡片变窄时切换为单列。
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 57b874af-8701-43ac-b88e-4ed9af4afa5e

📥 Commits

Reviewing files that changed from the base of the PR and between 914dbb5 and 6fea55a.

📒 Files selected for processing (10)
  • plugin/plugins/galgame_plugin/docs/quickstart.md
  • plugin/plugins/galgame_plugin/i18n/ui/en.json
  • plugin/plugins/galgame_plugin/i18n/ui/zh-CN.json
  • plugin/plugins/galgame_plugin/install_routes.py
  • plugin/plugins/galgame_plugin/models.py
  • plugin/plugins/galgame_plugin/plugin.toml
  • plugin/plugins/galgame_plugin/static/index.html
  • plugin/plugins/galgame_plugin/static/main.js
  • plugin/plugins/galgame_plugin/static/style.css
  • plugin/plugins/galgame_plugin/store.py

Comment thread plugin/plugins/galgame_plugin/docs/quickstart.md Outdated
Comment thread plugin/plugins/galgame_plugin/install_routes.py Outdated
Comment thread plugin/plugins/galgame_plugin/install_routes.py
Comment thread plugin/plugins/galgame_plugin/static/main.js
Comment thread plugin/plugins/galgame_plugin/static/main.js
Copy link
Copy Markdown
Contributor

@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: 3

🤖 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.

Inline comments:
In `@plugin/plugins/galgame_plugin/install_routes.py`:
- Around line 660-662: The error response currently returns the raw exception
string (str(exc)) in the JSONResponse which can leak internal details; change
the handler that builds JSONResponse (the return using JSONResponse with {"ok":
False, "error": str(exc), "progress": current}) to return a fixed, non-sensitive
error message (e.g., "Internal server error" or "An unexpected error occurred")
while logging the full exception details to the application logger before
returning; keep the JSON keys ("ok" and "progress") and status_code=500
unchanged and locate this change around the JSONResponse return in
install_routes.py where exc and current are in scope.
- Around line 654-656: The code currently converts the incoming body to a full
dict (including default/absent fields) then normalizes and updates the stored
tutorial state, which allows defaults to overwrite existing
started_at/completed_at/last_step_index; instead, change how payload is built to
include only client-sent fields (use model_dump(exclude_unset=True) for Pydantic
v2 or dict(exclude_unset=True) for v1) before passing it to
_normalize_tutorial_progress and current.update so only explicitly provided
fields from payload are merged into current.

In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 1669-1674: The buildFirstRunActions handler currently hardcodes
the install_ocr primary action to "install_rapidocr", which can produce a
dead-end when RapidOCR is unsupported; update the flow so buildFirstRunSteps
computes the actual available install action (e.g., "install_rapidocr" or
"install_tesseract") and passes that choice into buildFirstRunActions (instead
of using a fixed string), and add a corresponding branch for "install_tesseract"
in handleDiagnosisAction to perform the Tesseract install path; modify
references to firstIncomplete.key === 'install_ocr' in buildFirstRunActions to
use the provided install action value and ensure primaryActionLabel/
data-first-run-action use that value rather than always "install_rapidocr".
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 88036211-b8a6-4d5c-a9a3-3a082d5d585b

📥 Commits

Reviewing files that changed from the base of the PR and between 6fea55a and 8dc7884.

📒 Files selected for processing (4)
  • plugin/plugins/galgame_plugin/docs/quickstart.md
  • plugin/plugins/galgame_plugin/install_routes.py
  • plugin/plugins/galgame_plugin/static/main.js
  • plugin/plugins/galgame_plugin/static/style.css

Comment thread plugin/plugins/galgame_plugin/install_routes.py Outdated
Comment thread plugin/plugins/galgame_plugin/install_routes.py
Copy link
Copy Markdown
Contributor

@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: 3

🤖 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.

Inline comments:
In `@plugin/plugins/galgame_plugin/install_routes.py`:
- Around line 600-605: The current _read_tutorial_progress swallows exceptions
and returns None, which lets save_tutorial_progress treat a read failure as "no
data" and overwrite existing progress; instead, make _read_tutorial_progress
propagate the error (re-raise the caught exception) or return a distinct error
sentinel, and update save_tutorial_progress to abort the write when
_read_tutorial_progress fails (log an error and return non-destructively).
Specifically, stop returning None on load failures from
_tutorial_store().load_tutorial_progress in _read_tutorial_progress and ensure
save_tutorial_progress checks for an error/exception from
_read_tutorial_progress and refuses to merge/overwrite persistent state when a
read failed.

In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 1564-1572: The tutorial uses install_supported alone but the
install panel requires both install_supported and can_install; update the
feature checks so rapidocrSupported, tesseractSupported, and dxcamSupported use
both flags (e.g., rapidocr.install_supported && rapidocr.can_install !== false)
and then recalc ocrInstallAction (prefer 'install_rapidocr' only when
rapidocrSupported is true, otherwise fall back to 'install_tesseract') and
ocrReady/captureReady to use those updated supported booleans (ocrReady stays
true if rapidocr.installed || tesseract.installed || (!rapidocrSupported &&
!tesseractSupported); captureReady should use dxcam.installed ||
!dxcamSupported) so the tutorial skips install steps when can_install is false.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 18781d92-3c8c-4edf-ac24-e1942ae4f868

📥 Commits

Reviewing files that changed from the base of the PR and between 8dc7884 and 4b2ba22.

📒 Files selected for processing (2)
  • plugin/plugins/galgame_plugin/install_routes.py
  • plugin/plugins/galgame_plugin/static/main.js

Comment thread plugin/plugins/galgame_plugin/install_routes.py Outdated
Comment thread plugin/plugins/galgame_plugin/static/main.js
Comment thread plugin/plugins/galgame_plugin/static/main.js Outdated
Copy link
Copy Markdown
Contributor

@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: 2

♻️ Duplicate comments (1)
plugin/plugins/galgame_plugin/static/main.js (1)

6780-6783: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

跟着引导去装依赖时,不该把教程直接写成 skipped

navigateToInstallPanel() 会被 onboarding CTA 和普通安装入口共用。现在这里直接写本地 skip 和服务端 skipped: true,用户只是按教程去装 RapidOCR / DXcam,刷新后就会被当成“已跳过教程”,首屏引导没法继续恢复了喵。这个状态只该在显式点击跳过时落库喵。

🐾 建议最小修复喵
-  persistSkipOnboarding();
   onboardingDismissed = true;
   forceShowOnboarding = false;
-  saveTutorialProgress({ skipped: true }).catch(() => {});
   document.body.classList.remove('onboarding-active');
🤖 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 `@plugin/plugins/galgame_plugin/static/main.js` around lines 6780 - 6783, The
code in navigateToInstallPanel incorrectly marks the tutorial as skipped by
calling persistSkipOnboarding(), setting onboardingDismissed = true and
forceShowOnboarding = false, and saveTutorialProgress({ skipped: true }) — this
causes users who follow the install guide to be treated as having explicitly
skipped the tutorial. Remove those skip-related side effects from the
navigateToInstallPanel path (keep only the navigation logic) and ensure
persistSkipOnboarding, onboardingDismissed, forceShowOnboarding, and
saveTutorialProgress({ skipped: true }) are only invoked from the explicit "skip
tutorial" handler (the skip CTA), not from functions used by both onboarding CTA
and normal installers.
🤖 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.

Inline comments:
In `@plugin/plugins/galgame_plugin/install_routes.py`:
- Around line 641-645: The GET handler get_tutorial_status currently lets
_read_tutorial_progress() raise, producing a FastAPI 500 and a different
response shape than the POST path; wrap the call to _read_tutorial_progress() in
a try/except inside get_tutorial_status, and on failure return the same shaped
JSONResponse as POST (e.g. {"ok": False, "error": "<message>", "progress":
_normalize_tutorial_progress(raw_default)}) using a sensible default raw value
before calling _normalize_tutorial_progress; ensure you reference
_read_tutorial_progress, _normalize_tutorial_progress and keep the endpoint
returning JSONResponse with consistent keys.

In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 1735-1748: The code updates in-memory progress
(latestTutorialProgress and lastSavedStepIndex) before the POST completes so
transient save failures are treated as success; change the logic so you only
update latestTutorialProgress.completed and lastSavedStepIndex after
saveTutorialProgress resolves successfully (i.e., move the state mutation into
the .then/await success path of saveTutorialProgress and leave state unchanged
on catch), and do the same fix for the other occurrence that saves
last_step_index; reference saveTutorialProgress, latestTutorialProgress,
lastSavedStepIndex, steps, allDone, advancedOpen, and forceShowOnboarding to
locate the two save sites and ensure failures do not advance saved indices or
completed flag.

---

Duplicate comments:
In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 6780-6783: The code in navigateToInstallPanel incorrectly marks
the tutorial as skipped by calling persistSkipOnboarding(), setting
onboardingDismissed = true and forceShowOnboarding = false, and
saveTutorialProgress({ skipped: true }) — this causes users who follow the
install guide to be treated as having explicitly skipped the tutorial. Remove
those skip-related side effects from the navigateToInstallPanel path (keep only
the navigation logic) and ensure persistSkipOnboarding, onboardingDismissed,
forceShowOnboarding, and saveTutorialProgress({ skipped: true }) are only
invoked from the explicit "skip tutorial" handler (the skip CTA), not from
functions used by both onboarding CTA and normal installers.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 16a15578-bfcf-4eca-ba29-a5006ab17aa3

📥 Commits

Reviewing files that changed from the base of the PR and between 4b2ba22 and 93f920a.

📒 Files selected for processing (2)
  • plugin/plugins/galgame_plugin/install_routes.py
  • plugin/plugins/galgame_plugin/static/main.js

Comment thread plugin/plugins/galgame_plugin/install_routes.py
Comment thread plugin/plugins/galgame_plugin/static/main.js
Copy link
Copy Markdown
Contributor

@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

🧹 Nitpick comments (1)
plugin/plugins/galgame_plugin/install_routes.py (1)

574-589: ⚖️ Poor tradeoff

_tutorial_store() 重复创建了 PluginStore,虽然不会导致数据不一致但属于不优雅的设计喵~

因为 PluginStore 没有内存缓存、每次操作都直接读写 SQLite,而 SQLite 本身用文件锁处理并发访问,所以两个独立实例指向同一个数据库文件时不会出现数据不一致问题喵。

但这样做确实不太聪明:

  • 两个 PluginStore 实例 = 两份独立连接池,浪费资源
  • 路由模块没有办法访问主插件的 self.store,所以只能自己 new 一份

建议从插件初始化时就把 GalgameStore 实例存储到某个全局位置(比如在 _tutorial_store() 里用 plugin context 或者一个模块级 getter),让路由代码能拿到已有的实例而不是重复创建喵。

🤖 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 `@plugin/plugins/galgame_plugin/install_routes.py` around lines 574 - 589, The
_tutorial_store() helper currently creates a new PluginStore and GalgameStore
even when the main plugin already has one, causing duplicate DB connections;
change the design so the plugin initialization assigns the single GalgameStore
instance to the module-level _tutorial_store_instance (or exposes it via a
module-level getter) and update _tutorial_store() to simply return that stored
instance (referencing _tutorial_store_instance, GalgameStore, PluginStore and
the plugin's self.store), ensuring route code reuses the existing GalgameStore
instead of constructing a new PluginStore/GalgameStore pair.
🤖 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.

Inline comments:
In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 6687-6699: The calls to saveTutorialProgress in resetTutorialGuide
and initialize are currently awaited and will throw on HTTP errors, aborting the
UI flow (symbols: saveTutorialProgress, resetTutorialGuide, initialize,
refreshStatusAndWindowsFromAction, refreshAll); change those calls to be
best-effort by wrapping each await saveTutorialProgress(...) in a try/catch that
logs a non-fatal warning/error (do not rethrow) so failures don’t block the
subsequent calls to refreshStatusAndWindowsFromAction or refreshAll and the UI
initialization/reset can continue.

---

Nitpick comments:
In `@plugin/plugins/galgame_plugin/install_routes.py`:
- Around line 574-589: The _tutorial_store() helper currently creates a new
PluginStore and GalgameStore even when the main plugin already has one, causing
duplicate DB connections; change the design so the plugin initialization assigns
the single GalgameStore instance to the module-level _tutorial_store_instance
(or exposes it via a module-level getter) and update _tutorial_store() to simply
return that stored instance (referencing _tutorial_store_instance, GalgameStore,
PluginStore and the plugin's self.store), ensuring route code reuses the
existing GalgameStore instead of constructing a new PluginStore/GalgameStore
pair.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1cea868d-fd5b-4a48-8d9c-ed47903f557e

📥 Commits

Reviewing files that changed from the base of the PR and between 93f920a and 2453c78.

📒 Files selected for processing (2)
  • plugin/plugins/galgame_plugin/install_routes.py
  • plugin/plugins/galgame_plugin/static/main.js

Comment thread plugin/plugins/galgame_plugin/static/main.js Outdated
Copy link
Copy Markdown
Contributor

@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: 2

🤖 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.

Inline comments:
In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 1674-1683: The install CTA buttons created in the branch handling
firstIncomplete (symbols: firstIncomplete, installAction, and the
data-first-run-action values 'install_rapidocr', 'install_tesseract',
'install_dxcam') launch installs but do not dismiss the onboarding overlay;
modify the click/install entry-point so it first closes/hides the onboarding
(call the existing onboarding dismiss function or set the onboarding
state/visible flag) before kicking off the install flow, and ensure you do NOT
mark the onboarding step as "skipped" when hiding it. Apply this change for both
the OCR branch (installAction handling) and the install_capture branch
(install_dxcam) — ideally by moving the hide-onboarding call into the common
installation handler invoked by the data-first-run-action clicks.
- Around line 6635-6674: The GET in fetchTutorialProgress and the POST in
saveTutorialProgress can hang indefinitely; update both functions
(fetchTutorialProgress and the inner async in saveTutorialProgress) to use an
AbortController with a short timeout (e.g., a few seconds) and pass
controller.signal to fetch, clearing the timer on success; on timeout/abort
treat it as a failed best-effort call (return null from fetchTutorialProgress
and reject or resolve saveTutorialProgress as the current error-handling
expects) so initialization and settings reopening won’t block when the network
is unresponsive.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 01d60d63-14a9-45b1-bde2-519d59a27d11

📥 Commits

Reviewing files that changed from the base of the PR and between 93f920a and 14284d5.

📒 Files selected for processing (2)
  • plugin/plugins/galgame_plugin/install_routes.py
  • plugin/plugins/galgame_plugin/static/main.js

Comment thread plugin/plugins/galgame_plugin/static/main.js
Comment thread plugin/plugins/galgame_plugin/static/main.js
Copy link
Copy Markdown
Contributor

@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

♻️ Duplicate comments (1)
plugin/plugins/galgame_plugin/static/main.js (1)

1588-1593: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

教程里的“可安装”判断还没和安装面板完全对齐喵

这里用 can_install !== false 会把 undefined/null 也当成“可安装”,但下面安装面板实际用的是 Boolean(...can_install)。状态响应里只要暂时没带 can_install,首屏教程就还会给出安装步骤和 CTA,点进去后安装按钮却是隐藏的,用户会被卡在这一步喵。建议直接复用和安装面板一致的 installable 判定喵。

🐾 建议修法喵
-  const rapidocrSupported = Boolean(rapidocr.install_supported) && rapidocr.can_install !== false;
-  const tesseractSupported = Boolean(tesseract.install_supported) && tesseract.can_install !== false;
-  const dxcamSupported = Boolean(dxcam.install_supported) && dxcam.can_install !== false;
+  const rapidocrSupported = Boolean(rapidocr.install_supported) && Boolean(rapidocr.can_install);
+  const tesseractSupported = Boolean(tesseract.install_supported) && Boolean(tesseract.can_install);
+  const dxcamSupported = Boolean(dxcam.install_supported) && Boolean(dxcam.can_install);
🤖 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 `@plugin/plugins/galgame_plugin/static/main.js` around lines 1588 - 1593, The
current checks rapidocrSupported, tesseractSupported and dxcamSupported use
"can_install !== false" which treats undefined/null as installable and is
inconsistent with the install panel; change those checks to use the same
Boolean(...) installable logic the install panel uses (e.g.,
Boolean(rapidocr.can_install), Boolean(tesseract.can_install),
Boolean(dxcam.can_install)) and update dependent values (ocrInstallAction,
ocrReady, captureReady) to rely on those updated symbols so the tutorial CTA and
the install-panel visibility remain in sync.
🤖 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.

Inline comments:
In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 6673-6691: In saveTutorialProgress: don't merge
latestTutorialProgress into the POST body (this causes stale local snapshot
overwrites); instead send only the incoming partial (JSON.stringify(partial ||
{})) to TUTORIAL_PROGRESS_URL via fetchWithTutorialTimeout, await the response,
and then set latestTutorialProgress = data && data.progress (or leave as-is if
response lacks progress); keep the existing tutorialProgressSaveQueue chaining
and the fallback fetchTutorialProgress() when latestTutorialProgress is missing,
but remove the construction of payload that spreads latestTutorialProgress into
the body so the server's partial-merge behavior isn't clobbered.

---

Duplicate comments:
In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 1588-1593: The current checks rapidocrSupported,
tesseractSupported and dxcamSupported use "can_install !== false" which treats
undefined/null as installable and is inconsistent with the install panel; change
those checks to use the same Boolean(...) installable logic the install panel
uses (e.g., Boolean(rapidocr.can_install), Boolean(tesseract.can_install),
Boolean(dxcam.can_install)) and update dependent values (ocrInstallAction,
ocrReady, captureReady) to rely on those updated symbols so the tutorial CTA and
the install-panel visibility remain in sync.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 554571c4-3b6d-4793-b53a-5cb66363c7d9

📥 Commits

Reviewing files that changed from the base of the PR and between 14284d5 and 2efdc3b.

📒 Files selected for processing (1)
  • plugin/plugins/galgame_plugin/static/main.js

Comment thread plugin/plugins/galgame_plugin/static/main.js
@MomiJiSan
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@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

♻️ Duplicate comments (1)
plugin/plugins/galgame_plugin/static/main.js (1)

1588-1593: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

教程“可安装”判定和安装面板判定不一致,会把用户引到不可执行动作喵

Line 1588-1590 用的是 can_install !== false,但安装面板(renderRapidOcr/renderDxcam/renderTesseract)用 Boolean(can_install),当后端缺省 can_install 时会出现“引导要求安装,但按钮隐藏”的断路喵。建议统一为同一口径喵。

🐾 建议最小修复
-  const rapidocrSupported = Boolean(rapidocr.install_supported) && rapidocr.can_install !== false;
-  const tesseractSupported = Boolean(tesseract.install_supported) && tesseract.can_install !== false;
-  const dxcamSupported = Boolean(dxcam.install_supported) && dxcam.can_install !== false;
+  const rapidocrSupported = Boolean(rapidocr.install_supported) && Boolean(rapidocr.can_install);
+  const tesseractSupported = Boolean(tesseract.install_supported) && Boolean(tesseract.can_install);
+  const dxcamSupported = Boolean(dxcam.install_supported) && Boolean(dxcam.can_install);
🤖 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 `@plugin/plugins/galgame_plugin/static/main.js` around lines 1588 - 1593, The
feature-detection logic uses `can_install !== false` while the UI panels
(`renderRapidOcr`, `renderDxcam`, `renderTesseract`) use `Boolean(can_install)`,
causing mismatch when `can_install` is undefined; update the predicates used to
compute rapidocrSupported, tesseractSupported and dxcamSupported to use the same
Boolean(coerce) rule (e.g., Boolean(rapidocr.can_install) etc.) and ensure
ocrReady and captureReady use the same Boolean-coerced checks so the tutorial
prompts and install buttons use identical can_install semantics (leave
ocrInstallAction logic unchanged).
🤖 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.

Inline comments:
In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 1756-1771: The save path currently re-enqueues identical saves
each render because failures/timeouts leave
`lastSavedStepIndex`/`latestTutorialProgress.completed` unchanged; add in-flight
deduplication keyed by the payload (e.g., "completed" or
`last_step_index:${firstIncompleteIndex}`) by tracking a Map/Set of pending keys
before calling saveTutorialProgress, skip starting a new save if that key is
already pending, and ensure the pending key is removed in both .then and .catch;
on success update `lastSavedStepIndex` and `latestTutorialProgress.completed` as
before.

---

Duplicate comments:
In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 1588-1593: The feature-detection logic uses `can_install !==
false` while the UI panels (`renderRapidOcr`, `renderDxcam`, `renderTesseract`)
use `Boolean(can_install)`, causing mismatch when `can_install` is undefined;
update the predicates used to compute rapidocrSupported, tesseractSupported and
dxcamSupported to use the same Boolean(coerce) rule (e.g.,
Boolean(rapidocr.can_install) etc.) and ensure ocrReady and captureReady use the
same Boolean-coerced checks so the tutorial prompts and install buttons use
identical can_install semantics (leave ocrInstallAction logic unchanged).
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c64622b1-ccc3-42dd-84dd-5897b552d21a

📥 Commits

Reviewing files that changed from the base of the PR and between 2efdc3b and 4b81257.

📒 Files selected for processing (1)
  • plugin/plugins/galgame_plugin/static/main.js

Comment thread plugin/plugins/galgame_plugin/static/main.js
Copy link
Copy Markdown
Contributor

@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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 6730-6746: The resetTutorialGuide function sets lastSavedStepIndex
to -1 before saving but never updates it after a successful save, which can
allow the old saved-callback (e.g., the handler at lines referencing
last_step_index) to wrongly treat a later identical step as already saved; after
the await saveTutorialProgress(...) resolves successfully inside
resetTutorialGuide, set lastSavedStepIndex to 0 (and optionally update
latestTutorialProgress to match the reset payload) so the local state is
consistent with the server reset; make the change in resetTutorialGuide near the
success path that currently only catches errors.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 73b77042-62e8-4d4b-840f-186bd2278ae4

📥 Commits

Reviewing files that changed from the base of the PR and between 4b81257 and ee061d9.

📒 Files selected for processing (1)
  • plugin/plugins/galgame_plugin/static/main.js

Comment thread plugin/plugins/galgame_plugin/static/main.js
@MomiJiSan
Copy link
Copy Markdown
Contributor Author

五花马,千金裘,呼儿将出换TOKEN,与尔同改小BUG

Copy link
Copy Markdown
Contributor

@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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 6701-6704: The code in the save handler (const save =
tutorialProgressSaveQueue.catch(() => {}).then(async () => { ... }))
unnecessarily calls await fetchTutorialProgress() when latestTutorialProgress is
falsy before performing the POST; remove that pre-fetch (delete the await
fetchTutorialProgress() branch) so save only sends the partial update (matching
the partial/merge backend model) and avoids introducing extra latency for
callers like initialize() and resetTutorialGuide() that await
saveTutorialProgress(...).
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e87e1c24-24f0-4c90-8a1d-2f0885cf92a4

📥 Commits

Reviewing files that changed from the base of the PR and between ee061d9 and 7d490a6.

📒 Files selected for processing (1)
  • plugin/plugins/galgame_plugin/static/main.js

Comment thread plugin/plugins/galgame_plugin/static/main.js Outdated
MomiJiSan added 12 commits May 6, 2026 23:12
  - install_routes.py:教程进度 GET/POST API
  - zh-CN.json / en.json:首屏引导新增文案
  - main.js:动态 4-7 步引导、教程进度保存、DXcam/RapidOCR 安装跳转、重开引导、localStorage 容错
  - style.css / index.html:动态步骤布局和“重新打开设置引导”入口

  我也做了校验:

  - JS 语法通过
  - Python 编译通过
  - i18n JSON 解析通过
  - test_galgame_service.py 全量 34 个单测通过
      - 增加 tutorial_progress 存储键。
      - 增加教程进度读写方法。
      - 新增教程进度 API:/tutorial/status、/tutorial/progress。
  - 首屏引导从固定 4 步改为动态 4-7 步。
      - 支持 OCR 依赖安装引导。
      - 支持 DXcam 截图依赖安装引导。
      - 支持启动游戏、刷新窗口、选择窗口、截图校准、开始识别等步骤。
      - 已就绪或不支持自动安装的平台会跳过对应依赖步骤。
  - 修复 onboarding 遮罩影响安装面板的问题。
      - 从首屏点击安装 RapidOCR / DXcam 时,会退出 onboarding。
      - 自动展开高级设置。
      - 自动打开依赖安装模块。
      - 自动切换到对应安装页签并滚动到安装面板。
  - 增加“重新打开设置引导”入口。
      - 高级设置中新增重开引导按钮。
      - 支持清除跳过状态并重新显示引导。
  - 增强 localStorage 容错。
      - localStorage 读写失败时不会中断初始化或安装流程。
      - 避免受限 WebView / 隐私模式下提前失败。
  - 补充中英文 UI 文案。
      - 新增教程步骤、按钮、安装进度、跳过确认等 i18n key。
  - 调整首屏引导布局。
      - 动态步骤数量下使用自适应网格。
      - onboarding 和主界面的步骤展示更适合 4-7 步变化。

  验证:

  - JS 语法检查通过。
  - Python 编译检查通过。
  - i18n JSON 解析通过。
  - test_galgame_service.py 通过。
  - install_routes.py 的教程进度读写改为走 GalgameStore / PluginStore,不再直接读写 tutorial-progress.json。
  - 教程进度保存失败现在会继续记录 warning,并向前端返回 ok: false / HTTP 500。
  - main.js 中 saveTutorialProgress 增加串行队列,避免并发保存覆盖。
  - 增加 forceShowOnboarding,修复手动重开引导后被自动条件立刻隐藏的问题。
  - style.css 将步骤网格改为 auto-fit,并只在 640px 以下让 onboarding 步骤单列。

  跳过项:

  - 评论里提到的“另一份 _write_tutorial_progress/save_tutorial_progress 逻辑”在当前代码中不存在,因此未修改。

  验证已通过:

  - Python 编译检查
  - install_routes 导入检查
  - 保存成功/失败的接口行为检查
  - node --check main.js
  - git diff --check
      - payload 改为 exclude_unset=True,只合并客户端实际提交的字段,避免默认值覆盖已有 started_at/completed_at/last_step_index。
      - 保存失败时继续记录完整异常日志,但前端只收到固定错误文案:Internal server error,不再暴露 str(exc)。
  - N.E.K.O/plugin/plugins/galgame_plugin/static/main.js:1567
      - buildFirstRunSteps 根据 RapidOCR 是否支持选择 install_rapidocr 或 install_tesseract。
      - buildFirstRunActions 使用步骤里带的 installAction,不再硬编码 RapidOCR。
      - handleDiagnosisAction 增加 install_tesseract 分支,调用现有 installTesseract(false)。

  验证已通过:

  - .venv\Scripts\python.exe -m py_compile plugin\plugins\galgame_plugin\install_routes.py
  - node --check plugin\plugins\galgame_plugin\static\main.js
  - git diff --check
      - _read_tutorial_progress() 读失败时不再返回 None,而是记录日志后重新抛出异常。
      - save_tutorial_progress() 在读取失败时直接返回 ok: false / HTTP 500,不再 merge,也不会写入,避免把“读失败”当成“无数据”覆盖已有进度。
  - N.E.K.O/plugin/plugins/galgame_plugin/static/main.js:1567
      - rapidocrSupported / tesseractSupported / dxcamSupported 现在同时要求 install_supported 为真且 can_install !== false。
      - 原有 ocrInstallAction、ocrReady、captureReady 逻辑继续基于这些更新后的 supported booleans 计算。

  验证已通过:

  - .venv\Scripts\python.exe -m py_compile plugin\plugins\galgame_plugin\install_routes.py
  - node --check plugin\plugins\galgame_plugin\static\main.js
  - git diff --check
  - 额外 stub 验证:教程进度读取失败时会返回 500,且不会调用保存函数。
      - get_tutorial_status() 现在捕获 _read_tutorial_progress() 读失败。
      - 失败时返回与 POST 一致的 JSON 形状:ok/error/progress,HTTP 500,不再交给 FastAPI 默认 500。
  - N.E.K.O/plugin/plugins/galgame_plugin/static/main.js:6649
      - saveTutorialProgress() 失败时不再把 payload 写入 latestTutorialProgress,而是抛错。
      - lastSavedStepIndex 只在 saveTutorialProgress(...).then(...) 成功后更新。
      - completed 状态也只会在保存成功后通过 latestTutorialProgress 更新,失败不会被当作成功。
  - N.E.K.O/plugin/plugins/galgame_plugin/static/main.js:6773
      - navigateToInstallPanel() 已移除 persistSkipOnboarding()、onboardingDismissed = true、forceShowOnboarding = false、saveTutorialProgress({ skipped: true }) 以及隐藏 onboarding 的副作用。
      - 显式跳过教程的逻辑仍只保留在 skip CTA handler。

  验证已通过:

  - .venv\Scripts\python.exe -m py_compile plugin\plugins\galgame_plugin\install_routes.py
  - node --check plugin\plugins\galgame_plugin\static\main.js
  - git diff --check
  - stub 验证 GET 读失败返回统一 JSON,不走 FastAPI 默认错误形状。
  - resetTutorialGuide 中的 await saveTutorialProgress(...) 已包进 try/catch
  - initialize 中的 await saveTutorialProgress(...) 已包进 try/catch
  - catch 里只 console.warn(...),不 rethrow,所以后续 refreshStatusAndWindowsFromAction() / refreshAll() 不会被阻断

  验证:

  - node --check plugin\plugins\galgame_plugin\static\main.js 通过
  - 当前 diff 只包含这两处 best-effort 处理
  - 没有其它仍需处理的 finding
  - data-first-run-action 的公共点击入口现在会在执行安装动作前隐藏 onboarding。
  - 覆盖 install_rapidocr、install_tesseract、install_dxcam。
  - 隐藏 onboarding 时只更新 UI 状态,不调用 persistSkipOnboarding(),也不会保存 skipped: true。
  - fetchTutorialProgress 和 saveTutorialProgress 的 POST 都改为通过 AbortController 加 5 秒超时。
  - GET 超时/失败仍返回 null;POST 超时/失败仍按现有调用方的错误处理路径走,不会无限挂起。

  验证:

  - node --check plugin\plugins\galgame_plugin\static\main.js 通过
  - git diff --check 通过
  - 已确认没有残留 fetch(TUTORIAL_STATUS_URL / fetch(TUTORIAL_PROGRESS_URL 直连调用
  - 当前只有 plugin/plugins/galgame_plugin/static/main.js 有未暂存改动。
  - 移除了 { ...(latestTutorialProgress || {}), ...(partial || {}) }
  - POST body 现在只发送:

    JSON.stringify(partial || {})

  - 保留了 tutorialProgressSaveQueue 串行逻辑
  - 保留了 latestTutorialProgress 缺失时先 fetchTutorialProgress()
  - 成功响应后只有 data.progress 存在时才更新 latestTutorialProgress,否则保持原值

  验证:

  - node --check plugin\plugins\galgame_plugin\static\main.js 通过
  - git diff --check 通过
  - 已确认没有残留旧的合并 payload 写法
  - 当前只修改了 plugin/plugins/galgame_plugin/static/main.js
  - rapidocrSupported / tesseractSupported / dxcamSupported 现在都使用 Boolean(can_install),与安装面板语义一致。
  - ocrReady / captureReady 继续基于这些统一后的布尔值计算,ocrInstallAction 保持不变。
  - 新增 tutorialProgressPendingSaveKeys,对 first-run progress 保存按 key 去重:
      - completed
      - last_step_index:${firstIncompleteIndex}
  - pending key 会在成功和失败路径都移除。
  - 保存成功后仍更新 lastSavedStepIndex;完成保存成功后也更新 latestTutorialProgress.completed。

  验证:

  - node --check plugin\plugins\galgame_plugin\static\main.js 通过
  - git diff --check 通过
  - 当前只有 plugin/plugins/galgame_plugin/static/main.js 有改动。
  - 将 reset payload 提成 resetProgress
  - await saveTutorialProgress(resetProgress) 成功后设置:

    lastSavedStepIndex = 0;

  - 同步更新 latestTutorialProgress,优先保留服务端返回的进度字段,没有返回时用 reset payload 补齐

  验证:

  - node --check plugin\plugins\galgame_plugin\static\main.js 通过
  - git diff --check 通过
  - 当前只有 plugin/plugins/galgame_plugin/static/main.js 有改动。
  if (!latestTutorialProgress) {
    await fetchTutorialProgress();
  }

  现在保存逻辑只通过 fetchWithTutorialTimeout 发送 partial || {},保留原有队列链和响应后更新 latestTutorialProgress 的行为。

  验证:

  - node --check plugin\plugins\galgame_plugin\static\main.js 通过
  - git diff --check 通过
  - 当前只有 plugin/plugins/galgame_plugin/static/main.js 有改动。
@MomiJiSan MomiJiSan force-pushed the feat/galgame-tutorial-guide branch from b79f651 to 1384374 Compare May 6, 2026 15:12
@wehos
Copy link
Copy Markdown
Contributor

wehos commented May 6, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Tip

For best results, initiate chat on the files or code changes.

@wehos 好哒喵~主人叫我审查代码,那本大小姐就勉为其难地看一看嘛……才、才不是因为想帮你呢喵!马上触发审查喵~

[review]

@wehos
Copy link
Copy Markdown
Contributor

wehos commented May 6, 2026

解决与 #1194 的冲突

PR #1194 (commit 012b83e50) 在我推 e2b095b 之后 merge 到 main,独立修了同一个 _build_runtime_constructor_kwargs 签名 bug + 默认 PP-OCRv4。merge commit 1b564862f 把两边 reconcile 了:

CLs:

Mergeable 状态从 CONFLICTING 变成 MERGEABLE 了。

Copy link
Copy Markdown
Contributor

@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: 6

🧹 Nitpick comments (1)
plugin/plugins/galgame_plugin/rapidocr_support.py (1)

618-631: ⚡ Quick win

_verify_model_sha256 在 async 函数里同步算哈希,会卡住事件循环喵

最大的 rec 模型是 11.5MB,整段读 + hashlib 在中等机器上要几十毫秒,本身不算灾难,但它是从 download_rapidocr_models 这个 async 流里直接同步调用的(798 行),意味着这段时间整条事件循环都被冻住了喵——会顺手卡掉同进程里其它正在跑的 SSE 推送、轮询、心跳之类的协程喵。

既然下载本来就是 IO-bound 的 async 流程,把校验丢到线程池里就好喵:

♻️ 推荐改法:asyncio.to_thread
-                _verify_model_sha256(tmp_path, str(spec.get("sha256") or ""))
+                await asyncio.to_thread(
+                    _verify_model_sha256, tmp_path, str(spec.get("sha256") or "")
+                )

别忘了在文件顶部加上 import asyncio 喵。

顺便一提,_verify_model_sha256 内部用的是同步 path.open("rb") + 1MB chunk loop,留作同步函数完全没问题,只要别在事件循环线程里直接 await 它就行了喵。

🤖 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 `@plugin/plugins/galgame_plugin/rapidocr_support.py` around lines 618 - 631,
The sync SHA256 verification in _verify_model_sha256 blocks the event loop when
called directly from the async download_rapidocr_models; change the call site in
download_rapidocr_models to run _verify_model_sha256 in a thread using
asyncio.to_thread (i.e. await asyncio.to_thread(_verify_model_sha256, path,
expected_sha256)) and add import asyncio at the top of the file; keep
_verify_model_sha256 as a sync function (it can continue using path.open and
chunked reads) but never call it directly from async code on the event loop.
🤖 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.

Inline comments:
In `@plugin/plugins/galgame_plugin/docs/quickstart.md`:
- Around line 24-31: The docs are inconsistent about available screenshot
backends: the quickstart text lists "smart 链:`DXcam → MSS → PyAutoGUI`" but the
"截图后端切换" options omit PyAutoGUI; update the "截图后端切换" list to include PyAutoGUI
(or remove PyAutoGUI from the smart-chain if intended) so both places match,
specifically edit quickstart.md to make the screenshot backend options
consistent with the smart chain string `DXcam → MSS → PyAutoGUI` and ensure the
"截图后端切换" section includes PyAutoGUI as an option.
- Around line 11-14: The doc has conflicting default-model statements; update
the RapidOCR description to a single consistent line and clarify first-run
behavior: state the actual default values used by the plugin (referencing the
configuration keys lang_type and ocr_version), e.g. "default lang_type=ch and
ocr_version=PP-OCRv4" or "default lang_type=japan and ocr_version=PP-OCRv4", and
add a short note that if lang_type=japan the Japanese rec model is not bundled
in the wheel and the RapidOCR banner will prompt "模型未下载" with an "立即下载模型" button
to fetch the ~10MB model; also keep the Tesseract fallback sentence unchanged.
Ensure you change both the RapidOCR bullet and the highlighted paragraph so they
convey the same default model choice.

In `@plugin/plugins/galgame_plugin/i18n/ui/en.json`:
- Line 741: The two English strings for OCR default models conflict—update the
key "ui.first_run.install_ocr.pending" (and the other OCR-related key around the
second occurrence) so they use a single, consistent wording (either "current
selected model" or the true default, e.g., "ch + PP-OCRv4" or "japan +
PP-OCRv4"), and propagate that same phrasing to the matching locale keys; locate
and edit the entries named "ui.first_run.install_ocr.pending" and the other OCR
banner key near the second occurrence to ensure both refer to the same semantic
(and update other locale files to match).

In `@plugin/plugins/galgame_plugin/install_routes.py`:
- Around line 645-652: The merge currently only copies keys present in payload
into current (via current.update({... for key in payload if key in
_TUTORIAL_DEFAULTS})), which lets an existing completed_at persist when the
client resets completed/skipped/last_step_index; update the server-side
normalization in _normalize_tutorial_progress / the current.update call to also
clear or set completed_at consistently (e.g. include completed_at from
normalized_payload even when not present in payload, or explicitly set
completed_at = 0/None when completed is False or when a reset is detected) so
that current and _TUTORIAL_DEFAULTS stay consistent and no stale completed_at
remains.

In `@plugin/plugins/galgame_plugin/rapidocr_support.py`:
- Around line 802-811: The HTTP download except blocks in rapidocr_support.py
(the httpx.HTTPError except and the generic Exception except around the asset
download loop) currently only unlink tmp_path and re-raise, leaving the install
task stuck as "running"; update those except handlers to first call
update_install_task_state(status="failed") and emit a progress callback event
indicating failure (e.g., using the same progress callback used on success but
with status "failed" and include the error details/type and asset_name), then
unlink the tmp file and re-raise the exception so upstream still sees the error;
apply this change to both the httpx.HTTPError branch and the generic Exception
branch so tasks always reach a terminal failed state on download errors.

In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 1728-1730: The button label for the 'install_dxcam' first-run
action shows a hardcoded "一键安装 DXcam" but the actual action only opens the DXcam
status banner; update the fallback/copy to use
primaryActionLabel('install_dxcam') so the displayed text matches behavior —
modify the actions.push call that currently uses
uiT('ui.first_run.action.install_dxcam', '一键安装 DXcam') to instead call
primaryActionLabel('install_dxcam') (still wrapped with escapeHtml) in the
branch where firstIncomplete.key === 'install_capture'.

---

Nitpick comments:
In `@plugin/plugins/galgame_plugin/rapidocr_support.py`:
- Around line 618-631: The sync SHA256 verification in _verify_model_sha256
blocks the event loop when called directly from the async
download_rapidocr_models; change the call site in download_rapidocr_models to
run _verify_model_sha256 in a thread using asyncio.to_thread (i.e. await
asyncio.to_thread(_verify_model_sha256, path, expected_sha256)) and add import
asyncio at the top of the file; keep _verify_model_sha256 as a sync function (it
can continue using path.open and chunked reads) but never call it directly from
async code on the event loop.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8f8c017a-d0cc-46ec-8e89-bc2fe5140f58

📥 Commits

Reviewing files that changed from the base of the PR and between 22155fb and e2b095b.

📒 Files selected for processing (15)
  • plugin/plugins/galgame_plugin/__init__.py
  • plugin/plugins/galgame_plugin/docs/quickstart.md
  • plugin/plugins/galgame_plugin/i18n/ui/en.json
  • plugin/plugins/galgame_plugin/i18n/ui/ja.json
  • plugin/plugins/galgame_plugin/i18n/ui/ko.json
  • plugin/plugins/galgame_plugin/i18n/ui/ru.json
  • plugin/plugins/galgame_plugin/i18n/ui/zh-CN.json
  • plugin/plugins/galgame_plugin/install_routes.py
  • plugin/plugins/galgame_plugin/install_tasks.py
  • plugin/plugins/galgame_plugin/models.py
  • plugin/plugins/galgame_plugin/plugin.toml
  • plugin/plugins/galgame_plugin/rapidocr_support.py
  • plugin/plugins/galgame_plugin/static/index.html
  • plugin/plugins/galgame_plugin/static/main.js
  • plugin/tests/unit/plugins/test_galgame_ocr_reader.py
✅ Files skipped from review due to trivial changes (1)
  • plugin/plugins/galgame_plugin/i18n/ui/ko.json

Comment thread plugin/plugins/galgame_plugin/docs/quickstart.md Outdated
Comment thread plugin/plugins/galgame_plugin/docs/quickstart.md
Comment thread plugin/plugins/galgame_plugin/i18n/ui/en.json Outdated
Comment thread plugin/plugins/galgame_plugin/install_routes.py
Comment thread plugin/plugins/galgame_plugin/rapidocr_support.py
Comment thread plugin/plugins/galgame_plugin/static/main.js
Copy link
Copy Markdown
Contributor

@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: 3

♻️ Duplicate comments (1)
plugin/plugins/galgame_plugin/rapidocr_support.py (1)

890-897: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

下载异常时还是没有回写 failed 终态喵

这两个 except 现在仍然只是删掉临时文件然后继续抛异常,task_id 对应的安装任务和 progress_callback 都收不到失败终态,前端就会一直看到 running 喵。这个点在前一轮 review 里已经提过了,现在看起来还没补上喵。

🛠️ 建议在抛异常前先补失败状态喵
             except httpx.HTTPError as exc:
+                err_message = f"failed to download {asset_name}: {type(exc).__name__}: {exc}"
+                progress = (downloaded_bytes / total_bytes) if total_bytes else 0.0
+                if task_id:
+                    update_install_task_state(
+                        task_id,
+                        kind="rapidocr_models",
+                        status="failed",
+                        phase="failed",
+                        message=err_message,
+                        progress=progress,
+                        downloaded_bytes=downloaded_bytes,
+                        total_bytes=total_bytes,
+                        target_dir=str(cache_dir),
+                        asset_name=asset_name,
+                    )
+                await _emit_model_progress(
+                    progress_callback,
+                    {
+                        "status": "failed",
+                        "phase": "failed",
+                        "message": err_message,
+                        "progress": progress,
+                        "downloaded_bytes": downloaded_bytes,
+                        "total_bytes": total_bytes,
+                        "target_dir": str(cache_dir),
+                        "asset_name": asset_name,
+                    },
+                )
                 tmp_path.unlink(missing_ok=True)
-                raise RuntimeError(
-                    f"failed to download {asset_name}: {type(exc).__name__}: {exc}"
-                ) from exc
-            except Exception:
+                raise RuntimeError(err_message) from exc
+            except Exception as exc:
+                err_message = f"download interrupted at {asset_name}: {type(exc).__name__}: {exc}"
+                progress = (downloaded_bytes / total_bytes) if total_bytes else 0.0
+                if task_id:
+                    update_install_task_state(
+                        task_id,
+                        kind="rapidocr_models",
+                        status="failed",
+                        phase="failed",
+                        message=err_message,
+                        progress=progress,
+                        downloaded_bytes=downloaded_bytes,
+                        total_bytes=total_bytes,
+                        target_dir=str(cache_dir),
+                        asset_name=asset_name,
+                    )
+                await _emit_model_progress(
+                    progress_callback,
+                    {
+                        "status": "failed",
+                        "phase": "failed",
+                        "message": err_message,
+                        "progress": progress,
+                        "downloaded_bytes": downloaded_bytes,
+                        "total_bytes": total_bytes,
+                        "target_dir": str(cache_dir),
+                        "asset_name": asset_name,
+                    },
+                )
                 tmp_path.unlink(missing_ok=True)
                 raise
🤖 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.

Inline comments:
In `@plugin/plugins/galgame_plugin/rapidocr_support.py`:
- Around line 781-792: The cache-hit branch currently returns early and does not
emit the streaming completion event; before the early return, call the
progress_callback (if provided) with a completed payload (status "completed",
phase "completed", progress 1.0, message like "All required RapidOCR models
already on disk", and target_dir=str(cache_dir)) so streaming callers receive
the terminal event; keep the existing update_install_task_state(task_id, ...)
call as-is and ensure you reference progress_callback, task_id,
update_install_task_state, and cache_dir when adding this call.
- Around line 201-222: det/rec filename construction currently hardcodes PP-OCR
version into det_names/rec_names (variables lang, version, mt) causing
registry-provided filenames (from _RAPIDOCR_MODEL_REGISTRY) such as
"japan_PP-OCRv4_rec_mobile.onnx" to never match and rec_path to remain None;
instead, change the lookup to prefer exact filenames from
_RAPIDOCR_MODEL_REGISTRY (use the registry entry for ("PP-OCRv5", lang)["rec"] /
["det"] when present) before falling back to building names from
lang/version/model_type; update the code that builds det_names and rec_names to
merge registry filenames (unique list with registry first) so det_path/rec_path
resolution will match downloaded files and pass *_model_path into RapidOCR.

In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 130-146: Restore and wire up the rapidocr_models kind when
rehydrating install tasks and ensure the visible button binds to that kind's
runtime state: update the task-restoration code to include entries where kind
=== 'rapidocr_models' (so the SSE reconnection/progress/failure state is
rehydrated for storageKey `${PLUGIN_ID}:rapidocr_models_task_id`), change the UI
handler for rapidocrModelsDownloadBtn to use the rapidocr_models runtime state
(or call startInstall('rapidocr_models') in a way that uses the rapidocr_models
kind/storageKey rather than the old domPrefix 'rapidocr' logic), and make the
visible banner button read the rapidocr_models.inProgress/inState to
disable/show runningText so repeated clicks cannot create duplicate download
tasks.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 48ca5e9f-2adb-4fa4-97dd-9ac7904bb70d

📥 Commits

Reviewing files that changed from the base of the PR and between e2b095b and 1b56486.

📒 Files selected for processing (3)
  • plugin/plugins/galgame_plugin/rapidocr_support.py
  • plugin/plugins/galgame_plugin/static/main.js
  • plugin/plugins/galgame_plugin/static/style.css

Comment thread plugin/plugins/galgame_plugin/rapidocr_support.py Outdated
Comment thread plugin/plugins/galgame_plugin/rapidocr_support.py
Comment thread plugin/plugins/galgame_plugin/static/main.js
Resolver / runtime
- _resolve_rapidocr_model_paths consults the registry first so
  cross-version fallbacks resolve. Specifically, ("PP-OCRv5", "japan")
  rec downloads as `japan_PP-OCRv4_rec_mobile.onnx` (no v5 japan rec
  upstream); the synthesized `f"{lang}_{version}_rec_*"` candidates would
  never match this filename, so RapidOCR silently fell back to its
  default ch model even after the download succeeded.

Download task observability
- Exception path in download_rapidocr_models now flips the persisted
  task to status=failed and emits a `failed` progress event before
  re-raising. Without these the SSE stream stayed in `running` until
  the client timed out and the user saw a download "that never finishes."
- Cache-hit early-return now emits a `completed` progress event in
  addition to the persisted task update, matching the bundled-no-op
  branch's behavior so streaming subscribers receive a terminal event.

Tutorial reset state
- install_routes.save_tutorial_progress now clears completed_at when
  the post-merge state has completed=False AND skipped=False (i.e. a
  reset). Otherwise an old completed_at would persist and produce a
  self-contradicting `completed=False, completed_at>0` record.

Frontend
- restoreRapidOcrModelsState() runs alongside restoreTesseractInstallState
  /restoreTextractorInstallState during init, so refreshing mid-download
  reconnects the SSE stream and re-renders the progress card.
- rapidocrModelsDownloadBtn now reflects inProgress (disabled +
  runningText) and the failure state (retryText), so users can't trigger
  duplicate concurrent downloads by re-clicking the banner button.
- buildFirstRunActions install_dxcam button fallback uses
  primaryActionLabel('install_dxcam') ("查看 DXcam 状态") instead of
  the stale "一键安装 DXcam" — the action only opens the bundled hint
  banner now, doesn't actually install.

Docs / i18n
- quickstart.md: unify the RapidOCR description so wheel-bundled
  (ch+v4) and plugin default (japan+v4) are no longer presented as
  conflicting "default" claims; add PyAutoGUI to section 九's backend list.
- i18n × 5 locales: rewrite install_ocr.pending to actually describe
  the rapidocr-unavailable scenario (it was leftover copy claiming
  "default models bundled" that contradicted .pending_models). Drop
  the overloaded "default" word from .pending_models.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@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: 2

🤖 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.

Inline comments:
In `@plugin/plugins/galgame_plugin/i18n/ui/en.json`:
- Line 1053: The string under key ui.first_run.install_ocr.pending_models
currently hardcodes "japan + PP-OCRv4" and "~10 MB"; update this key to use the
same interpolation placeholders as ui.install.rapidocr.missing_models_body (e.g.
{lang}, {version}, {size}) so the text is generated dynamically, and coordinate
with the frontend to pass the corresponding lang, version and size values when
rendering ui.first_run.install_ocr.pending_models.

In `@plugin/plugins/galgame_plugin/i18n/ui/ko.json`:
- Line 1009: The translation key ui.common.auto_value was changed from Korean to
English causing mixed-language UI; revert its value back to the original Korean
string "(자동)" in the i18n JSON so the Korean locale remains consistent by
updating the ui.common.auto_value entry in
plugin/plugins/galgame_plugin/i18n/ui/ko.json to "(자동)".
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8760708f-0757-47b2-94d9-b23f96c7a01e

📥 Commits

Reviewing files that changed from the base of the PR and between 1b56486 and 12e1305.

📒 Files selected for processing (9)
  • plugin/plugins/galgame_plugin/docs/quickstart.md
  • plugin/plugins/galgame_plugin/i18n/ui/en.json
  • plugin/plugins/galgame_plugin/i18n/ui/ja.json
  • plugin/plugins/galgame_plugin/i18n/ui/ko.json
  • plugin/plugins/galgame_plugin/i18n/ui/ru.json
  • plugin/plugins/galgame_plugin/i18n/ui/zh-CN.json
  • plugin/plugins/galgame_plugin/install_routes.py
  • plugin/plugins/galgame_plugin/rapidocr_support.py
  • plugin/plugins/galgame_plugin/static/main.js
✅ Files skipped from review due to trivial changes (1)
  • plugin/plugins/galgame_plugin/docs/quickstart.md
🚧 Files skipped from review as they are similar to previous changes (6)
  • plugin/plugins/galgame_plugin/i18n/ui/ja.json
  • plugin/plugins/galgame_plugin/install_routes.py
  • plugin/plugins/galgame_plugin/i18n/ui/zh-CN.json
  • plugin/plugins/galgame_plugin/rapidocr_support.py
  • plugin/plugins/galgame_plugin/i18n/ui/ru.json
  • plugin/plugins/galgame_plugin/static/main.js

Comment thread plugin/plugins/galgame_plugin/i18n/ui/en.json Outdated
Comment thread plugin/plugins/galgame_plugin/i18n/ui/ko.json Outdated
Copy link
Copy Markdown

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

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: 12e13050ed

ℹ️ 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 thread plugin/plugins/galgame_plugin/static/main.js
…lders + ko auto_value

- Codex P1 (3198568766): startInstall('rapidocr_models') was crashing on
  `button.disabled = true` because getInstallNodes resolved
  domPrefix='rapidocr' → `rapidocrInstallBtn`, an element that was
  removed in PR Project-N-E-K-O#1191 (only `rapidocrModelsDownloadBtn` remains in
  index.html). Add a `buttonId` config override so the model-download
  flow binds to its real visible button. The download POST never fired
  before this fix.
- CodeRabbit 3198565024: `ui.first_run.install_ocr.pending_models`
  hardcoded "japan + PP-OCRv4" and "~10 MB" while
  `ui.install.rapidocr.missing_models_body` already used {lang}/{version}/
  {size} placeholders — switching default lang or selecting a non-japan
  pack would have made this string lie. Now uses the same placeholders
  across all 5 locales; renderRapidOcr's buildFirstRunSteps passes
  `lang_type / ocr_version / missing_model_total_size` via uiTf.
- CodeRabbit 3198565026: `ko.json:ui.common.auto_value` regressed from
  `(자동)` (main) to `(auto)` somewhere on this branch — restored.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

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

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: c2d25f53cb

ℹ️ 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 thread plugin/plugins/galgame_plugin/rapidocr_support.py
Copy link
Copy Markdown
Contributor

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
plugin/plugins/galgame_plugin/static/main.js (1)

3385-3405: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

RapidOCR 模型下载这条链路还差最后一段 UI 接线喵

现在 rapidocr_models 的 task state 虽然能恢复、能收 SSE,也会驱动 banner 按钮文案,但不会真正把复用的 rapidocrInstallState 进度卡片渲染出来喵。根因是 applyInstallTaskState() 在有 latestStatus 时只走 renderStatus(latestStatus),而 renderStatus() / renderRapidOcr() 并没有调用 renderInstallTaskState('rapidocr_models'),所以用户看不到百分比、错误详情和恢复后的进度卡片喵。顺手还有个连带问题:download_rapidocr_models 先精确滚到 rapidocrPrompt,但 startInstall('rapidocr_models') 里又会默认 scrollToSection: true,会把视口拉回 installSection 顶部,把刚展开的提示/进度区域顶走喵。

🐾 建议最小修法喵
 function renderRapidOcr(status) {
   const rapidocr = status.rapidocr || {};
   const runtime = status.ocr_reader_runtime || {};
+  renderInstallTaskState('rapidocr_models');
   const banner = document.getElementById('rapidocrPrompt');
   const kicker = document.getElementById('rapidocrPromptKicker');
   const title = document.getElementById('rapidocrPromptTitle');
   const body = document.getElementById('rapidocrPromptBody');
   const path = document.getElementById('rapidocrPathText');
-async function startInstall(kind, force = false) {
+async function startInstall(kind, force = false, { navigateKind = kind, scrollToSection = true } = {}) {
   const config = getInstallConfig(kind);

-  navigateToInstallPanel(kind);
+  navigateToInstallPanel(navigateKind, { scrollToSection });
 async function downloadRapidOcrModels(force = false) {
-  await startInstall('rapidocr_models', force);
+  await startInstall('rapidocr_models', force, {
+    navigateKind: 'rapidocr',
+    scrollToSection: false,
+  });
 }

Also applies to: 3572-3579, 4732-4764, 6002-6009, 6944-6951

🤖 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 `@plugin/plugins/galgame_plugin/static/main.js` around lines 3385 - 3405,
applyInstallTaskState currently skips rendering the per-kind install card when
latestStatus is set (it only calls renderStatus(latestStatus)); update the flow
so the rapidocr_models card is always updated: either (A) after
renderStatus(latestStatus) call renderInstallTaskState('rapidocr_models') when
kind === 'rapidocr_models' (or generally call renderInstallTaskState(kind) after
renderStatus when an install state exists), or (B) modify
renderStatus()/renderRapidOcr() to invoke renderInstallTaskState(kind) for
rapidocr_models; additionally fix the scrolling: in download_rapidocr_models
where you call startInstall('rapidocr_models') pass scrollToSection: false (and
change startInstall to respect a provided scrollToSection option instead of
always defaulting true) so the viewport doesn't jump back and hide the opened
prompt/progress area.
🤖 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.

Outside diff comments:
In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 3385-3405: applyInstallTaskState currently skips rendering the
per-kind install card when latestStatus is set (it only calls
renderStatus(latestStatus)); update the flow so the rapidocr_models card is
always updated: either (A) after renderStatus(latestStatus) call
renderInstallTaskState('rapidocr_models') when kind === 'rapidocr_models' (or
generally call renderInstallTaskState(kind) after renderStatus when an install
state exists), or (B) modify renderStatus()/renderRapidOcr() to invoke
renderInstallTaskState(kind) for rapidocr_models; additionally fix the
scrolling: in download_rapidocr_models where you call
startInstall('rapidocr_models') pass scrollToSection: false (and change
startInstall to respect a provided scrollToSection option instead of always
defaulting true) so the viewport doesn't jump back and hide the opened
prompt/progress area.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b63bd387-2096-4eb1-a43f-fbb6457e939c

📥 Commits

Reviewing files that changed from the base of the PR and between 12e1305 and c2d25f5.

📒 Files selected for processing (6)
  • plugin/plugins/galgame_plugin/i18n/ui/en.json
  • plugin/plugins/galgame_plugin/i18n/ui/ja.json
  • plugin/plugins/galgame_plugin/i18n/ui/ko.json
  • plugin/plugins/galgame_plugin/i18n/ui/ru.json
  • plugin/plugins/galgame_plugin/i18n/ui/zh-CN.json
  • plugin/plugins/galgame_plugin/static/main.js
🚧 Files skipped from review as they are similar to previous changes (5)
  • plugin/plugins/galgame_plugin/i18n/ui/ja.json
  • plugin/plugins/galgame_plugin/i18n/ui/en.json
  • plugin/plugins/galgame_plugin/i18n/ui/ko.json
  • plugin/plugins/galgame_plugin/i18n/ui/zh-CN.json
  • plugin/plugins/galgame_plugin/i18n/ui/ru.json

Codex P1 (3198594311): missing_model_files detection only ran in the
`bundled_spec is not None` branch. Upgrade users on a legacy
plugin-isolated install (find_spec()=None but package_dir exists) hit
the legacy `load_rapidocr_runtime` branch, set detail="installed", and
skipped the check entirely. With default lang_type=japan, that meant
`can_download_models=False`, no UI affordance to download japan rec, and
OCR silently fell back to bundled ch model.

Mirror the bundled branch's check in the legacy branch: after a
successful runtime load, run missing_rapidocr_model_files and flip
detail to "missing_model_files" if anything's absent.

Smoke-tested both paths:
- legacy + (ch, PP-OCRv4)     → detail=installed (bundled wheel models match)
- legacy + (japan, PP-OCRv4)  → detail=missing_model_files, can_download=True
                                missing=[ch_PP-OCRv4_det_mobile, japan_..._rec, cls]

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

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

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: 9df73c0a29

ℹ️ 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 thread plugin/plugins/galgame_plugin/rapidocr_support.py Outdated
…lenames

Codex P1 (3198594311 sibling): missing_rapidocr_model_files only checked
the registry's exact target_path filename in model_cache_dir, but
_resolve_rapidocr_model_paths happily accepts:
  - both filename conventions (_infer.onnx for wheel/Paddle pattern,
    _mobile.onnx / _server.onnx for ModelScope v3.x)
  - both locations (model_cache_dir + the imported package's models/ dir)

The mismatch meant inspect_rapidocr_installation could keep returning
detail="missing_model_files" + can_download_models=True even when
RapidOCR could already serve OCR successfully (e.g. wheel-bundled
ch_PP-OCRv4_det_infer.onnx satisfies the det requirement; the user
would see a perpetual download banner that does nothing because all
files RapidOCR needs are already there).

- Rewrite missing_rapidocr_model_files to delegate per-stage to the
  resolver; mark a stage missing only if det/cls/rec_path is None.
- Extend the resolver to also try `_alt_infer(name)` derivatives —
  e.g. for registry name `ch_PP-OCRv4_det_mobile.onnx` we also try
  `ch_PP-OCRv4_det_infer.onnx`. Without this, the wheel's `_infer`
  files were missed because they don't share the registry's prefix
  pattern (registry says ch det but resolver only tried lang-prefixed
  synthesized names).

Smoke verified 5 scenarios: japan+v4 with _mobile, japan+v4 with
_infer, empty cache, bundled ch+v4, and v5+japan cross-version
fallback (rec falls back to v4 japan rec). All resolve correctly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

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

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: 3e654b0ef5

ℹ️ 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 thread plugin/plugins/galgame_plugin/rapidocr_support.py Outdated
Codex P2 (3198652432): missing_rapidocr_model_files only derived
package_models_dir from importlib.util.find_spec(), but legacy
plugin-isolated installs are loaded via _rapidocr_import_context and
their `<install_target>/runtime/site-packages/rapidocr_onnxruntime`
package is not visible to find_spec — so files in the legacy package's
`models/` dir got reported as missing even though load_rapidocr_runtime
can use them. inspect_rapidocr_installation would then keep returning
detail="missing_model_files" for legacy installs.

Now scan both candidates (bundled via find_spec + legacy via
_rapidocr_package_dir) and merge "any candidate resolves a stage" into
the per-stage missing decision.

Smoke verified: legacy install with `_infer` wheel-pattern files in
`<target>/runtime/site-packages/rapidocr_onnxruntime/models/`,
find_spec→None, empty cache_dir → missing=[] (no false-positive banner).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 1607-1615: The CTA routing treats missing_model_files the same
regardless of whether models can actually be downloaded; update
buildFirstRunSteps where ocrInstallAction/rapidocrModelsMissing is computed to
require rapidocr.can_download_models === true before returning
'download_rapidocr_models' (otherwise choose a non-actionable informational
state), update renderRapidOcr to hide rapidocrModelsDownloadBtn and adjust
banner text when can_download_models is false, and prevent the viewport flip by
adding a skipNavigate flag to startInstall(kind, {skipNavigate}) (or have
downloadRapidOcrModels reuse the prior scroll) so
handleDiagnosisAction('download_rapidocr_models') that calls
downloadRapidOcrModels() won't immediately call navigateToInstallPanel via
startInstall.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 002fe232-1aec-41a1-96b4-2f97c0bd6daf

📥 Commits

Reviewing files that changed from the base of the PR and between 12e1305 and e9f9d4a.

📒 Files selected for processing (7)
  • plugin/plugins/galgame_plugin/i18n/ui/en.json
  • plugin/plugins/galgame_plugin/i18n/ui/ja.json
  • plugin/plugins/galgame_plugin/i18n/ui/ko.json
  • plugin/plugins/galgame_plugin/i18n/ui/ru.json
  • plugin/plugins/galgame_plugin/i18n/ui/zh-CN.json
  • plugin/plugins/galgame_plugin/rapidocr_support.py
  • plugin/plugins/galgame_plugin/static/main.js
🚧 Files skipped from review as they are similar to previous changes (4)
  • plugin/plugins/galgame_plugin/i18n/ui/en.json
  • plugin/plugins/galgame_plugin/i18n/ui/zh-CN.json
  • plugin/plugins/galgame_plugin/i18n/ui/ko.json
  • plugin/plugins/galgame_plugin/i18n/ui/ru.json

Comment thread plugin/plugins/galgame_plugin/static/main.js Outdated
CodeRabbit Major (3198805467): two state-misalignment bugs in the
RapidOCR missing-models path.

1. buildFirstRunSteps routed to download_rapidocr_models whenever
   detail==='missing_model_files' but didn't check can_download_models.
   The button itself was hidden via `!canDownloadModels`, but the
   tutorial banner still said "Click 'Download Now'" pointing at a
   hidden button. Now route to download_rapidocr_models only when
   `can_download_models === true`; when models are missing but
   auto-download isn't, drop the primary CTA entirely (no fake
   "Install Tesseract" surrogate either) and switch the body copy to
   `pending_models_manual` directing the user to the RapidOCR banner's
   manual recovery instructions. New i18n key added across 5 locales.

2. handleDiagnosisAction('download_rapidocr_models') explicitly used
   `navigateToInstallPanel('rapidocr', { scrollToSection: false })` +
   `expandAndScrollTo('rapidocrPrompt')` to position the viewport on
   the missing-models banner, then called downloadRapidOcrModels which
   went through startInstall → navigateToInstallPanel(kind) with the
   default scrollToSection=true, snapping the viewport back to
   installSection top on the next frame and undoing the careful
   positioning. Add a `navigate` option to startInstall and pass
   `{ navigate: false }` from downloadRapidOcrModels — both call sites
   (the diagnosis route and the in-banner button) already have the
   right view positioning.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

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

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: 744b622458

ℹ️ 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 thread plugin/plugins/galgame_plugin/static/main.js
Codex P2 (3198836320): when rapidocr_models state updates,
applyInstallTaskState normally takes the latestStatus → renderStatus →
renderRapidOcr path (efficiency optimization to re-render the whole
status). renderRapidOcr only synced the download button text/disabled
state and never touched renderInstallTaskState('rapidocr_models'), so
the in-banner progress card (rapidocrInstallState — status text,
percent, message, detail, progress bar) stayed hidden/stale during
running or failed downloads. Users saw the button label change but no
actual progress bar or error message.

Call renderInstallTaskState('rapidocr_models') from renderRapidOcr
when state exists so the card mirrors the runtime state. Guarded by
`if (installRuntime.rapidocr_models.state)` to avoid touching nodes
when no task has run yet (the card stays hidden).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@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: 2

🤖 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.

Inline comments:
In `@plugin/plugins/galgame_plugin/rapidocr_support.py`:
- Around line 1005-1010: The current sequence calls destination.unlink() before
tmp_path.replace(), which removes the target file and creates a race window;
remove the explicit destination.unlink() and rely on
tmp_path.replace(destination) (which uses os.replace and atomically overwrites
on POSIX/Windows) in the block around _verify_model_sha256(tmp_path, ...) so
that tmp_path.replace(destination) alone updates the file atomically and
maintain correct updates to downloaded_bytes and downloaded using spec and
asset_name.

In `@plugin/plugins/galgame_plugin/static/main.js`:
- Around line 1604-1632: The ocrReady check and the banner CTA handling leak two
cases: update ocrReady (symbol: ocrReady) to exclude the rapidocrModelsMissing
case so that tesseract.installed does not short-circuit readiness when
rapidocr.detail === 'missing_model_files' (use rapidocrModelsMissing to force
not-ready); and change the banner button state logic that currently only treats
'inProgress'/'failed' specially to also treat 'completed' as non-clickable (or
map 'completed' to the same disabled/awaiting-refresh state) so users cannot
start a second download before refreshAll() repopulates rapidocr.detail. Ensure
you reference rapidocrModelsMissing/rapidocrModelsDownloadable and the
refreshAll() refresh path when making these checks.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e0f53c3d-332f-4c6c-88b3-9a5f02fa9056

📥 Commits

Reviewing files that changed from the base of the PR and between 12e1305 and 744b622.

📒 Files selected for processing (7)
  • plugin/plugins/galgame_plugin/i18n/ui/en.json
  • plugin/plugins/galgame_plugin/i18n/ui/ja.json
  • plugin/plugins/galgame_plugin/i18n/ui/ko.json
  • plugin/plugins/galgame_plugin/i18n/ui/ru.json
  • plugin/plugins/galgame_plugin/i18n/ui/zh-CN.json
  • plugin/plugins/galgame_plugin/rapidocr_support.py
  • plugin/plugins/galgame_plugin/static/main.js
🚧 Files skipped from review as they are similar to previous changes (5)
  • plugin/plugins/galgame_plugin/i18n/ui/ja.json
  • plugin/plugins/galgame_plugin/i18n/ui/ko.json
  • plugin/plugins/galgame_plugin/i18n/ui/en.json
  • plugin/plugins/galgame_plugin/i18n/ui/ru.json
  • plugin/plugins/galgame_plugin/i18n/ui/zh-CN.json

Comment thread plugin/plugins/galgame_plugin/rapidocr_support.py
Comment thread plugin/plugins/galgame_plugin/static/main.js Outdated
1. rapidocr_support.py:1006 (Minor) — drop the redundant
   `destination.unlink()` before `tmp_path.replace(destination)`.
   Path.replace IS atomic overwrite on both POSIX and Windows
   (Python 3.3+); the explicit unlink-first opened a race window
   where the destination briefly didn't exist. force=True re-downloads
   were the worst case — concurrent inspect_rapidocr_installation
   would observe the file as missing during the gap.

2. main.js:1632 ocrReady (Major) — `tesseract.installed` was
   short-circuiting the readiness check, so a user with both
   Tesseract installed AND `rapidocr.detail==='missing_model_files'`
   never got the install_ocr tutorial step. Tesseract is a fallback
   for "rapidocr completely unavailable", not "rapidocr is there but
   the configured model isn't". Gate `tesseract.installed` behind
   `!rapidocrModelsMissing`.

3. main.js renderRapidOcr (Major) — banner button only handled
   inProgress/failed. After a download completes, there's a brief
   window before refreshAll repopulates rapidocr.detail, during
   which the button springs back to the actionable label and a
   second click would spawn another concurrent download. Add a
   `waitingRefresh = lastStatus==='completed' && rapidocr.detail==='missing_model_files'`
   gate that keeps the button disabled with explicit "task done,
   waiting for refresh" copy until the next status sweep clears
   the missing_model_files signal. New i18n key
   ui.install.task_done_refreshing × 5 locales.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

2 participants