Skip to content

feat: implement batch selection and deletion for apps#673

Merged
Yundi339 merged 4 commits into
masterfrom
feat_deleteapps
May 25, 2026
Merged

feat: implement batch selection and deletion for apps#673
Yundi339 merged 4 commits into
masterfrom
feat_deleteapps

Conversation

@Yundi339
Copy link
Copy Markdown
Member

No description provided.

qiin2333 and others added 3 commits May 24, 2026 23:02
RX 9070 + Adrenalin 26.5.x freezes after ~2min on H.264/HEVC streaming
because Sunshine's direct-AMF integration hardcodes aggressive properties
(LOWLATENCY_MODE=true, INPUT_QUEUE_SIZE=1, HIGH_MOTION_QUALITY_BOOST=true,
AV1 ENCODING_LATENCY_MODE=LOWEST_LATENCY) that force less-traveled VCN
paths. AV1 is unaffected because users typically don't hit those props
through other means.

Mirror FFmpeg amfenc convention: every aggressive opt is std::optional,
default = nullopt = skip SetProperty = use AMD driver default. Streaming-
required props kept hardcoded (QUERY_TIMEOUT=1, IDR_PERIOD/GOP_SIZE=0,
B_PIC_PATTERN=0, HEVC NUM_GOPS_PER_IDR=1 + IDR_ALIGNED, AV1 NO_RESTRICTIONS).

Exposed to WebUI under new 'AMF Advanced (Driver Workarounds)' accordion
with empty-string = driver default round-trip through optional<>.

Affected props:
  - LOWLATENCY_MODE (H.264/HEVC)
  - INPUT_QUEUE_SIZE (H.264/HEVC/AV1)
  - HIGH_MOTION_QUALITY_BOOST_ENABLE (H.264/HEVC)
  - AV1 ENCODING_LATENCY_MODE

Refs: #666
)

Hand-ported subset of upstream LizardByte/Sunshine 738ac93:
adds check_content_type() helper and calls it at the start of POST handlers
for /api/apps, /api/apps/close, /api/apps/<id> (DELETE), /api/clients/unpair,
/api/clients/unpair-all, /api/config, /api/covers/upload, /api/password,
/api/pin, /api/restart, and /api/reset-display-device-persistence.

AlkaidLab does not have upstreams bad_request() helper, so the bad-request
response is inlined inside check_content_type() as a local lambda; the
behavior matches upstream (HTTP 400 + JSON body with status_code/status/error).

AlkaidLab-specific POST endpoints (AI/LLM proxy at /api/ai/config and
/api/ai/chat/completions, QR pairing at /api/qr-pair{,/cancel}, client
rename at /api/clients/rename, /api/apps/test-menu-cmd, /api/logout) are
intentionally NOT covered by this PR; reviewer may extend the same check
to those if desired.

HTML-side Content-Type-on-fetch changes from upstream are skipped:
AlkaidLab UI is heavily restructured for Chinese localization + AI UI
and using a different request framework.

(cherry picked from commit 738ac93)

Signed-off-by: dkgkdfg65 <219107372+dkgkdfg65@users.noreply.github.com>
Co-authored-by: dkgkdfg65 <219107372+dkgkdfg65@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

Review Change Stack

Summary by CodeRabbit

  • 新功能
    • 应用列表支持多选与批量删除:切换多选、单/全选、清空选择、批量删除确认与结果反馈
    • 新增批量删除接口支持一次删除多个应用
    • 客户端服务新增批量删除调用并在操作后刷新列表
  • 样式
    • 为批量选择/操作新增界面样式
  • 本地化
    • 为 24 种语言添加批量操作相关文案

Walkthrough

新增后端Content-Type校验与批量删除HTTP处理器;前端新增多选/批量删除状态与方法、API 客户端、UI 选择与确认对话框、样式调整,并为多语言资源添加批量操作文案键。

变更概览

批量删除应用功能

