fix: 在非安全上下文中为 copyMessage 添加 execCommand 备用方案 by alonguser · Pull Request #7747 · AstrBotDevs/AstrBot · GitHub
Skip to content

fix: 在非安全上下文中为 copyMessage 添加 execCommand 备用方案#7747

Open
alonguser wants to merge 1 commit intoAstrBotDevs:masterfrom
alonguser:fix/copy-fallback-non-secure-context
Open

fix: 在非安全上下文中为 copyMessage 添加 execCommand 备用方案#7747
alonguser wants to merge 1 commit intoAstrBotDevs:masterfrom
alonguser:fix/copy-fallback-non-secure-context

Conversation

@alonguser
Copy link
Copy Markdown

@alonguser alonguser commented Apr 23, 2026

在非安全上下文中(例如通过 HTTP 局域网 IP 访问),navigator.clipboard 不可用。为此,我们添加了使用 document.execCommand(‘copy’) 的备用方案,这与 ReadmeDialog.vue 和 Settings.vue 中的现有实现保持一致。

Fixes #7739

Modifications / 改动点

  • 修改 dashboard/src/components/chat/MessageList.vue
  • 新增 tryFallbackCopy() 函数,使用 document.execCommand('copy') 实现复制
  • 修改 copyMessage(),安全上下文优先用 Clipboard API,否则回退到 tryFallbackCopy()
  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

由于代码运行在 Docker 容器内,无法直接修改编译后的文件进行测试。


Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
    / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。

  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
    / 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”

  • 🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
    / 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 requirements.txtpyproject.toml 文件相应位置。

  • 😮 My changes do not introduce malicious code.
    / 我的更改没有引入恶意代码。

Summary by Sourcery

Bug Fixes:

  • Ensure copying chat messages works when the Clipboard API is unavailable in non-secure (e.g., HTTP) contexts by falling back to a document.execCommand-based implementation.

在非安全上下文中(例如通过 HTTP 局域网 IP 访问),navigator.clipboard 不可用。为此,我们添加了使用 document.execCommand(‘copy’) 的备用方案,这与 ReadmeDialog.vue 和 Settings.vue 中的现有实现保持一致。
@auto-assign auto-assign Bot requested review from Raven95676 and Soulter April 23, 2026 09:54
@dosubot dosubot Bot added size:S This PR changes 10-29 lines, ignoring generated files. feature:chatui The bug / feature is about astrbot's chatui, webchat labels Apr 23, 2026
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a fallback mechanism for copying text to the clipboard using a hidden textarea when the Clipboard API is unavailable or the context is insecure. Feedback suggests making the fallback implementation more robust by using fixed positioning and read-only attributes, refactoring it into a shared utility to eliminate code duplication, and adding error handling to the primary Clipboard API call to ensure the fallback is triggered upon failure.

Comment on lines +449 to +461
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.

medium

建议优化 tryFallbackCopy 的实现并考虑将其提取为公共工具函数。设置 readOnly 可以防止在移动设备上弹出虚拟键盘,使用 position: fixed 并将其移出可视区域比 position: absolute 更稳健,能有效避免页面滚动或布局抖动。此外,PR 描述提到此逻辑在 ReadmeDialog.vueSettings.vue 中也有重复,建议根据通用规则将其重构为共享函数以提高可维护性。

function tryFallbackCopy(text: string) {
  const textArea = document.createElement("textarea");
  textArea.value = text;
  textArea.readOnly = true;
  Object.assign(textArea.style, {
    position: "fixed",
    left: "-9999px",
    top: "0",
  });
  document.body.appendChild(textArea);
  textArea.select();
  try {
    document.execCommand("copy");
  } catch (err) {
    console.error("Fallback copy failed:", err);
  } finally {
    document.body.removeChild(textArea);
  }
}
References
  1. 当在不同场景下实现类似功能时,应将逻辑重构为共享的辅助函数以避免代码重复。

Comment on lines +466 to +470
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard.writeText(text);
} else {
tryFallbackCopy(text);
}
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.

medium

即使在安全上下文中,navigator.clipboard.writeText 也可能因为用户拒绝权限或其他运行时错误而失败。建议增加错误处理,确保在 Clipboard API 抛出异常时也能回退到 tryFallbackCopy

  if (navigator.clipboard && window.isSecureContext) {
    try {
      await navigator.clipboard.writeText(text);
      return;
    } catch (err) {
      console.warn("Clipboard API failed, falling back:", err);
    }
  }
  tryFallbackCopy(text);

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • The new tryFallbackCopy implementation duplicates the existing clipboard fallback logic used in ReadmeDialog.vue and Settings.vue; consider extracting a shared utility to avoid divergence between implementations.
  • document.execCommand('copy') is deprecated and can fail silently; it may be worth wrapping tryFallbackCopy in a try/catch and optionally checking the boolean return value so the caller can handle failures more gracefully.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `tryFallbackCopy` implementation duplicates the existing clipboard fallback logic used in `ReadmeDialog.vue` and `Settings.vue`; consider extracting a shared utility to avoid divergence between implementations.
- `document.execCommand('copy')` is deprecated and can fail silently; it may be worth wrapping `tryFallbackCopy` in a try/catch and optionally checking the boolean return value so the caller can handle failures more gracefully.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@RC-CHN
Copy link
Copy Markdown
Member

RC-CHN commented Apr 24, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature:chatui The bug / feature is about astrbot's chatui, webchat size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 局域网IP的HTTP访问时WebUI 代码块复制按钮无效

2 participants