feat(social): 实现社交解锁状态管理与多语言支持 - #2672
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🔗 Linked repositories identifiedCodeRabbit considers these linked repositories for cross-repo context during reviews:
🚧 Files skipped from review as they are similar to previous changes (1)
Walkthrough本 PR 新增卡片制作器嵌入模式、轻量模型运行时、社交按钮三天解锁状态、版本化静态资源缓存校验,以及项目根目录导入规范化喵。 Changes卡片制作器与嵌入运行时
社交入口解锁
静态资源与导入路径
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested labels: Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
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 `@static/avatar/avatar-ui-buttons/methods-buttons.js`:
- Around line 108-113: Update refreshButtons() in
static/avatar/avatar-ui-buttons/methods-buttons.js:108-113 to query the
data-social-button marker written by applyButtonState(), or consistently change
registration to use data-neko-social-button. In
tests/frontend/social_unlock_state.test.cjs:77-105, make the mocked
document.querySelectorAll() return registered buttons and verify
refreshButtons() clears locked styling and updates the title on the unlock date.
In `@static/js/card_maker_embed_bootstrap.js`:
- Around line 44-53: Update _YUI_GUIDE_ASSET_VERSION_PATHS in
main_routers/pages_router.py to include all seven Live2D runtime assets loaded
by loadLive2DRuntime in static/js/card_maker_embed_bootstrap.js: the four
static/libs files plus live2d-core.js, live2d-emotion.js, and live2d-model.js.
Add regression assertions in tests/unit/test_card_maker_embed_static.py covering
lines 94-100 to verify each runtime asset changes static_asset_version produced
by _static_assets_ctx().
🪄 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 Plus
Run ID: de0dfe45-d807-4701-8be1-f1e265aca1e1
📒 Files selected for processing (22)
app/main_server/web_app.pymain_routers/pages_router.pystatic/app/app-ui/surface-floating-controls.jsstatic/avatar/avatar-ui-buttons/methods-buttons.jsstatic/js/card_maker.jsstatic/js/card_maker_embed_bootstrap.jsstatic/live2d/live2d-model.jsstatic/locales/en.jsonstatic/locales/es.jsonstatic/locales/ja.jsonstatic/locales/ko.jsonstatic/locales/pt.jsonstatic/locales/ru.jsonstatic/locales/zh-CN.jsonstatic/locales/zh-TW.jsonstatic/mmd/mmd-init.jsstatic/social-embed.jsstatic/vrm/vrm-init.jstemplates/card_maker.htmltests/frontend/avatar_ui_buttons_split.test.cjstests/frontend/social_unlock_state.test.cjstests/unit/test_card_maker_embed_static.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Project-N-E-K-O/N.E.K.O.-PC(manual)
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2cc2cd7ec4
ℹ️ 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".
|
|
||
| function refreshButtons() { | ||
| const status = getStatus(); | ||
| document.querySelectorAll('[data-neko-social-button="true"]').forEach((btn) => { |
There was a problem hiding this comment.
Use the same social-button marker when refreshing
When the midnight timer or localechange calls refreshButtons(), this selector never matches because applyButtonState() marks the button via btn.dataset.socialButton = 'true' (data-social-button), and there is no writer for data-neko-social-button. Users who leave the app open until the 3-day lock expires, or whose button initializes before i18n finishes, keep the grey disabled styling and stale title even though clicks are now allowed; query the same attribute that is actually set.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
该问题已在前一修复提交 fb0f3f2 中处理:refreshButtons() 已改为查询 data-social-button 标记,并补充了解锁日刷新测试。
| if b"v=" in scope.get("query_string", b""): | ||
| response.headers["Cache-Control"] = "public, max-age=31536000, immutable" |
There was a problem hiding this comment.
Don’t make fixed-version submodules immutable
Applying a one-year immutable policy to every static URL containing v= also covers dynamically loaded modules whose cache buster is not tied to the file contents; for example, I checked static/mmd/mmd-init.js, which still loads all MMD submodules with the fixed ?v=1.0.0. After a user opens an MMD avatar once, a later release that changes one of those submodules can keep serving the old cached file for up to a year, so this should either be limited to URLs using the computed static_asset_version or those loaders need to propagate a changing version.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
已处理,提交 5a27377:immutable 缓存现在只对内容派生的时间戳版本启用,固定版本如 MMD 的 ?v=1.0.0 不再被缓存一年;新增了覆盖动态/固定版本的缓存策略测试。
| "screenShare": "Screen Share", | ||
| "social": "Neko Community", | ||
| "social": "nekoverse", | ||
| "socialCharging": "nekoverse charging — come back in {{days}} days.", |
There was a problem hiding this comment.
Bump the locale cache version with new keys
Adding buttons.socialCharging requires bumping the locale cache buster in static/i18n-i18next.js; it still requests locale files with LOCALE_VERSION = '2026-07-27-merged-main-i18n', and the new immutable static caching means returning users can keep an older /static/locales/*.json?v=2026-07-27-merged-main-i18n that lacks this key for up to a year. In that case the locked social button renders the raw buttons.socialCharging key instead of the countdown text.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
已处理,提交 5a27377:将 LOCALE_VERSION 更新为 2026-08-04-social-unlock,确保新增的 buttons.socialCharging 文案不会继续命中旧语言包缓存;相关 Node/Python 定向测试已通过。
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
tests/unit/test_static_cache_policy.py (1)
6-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win补充
CustomStaticFiles的响应头回归测试喵。当前参数化用例只覆盖
_has_generated_asset_version喵。它没有调用CustomStaticFiles.get_response,因此app/main_server/web_app.pyLine 59-60 的响应头行为即使回归,测试仍会通过喵。请添加有效v、无效v和缺失v的响应级测试,并在合并前运行完整测试套件喵。🤖 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 `@tests/unit/test_static_cache_policy.py` around lines 6 - 19, Extend test_only_generated_asset_versions_enable_immutable_cache with response-level tests for CustomStaticFiles.get_response, covering a valid v value, an invalid v value, and a missing v value. Assert the resulting response headers match the intended immutable-cache behavior, so regressions in CustomStaticFiles rather than only _has_generated_asset_version are detected; run the full test suite afterward.
🤖 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 `@app/main_server/web_app.py`:
- Around line 45-50: 在处理版本尾部的逻辑中更新条件,使 version_tail 同时满足 isascii() 和
isdigit(),确保仅接受 ASCII 数字;保留现有长度与版本参数筛选行为,并为 Unicode 数字尾部补充否定测试。
In `@static/i18n-i18next.js`:
- Around line 32-34: 将 static/i18next.js 中 LOCALE_VERSION 的日期格式值改为
_has_generated_asset_version 接受的生成资源版本格式,以启用 immutable 缓存策略;同时同步更新
static/yui-guide-day1-systray-intro.test.cjs 中对应的版本断言,确保测试与新版本值一致。
---
Nitpick comments:
In `@tests/unit/test_static_cache_policy.py`:
- Around line 6-19: Extend
test_only_generated_asset_versions_enable_immutable_cache with response-level
tests for CustomStaticFiles.get_response, covering a valid v value, an invalid v
value, and a missing v value. Assert the resulting response headers match the
intended immutable-cache behavior, so regressions in CustomStaticFiles rather
than only _has_generated_asset_version are detected; run the full test suite
afterward.
🪄 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 Plus
Run ID: 3db8c2a2-4f5e-4033-a3f3-c68a1c9d8ae5
📒 Files selected for processing (5)
app/main_server/web_app.pystatic/i18n-i18next.jsstatic/yui-guide-day1-systray-intro.test.cjstests/unit/test_card_maker_embed_static.pytests/unit/test_static_cache_policy.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Project-N-E-K-O/N.E.K.O.-PC(manual)
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/unit/test_card_maker_embed_static.py
|
关于本轮缓存策略测试的 nitpick:已处理,提交 939aecd 新增了真实调用 CustomStaticFiles.get_response() 的响应级测试,覆盖内容派生版本、固定版本和缺失版本三种情况,并断言最终 Cache-Control 响应头。 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 939aecda52
ℹ️ 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".
| if path.endswith(".js"): | ||
| response.headers["Content-Type"] = "application/javascript" | ||
| if _has_generated_asset_version(scope.get("query_string", b"")): | ||
| response.headers["Cache-Control"] = "public, max-age=31536000, immutable" |
There was a problem hiding this comment.
Limit immutable caching to complete asset versions
Because this header is now applied solely from the shape of the v query, every ?v={{ static_asset_version }} URL must be covered by the timestamp that generated it. I checked templates/index.html and /static/social-embed.js?v={{ static_asset_version }} is emitted there, but social-embed.js is not part of _YUI_GUIDE_ASSET_VERSION_PATHS; after a patch that only changes that script while APP_VERSION and the tracked paths stay unchanged, clients that already cached it under the unchanged generated v can keep the old embed for up to a year. Either make the version depend on all versioned assets or only mark known tracked paths immutable.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
已处理,提交 56cbafc:将 static/social-embed.js 加入 _YUI_GUIDE_ASSET_VERSION_PATHS。现在该文件内容变化会更新 static_asset_version,避免继续复用旧的 immutable 缓存。
There was a problem hiding this comment.
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 `@tests/unit/test_plugin_sdk_packaging.py`:
- Line 46: 在测试函数 test_current_sdk_modules_are_importable 开始时调用
_ensure_project_root_first,确保导入所有 plugin.sdk 模块前项目根目录优先。保留现有调用,并让该 helper
在相关两个测试开始前都执行,避免测试顺序影响模块解析。
🪄 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 Plus
Run ID: f3df3f29-7e82-4a26-b7a6-589f6e63c8d1
📒 Files selected for processing (2)
launcher_core/runtime.pytests/unit/test_plugin_sdk_packaging.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Project-N-E-K-O/N.E.K.O.-PC(manual)
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2228de5855
ℹ️ 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".
| window._mmdModulesLoading = true; | ||
| window._mmdModulesFailed = null; | ||
| console.log('[MMD] 开始加载依赖模块'); | ||
| const lightweightEmbed = window.__NEKO_CARD_MAKER_EMBED__ === true; |
There was a problem hiding this comment.
Add mmd-init to static version inputs
When only the MMD loader changes after this release, clients that opened the main page can keep /static/mmd/mmd-init.js?v={{ static_asset_version }} cached under the new immutable policy, but main_routers/pages_router.py still tracks only static/mmd/mmd-ui-buttons.js for MMD, not this loader. That means changes like this lightweight-embed branch may not reach existing users until some unrelated tracked asset changes or the one-year cache expires; include mmd-init.js (or the MMD loader set) in the static asset version inputs before serving it immutably.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
已处理,提交 56cbafc:将 static/mmd/mmd-init.js 加入 _YUI_GUIDE_ASSET_VERSION_PATHS,MMD loader 的变更现在会触发新的静态资源版本。
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 56cbafc4a7
ℹ️ 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".
| if _has_generated_asset_version(scope.get("query_string", b"")): | ||
| response.headers["Cache-Control"] = "public, max-age=31536000, immutable" |
There was a problem hiding this comment.
Track every asset before serving it immutable
Fresh evidence after the current fixes: templates/index.html still serves assets such as /static/app/app-chat.js?v={{ static_asset_version }} (lines 411-412), but _YUI_GUIDE_ASSET_VERSION_PATHS only includes selected static/app files and the app-ui/app-interpage globs, not static/app/app-chat.js (main_routers/pages_router.py lines 97-103). With this new header, a release that changes only one of those untracked versioned files keeps the same generated v, so returning clients can reuse the old script for up to a year; either make the version input cover every static_asset_version URL or restrict immutable to known tracked assets.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
已处理,感谢指出。之前版本仅维护了部分静态资源清单,导致模板中的 app-chat.js 等资源单独变更时版本号不会更新。现在 pages_router 会自动扫描 templates 中所有带 static_asset_version 的静态资源引用,并将实际存在的文件加入版本计算,同时保留运行时/非模板资源的手工清单。新增回归测试覆盖全部模板引用;修复已在提交 90cd5e0 中推送。
There was a problem hiding this comment.
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 `@tests/unit/test_card_maker_embed_static.py`:
- Around line 142-153: Update test_template_versioned_static_assets_are_tracked
to assert referenced_paths is non-empty and explicitly contains ROOT /
"static/js/card_maker_embed_bootstrap.js" before the existing subset and
tracked-path assertions, ensuring the template scan actually discovers a known
versioned asset.
🪄 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 Plus
Run ID: 8c00d129-de46-48c2-9954-c47a7787a954
📒 Files selected for processing (2)
main_routers/pages_router.pytests/unit/test_card_maker_embed_static.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Project-N-E-K-O/N.E.K.O.-PC(manual)
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3c1cca1f9f
ℹ️ 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".
| if path.endswith(".js"): | ||
| response.headers["Content-Type"] = "application/javascript" | ||
| if _has_generated_asset_version(scope.get("query_string", b"")): | ||
| response.headers["Cache-Control"] = "public, max-age=31536000, immutable" |
There was a problem hiding this comment.
Limit immutable caching to version-owned assets
Fresh evidence after the template-scan fix: static/app/app-react-chat-window/cat-local-chat.js builds /static/assets/neko-idle/thought-items/cat1-chat-angry.gif?v=<react_chat_asset_version> from its own script URL, but _REACT_CHAT_ASSET_VERSION_PATHS in main_routers/pages_router.py does not include that GIF. With this broad Cache-Control, a release that changes only that image keeps the same numeric React-chat version, so clients that have already loaded the cat-local-chat sticker can reuse the old image for up to a year; include that asset in the React-chat version inputs or only mark paths owned by the version immutable.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
已处理,提交 7600458。cat1-chat-angry.gif 现在加入 _REACT_CHAT_ASSET_VERSION_PATHS,因此由 cat-local-chat.js 继承的 react_chat_asset_version 会随该 GIF 的 mtime 更新;同时补充回归断言。定向 pytest 39/39、Ruff、Node 语法检查均通过。
| '/static/vrm/vrm-cursor-follow.js', | ||
| ...(!lightweightEmbed ? [ | ||
| '/static/vrm/vrm-interaction.js', | ||
| '/static/vrm/vrm-cursor-follow.js' |
There was a problem hiding this comment.
Keep VRM cursor tracking disabled in embeds
When mode=embed skips vrm-cursor-follow.js, VRMManager._initMouseLookAtTracking() falls back to the legacy mousemove path because CursorFollowController is undefined; that path installs a document mousemove listener and the animation loop still assigns vrm.lookAt.target to the fallback target even after disableMouseTracking() sets tracking false. VRM card embeds can therefore keep following the viewer's mouse despite the lightweight/static embed intent; either keep the cursor-follow controller loaded so it can be disabled, or gate the fallback path on the embed/disabled tracking state.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
已处理,提交 7600458。VRM legacy fallback 现在完整遵守鼠标跟踪禁用状态:禁用时不初始化/处理 mousemove,移除已注册 listener 并清空 lookAt target;重新启用时可恢复 fallback。补充了对应静态契约测试。定向 pytest 39/39、Ruff、Node 语法检查均通过。
There was a problem hiding this comment.
🧹 Nitpick comments (1)
tests/unit/test_vrm_interaction_static_contracts.py (1)
24-40: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win让静态契约测试验证控制流位置喵
Line 36-40 只验证字符串存在于方法片段中。它不能证明
removeEventListener(...)位于if (!effectiveEnabled)分支,也不能证明_initMouseLookAtTracking()只在启用路径执行喵。未来把这些调用移到无条件路径时,测试仍可能通过。请按分支边界拆分源码片段,或使用 AST/VM 测试验证这两个控制流不变量喵。
🤖 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 `@tests/unit/test_vrm_interaction_static_contracts.py` around lines 24 - 40, 更新 test_vrm_legacy_mouse_tracking_respects_disabled_state,使其按 setMouseTrackingEnabled(enabled) 中的启用与禁用分支拆分源码并分别断言:removeEventListener(...) 仅位于 !effectiveEnabled 分支,_initMouseLookAtTracking() 仅位于启用路径;不要仅在整个方法片段中检查字符串存在。保留现有对初始化和动画禁用状态的断言。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@tests/unit/test_vrm_interaction_static_contracts.py`:
- Around line 24-40: 更新
test_vrm_legacy_mouse_tracking_respects_disabled_state,使其按
setMouseTrackingEnabled(enabled) 中的启用与禁用分支拆分源码并分别断言:removeEventListener(...) 仅位于
!effectiveEnabled 分支,_initMouseLookAtTracking()
仅位于启用路径;不要仅在整个方法片段中检查字符串存在。保留现有对初始化和动画禁用状态的断言。
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: cfd99e8b-d941-4031-9a89-b0b22843a652
📒 Files selected for processing (4)
main_routers/pages_router.pystatic/vrm/vrm-manager.jstests/unit/test_avatar_return_button_cat1_static.pytests/unit/test_vrm_interaction_static_contracts.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
Project-N-E-K-O/N.E.K.O.-PC(manual)
🚧 Files skipped from review as they are similar to previous changes (1)
- main_routers/pages_router.py
|
已处理本轮 CodeRabbit nitpick,提交 |
变更内容
验证
回归报告 / Regression Report
Summary by CodeRabbit