Layer / File(s) Summary
后端HTTP处理器与Content-Type校验
src/confighttp.cpp
新增通用 check_content_type 并在多个POST入口使用;新增 batchDeleteApps 处理函数,使用 apps_writing 写锁、解析并验证 indices、单次重写 file_apps 并调用 proc::refresh,在路由中注册 POST ^/api/apps/batch-delete$
前端组合式状态与批量删除逻辑
src_assets/common/assets/web/composables/useApps.js
新增 selectionModeselectedIndicesbatchDeleteConfirmisBatchDeleting 等响应式状态与方法(切换、多选/全选/清空、发起/取消/确认批量删除),并在 init 使用 i18n translate 展示本地化消息。
前端API客户端与端点配置
src_assets/common/assets/web/services/appService.js, src_assets/common/assets/web/utils/constants.js
新增 AppService.batchDeleteApps(indices) 发起 POST /api/apps/batch-delete,容错解析响应并返回数值化的 deletedremainingAPI_ENDPOINTS 新增 APP_BATCH_DELETE 常量。
UI组件与选择交互
src_assets/common/assets/web/views/Apps.vue
新增多选模式切换按钮、批量操作工具栏(显示已选数量、全选/清空/批量删除)、为网格/列表项增加复选框与选择行为、禁用拖拽并将 edit 行为在选择模式下改为切换选中;新增批量删除确认对话框并在 <script setup> 解构 useApps() 的新增 API。
批量选择样式
src_assets/common/assets/web/styles/apps.less
新增 .batch-action-bar.batch-action-info.batch-action-buttons 工具栏样式,添加 .app-card-wrapper.selection-mode / .is-selected.app-list-wrapper 对应选择态样式,以及 .app-select-checkbox 复选框覆盖层样式与修饰器。
国际化文案支持
src_assets/common/assets/web/public/assets/locale/*.json
为多语言 locale 文件新增8个批量操作相关键:batch_select_togglebatch_selectedbatch_select_allbatch_clearbatch_deletebatch_delete_confirmbatch_delete_resultbatch_delete_failed

序列图

sequenceDiagram
  participant User as 用户
  participant UI as Apps.vue
  participant Composable as useApps
  participant Service as AppService
  participant Backend as 后端API
  User->>UI: 点击切换多选模式
  UI->>Composable: toggleSelectionMode()
  Composable->>UI: selectionMode=true
  User->>UI: 勾选应用复选框
  UI->>Composable: toggleAppSelection(index)
  Composable->>UI: selectedIndices更新
  User->>UI: 点击批量删除
  UI->>Composable: askBatchDelete()
  Composable->>UI: batchDeleteConfirm=true
  UI->>User: 显示确认对话框
  User->>UI: 确认删除
  UI->>Composable: confirmBatchDelete()
  Composable->>Service: batchDeleteApps(indices数组)
  Service->>Backend: POST /api/apps/batch-delete
  Backend->>Service: {deleted, remaining}
  Service->>Composable: 返回删除结果
  Composable->>UI: 刷新应用列表,清空选择
  Composable->>UI: 显示成功或失败消息
  UI->>User: 展示删除结果提示
Loading

🎯 3 (Moderate) | ⏱️ ~25 minutes

可能相关的 PR:

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive PR缺少描述信息,无法评估其与changeset的关联性。 建议作者补充PR描述,说明此功能的目的、实现方式或任何相关的上下文信息。
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed PR标题「feat: implement batch selection and deletion for apps」准确总结了主要功能变更——在应用模块新增批量选择与批量删除能力。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat_deleteapps

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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.

@Yundi339 Yundi339 linked an issue May 25, 2026 that may be closed by this pull request
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
src_assets/common/assets/web/styles/apps.less (1)

554-575: ⚡ Quick win

为选择复选框补充键盘焦点可见态

.app-select-checkbox 目前只有 :hover 态;键盘导航时焦点反馈不够明确,建议补充 :focus-visible,避免无鼠标场景下难以定位当前控件。

♿ 建议修改
 .app-select-checkbox {
   position: absolute;
@@
   &:hover {
     background: rgba(99, 102, 241, 0.9);
   }
+
+  &:focus-visible {
+    outline: 2px solid var(--bs-primary, `#6366f1`);
+    outline-offset: 2px;
+  }
 
   &--list {
🤖 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 `@src_assets/common/assets/web/styles/apps.less` around lines 554 - 575, The
.app-select-checkbox lacks keyboard-focused styling; add a :focus-visible rule
for .app-select-checkbox to provide a clear, accessible focus indicator (e.g., a
visible outline or box-shadow and maintain contrast) so keyboard users can
identify the control; update the selector .app-select-checkbox:focus-visible to
set an accessible outline/box-shadow, ensure pointer-events and background
interactions remain consistent with :hover, and keep transition behavior in the
relevant CSS block.
🤖 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 `@src_assets/common/assets/web/views/Apps.vue`:
- Around line 50-57: The toggle button for batch selection is missing
accessibility state semantics; update the button element that uses selectionMode
and toggleSelectionMode to include aria-pressed bound to selectionMode (e.g.,
:aria-pressed="selectionMode") and add an explicit aria-label that reflects the
action/state (e.g., :aria-label="$t('apps.batch_select_toggle') + (selectionMode
? ' ' + $t('on') : ' ' + $t('off'))" or a concise localized label), ensuring the
same button that currently has :class and :title is the one updated so screen
readers get the toggle role and current state.
- Around line 137-145: The custom checkbox divs with role="checkbox" (the block
controlled by selectionMode and using isAppSelected(index) and
toggleAppSelection(index) in Apps.vue) are not keyboard-focusable or operable;
make them accessible by adding tabindex="0" so they are tabbable, and add a
keyboard handler (e.g., `@keydown`) that listens for Space and Enter and invokes
toggleAppSelection(index) (with appropriate .stop/.prevent) so keyboard users
can toggle selection; keep the existing `@click` behavior and ensure aria-checked
remains in place.

In `@src/confighttp.cpp`:
- Around line 1017-1020: 返回空删除请求时缺少与其他成功响应一致的 remaining 字段:在处理
indices_to_remove.empty() 分支中(同一函数使用到变量 indices_to_remove 和 outputTree),在设置
outputTree.put("status", "true") 和 outputTree.put("deleted", 0") 后也写入
outputTree.put("remaining", <当前 apps 数量>);获取当前 apps
数量可以复用后续计数路径或读取保存应用列表/容器的变量/方法以获得一致的值,保证该分支与其它成功响应字段契约一致。
- Around line 975-980: The error branches currently only populate outputTree and
call response->write(data.str()) inside the fail_guard, which leaves the HTTP
status at 200; introduce a status_code variable (default 200) alongside
outputTree and g, update each error branch that builds an error response to set
status_code to the appropriate value (e.g., 400, 409), and before writing the
JSON in the fail_guard set the response HTTP status using the response object
(e.g., response->set_status(status_code) or response->setStatus(status_code)) so
the written body and status code are consistent; apply this pattern for the
blocks around outputTree/g/response->write and the other listed ranges (991-995,
997-1001, 1010-1015, 1033-1037, 1057-1061).

---

Nitpick comments:
In `@src_assets/common/assets/web/styles/apps.less`:
- Around line 554-575: The .app-select-checkbox lacks keyboard-focused styling;
add a :focus-visible rule for .app-select-checkbox to provide a clear,
accessible focus indicator (e.g., a visible outline or box-shadow and maintain
contrast) so keyboard users can identify the control; update the selector
.app-select-checkbox:focus-visible to set an accessible outline/box-shadow,
ensure pointer-events and background interactions remain consistent with :hover,
and keep transition behavior in the relevant CSS block.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 43eb6626-2482-408c-86da-29f96faeae6d

📥 Commits

Reviewing files that changed from the base of the PR and between 1666732 and 434c525.

📒 Files selected for processing (26)
  • src/confighttp.cpp
  • src_assets/common/assets/web/composables/useApps.js
  • src_assets/common/assets/web/public/assets/locale/bg.json
  • src_assets/common/assets/web/public/assets/locale/cs.json
  • src_assets/common/assets/web/public/assets/locale/de.json
  • src_assets/common/assets/web/public/assets/locale/en.json
  • src_assets/common/assets/web/public/assets/locale/en_GB.json
  • src_assets/common/assets/web/public/assets/locale/en_US.json
  • src_assets/common/assets/web/public/assets/locale/es.json
  • src_assets/common/assets/web/public/assets/locale/fr.json
  • src_assets/common/assets/web/public/assets/locale/it.json
  • src_assets/common/assets/web/public/assets/locale/ja.json
  • src_assets/common/assets/web/public/assets/locale/ko.json
  • src_assets/common/assets/web/public/assets/locale/pl.json
  • src_assets/common/assets/web/public/assets/locale/pt.json
  • src_assets/common/assets/web/public/assets/locale/pt_BR.json
  • src_assets/common/assets/web/public/assets/locale/ru.json
  • src_assets/common/assets/web/public/assets/locale/sv.json
  • src_assets/common/assets/web/public/assets/locale/tr.json
  • src_assets/common/assets/web/public/assets/locale/uk.json
  • src_assets/common/assets/web/public/assets/locale/zh.json
  • src_assets/common/assets/web/public/assets/locale/zh_TW.json
  • src_assets/common/assets/web/services/appService.js
  • src_assets/common/assets/web/styles/apps.less
  • src_assets/common/assets/web/utils/constants.js
  • src_assets/common/assets/web/views/Apps.vue
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Windows
🧰 Additional context used
📓 Path-based instructions (2)
src_assets/**/*.{vue,js,html}

⚙️ CodeRabbit configuration file

src_assets/**/*.{vue,js,html}: 基于 Vue.js 的 Web 配置面板。审查 XSS/CSRF 安全性、 组件设计、状态管理和可访问性。

Files:

  • src_assets/common/assets/web/services/appService.js
  • src_assets/common/assets/web/utils/constants.js
  • src_assets/common/assets/web/composables/useApps.js
  • src_assets/common/assets/web/views/Apps.vue
src/**/*.{cpp,c,h}

⚙️ CodeRabbit configuration file

src/**/*.{cpp,c,h}: Sunshine 核心 C++ 源码,自托管游戏串流服务器。审查要点:内存安全、 线程安全、RAII 资源管理、安全漏洞。注意预处理宏控制的平台相关代码。

Files:

  • src/confighttp.cpp
🔇 Additional comments (25)
src_assets/common/assets/web/public/assets/locale/bg.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/cs.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/de.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/en.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/en_GB.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/en_US.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/es.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/fr.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/it.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/ja.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/ko.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/pl.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/pt.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/pt_BR.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/ru.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/sv.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/tr.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/uk.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/zh.json (1)

57-64: LGTM!

src_assets/common/assets/web/public/assets/locale/zh_TW.json (1)

57-64: LGTM!

src/confighttp.cpp (1)

2963-2963: LGTM!

src_assets/common/assets/web/composables/useApps.js (1)

39-42: LGTM!

Also applies to: 73-77, 175-241, 615-618, 639-646

src_assets/common/assets/web/services/appService.js (1)

83-103: LGTM!

src_assets/common/assets/web/utils/constants.js (1)

85-86: LGTM!

src_assets/common/assets/web/views/Apps.vue (1)

148-153: ⚡ Quick win

多选模式下需禁用拖拽与单项删除,避免 selectedIndices 基于索引导致误删

src_assets/common/assets/web/views/Apps.vueselectionMode 下,列表仍可能发生重排/结构变更(对应 draggable :disabled="false"),同时单项删除仍绑定 @delete="showDeleteForm(index)"(也影响 218-222、251-253)。若 selectedIndices 按“索引”存储,重排后索引可能漂移,导致后续批量删除删除到错误应用。

建议修复(示例)
-          :disabled="false"
+          :disabled="selectionMode"
...
-          :disabled="false"
+          :disabled="selectionMode"
-                `@delete`="showDeleteForm(index)"
+                `@delete`="selectionMode ? undefined : showDeleteForm(index)"
...
-                `@delete`="showDeleteForm(index)"
+                `@delete`="selectionMode ? undefined : showDeleteForm(index)"
...
-              `@delete`="showDeleteForm(getOriginalIndex(app, index))"
+              `@delete`="selectionMode ? undefined : showDeleteForm(getOriginalIndex(app, index))"

Comment thread src_assets/common/assets/web/views/Apps.vue
Comment thread src_assets/common/assets/web/views/Apps.vue
Comment thread src/confighttp.cpp
Comment thread src/confighttp.cpp
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/confighttp.cpp (1)

1028-1048: 💤 Low value

文件读取与索引验证逻辑清晰,但建议增加防御性检查

当前逻辑在读取 JSON 后直接调用 get_child("apps"s)(Line 1041),如果配置文件存在但缺少 apps 数组,会抛出 ptree_bad_path 异常且未被捕获,导致 fail_guard 返回空响应体 {}

虽然这与 deleteApp/saveApp 的现有模式一致,但建议增加防御性检查:

🛡️ 建议增加防御性检查
     }
     catch (std::exception &e) {
       BOOST_LOG(warning) << "BatchDeleteApps: "sv << e.what();
       outputTree.put("status", "false");
       outputTree.put("error", "Invalid File JSON");
       return;
     }

+    auto apps_node_opt = fileTree.get_child_optional("apps"s);
+    if (!apps_node_opt) {
+      outputTree.put("status", "false");
+      outputTree.put("error", "Invalid File JSON: missing 'apps' array");
+      return;
+    }
+
     // Validate every index against the single snapshot we just loaded BEFORE
     // any write, so a partially invalid request fails atomically.
-    const int apps_count = static_cast<int>(fileTree.get_child("apps"s).size());
+    const int apps_count = static_cast<int>(apps_node_opt->size());
🤖 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 `@src/confighttp.cpp` around lines 1028 - 1048, The code assumes the JSON
contains an "apps" child and calls fileTree.get_child("apps"s) which can throw
ptree_bad_path; update the logic around pt::ptree fileTree / pt::read_json and
where apps_count is computed so you first verify the presence and type of "apps"
(e.g. use get_child_optional or count/find) before calling get_child("apps"s),
and if missing or not an array set outputTree.put("status","false") and
outputTree.put("error","Invalid or missing apps array") and return; adjust the
validation loop that uses indices_to_remove and apps_count accordingly to avoid
uncaught exceptions from get_child.
🤖 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 `@src_assets/common/assets/web/views/Apps.vue`:
- Line 146: 在 Apps.vue 中四个复选框(网格/列表 + 搜索/非搜索)当前都使用相同的
aria-label="$t('apps.batch_select_toggle')",导致读屏用户无法区分项;请把每个复选框的 aria-label
改为包含对应应用名(使用 app.name),例如通过将 $t 调用传入 name 参数或拼接 app.name,确保每个复选框的 aria-label
唯一且包含 app.name(定位参考 symbol: aria-label, $t('apps.batch_select_toggle'),
app.name,在文件 Apps.vue 的四个复选框块里同步修改)。

---

Nitpick comments:
In `@src/confighttp.cpp`:
- Around line 1028-1048: The code assumes the JSON contains an "apps" child and
calls fileTree.get_child("apps"s) which can throw ptree_bad_path; update the
logic around pt::ptree fileTree / pt::read_json and where apps_count is computed
so you first verify the presence and type of "apps" (e.g. use get_child_optional
or count/find) before calling get_child("apps"s), and if missing or not an array
set outputTree.put("status","false") and outputTree.put("error","Invalid or
missing apps array") and return; adjust the validation loop that uses
indices_to_remove and apps_count accordingly to avoid uncaught exceptions from
get_child.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a9e20687-b9b1-491f-a92f-d32fc1fb9e4b

📥 Commits

Reviewing files that changed from the base of the PR and between 434c525 and e33e2b9.

📒 Files selected for processing (3)
  • src/confighttp.cpp
  • src_assets/common/assets/web/styles/apps.less
  • src_assets/common/assets/web/views/Apps.vue
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Windows
🧰 Additional context used
📓 Path-based instructions (2)
src_assets/**/*.{vue,js,html}

⚙️ CodeRabbit configuration file

src_assets/**/*.{vue,js,html}: 基于 Vue.js 的 Web 配置面板。审查 XSS/CSRF 安全性、 组件设计、状态管理和可访问性。

Files:

  • src_assets/common/assets/web/views/Apps.vue
src/**/*.{cpp,c,h}

⚙️ CodeRabbit configuration file

src/**/*.{cpp,c,h}: Sunshine 核心 C++ 源码,自托管游戏串流服务器。审查要点:内存安全、 线程安全、RAII 资源管理、安全漏洞。注意预处理宏控制的平台相关代码。

Files:

  • src/confighttp.cpp
🔇 Additional comments (3)
src/confighttp.cpp (3)

1050-1057: 已修复:空删除请求现在正确返回 remaining 字段

此更改解决了先前评审中指出的"空删除请求成功返回里缺少 remaining 字段"问题,确保了与非空路径的响应契约一致。


949-956: LGTM!


981-991: 状态码处理逻辑已修复,符合 uploadCover() 的约定

新增的 fail_guard 逻辑检查 error 字段来决定返回 400 还是 200,解决了先前评审中指出的"错误分支返回 200"问题。

一个小建议:当前所有错误(包括文件 I/O 失败)都返回 400,而文件写入失败实际上是服务端错误(5xx)。不过这与 uploadCover() 的模式一致,属于现有约定。

role="checkbox"
tabindex="0"
:aria-checked="isAppSelected(index)"
:aria-label="$t('apps.batch_select_toggle')"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

每个应用复选框应包含应用名,避免读屏标签重复

Line 146、Line 181、Line 224、Line 258 当前都使用同一个 aria-label,读屏时难以区分正在操作哪一个应用。建议把 app.name 拼入标签。

♿ 建议修改
-:aria-label="$t('apps.batch_select_toggle')"
+:aria-label="`${$t('apps.batch_select_toggle')}: ${app.name}`"

同样改动请同步到 4 个复选框块(网格/列表 + 搜索/非搜索)。

As per coding guidelines, src_assets/**/*.{vue,js,html} 需要重点审查“可访问性”。

Also applies to: 181-181, 224-224, 258-258

🤖 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 `@src_assets/common/assets/web/views/Apps.vue` at line 146, 在 Apps.vue
中四个复选框(网格/列表 + 搜索/非搜索)当前都使用相同的
aria-label="$t('apps.batch_select_toggle')",导致读屏用户无法区分项;请把每个复选框的 aria-label
改为包含对应应用名(使用 app.name),例如通过将 $t 调用传入 name 参数或拼接 app.name,确保每个复选框的 aria-label
唯一且包含 app.name(定位参考 symbol: aria-label, $t('apps.batch_select_toggle'),
app.name,在文件 Apps.vue 的四个复选框块里同步修改)。

@Yundi339 Yundi339 merged commit 8bb3a5a into master May 25, 2026
4 checks passed
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.

[Feature]: 批量删除串流页的应用程序(Applications)

3 participants