跳转到内容

Clipboard

Clipboard 提供一层轻量的文本复制 API,用来统一 browser / WebView 应用里常见的复制到剪贴板逻辑。

它解决的是运行时基础问题:优先使用原生 Clipboard API,并在受限 WebView 或不支持原生 API 时尝试兼容 fallback。它不负责 toast、埋点、按钮状态、复制内容序列化、读取剪贴板、剪切或粘贴输入规则。

适合场景

场景推荐入口说明
复制分享链接clipboard.writeText例如新闻详情、活动页、邀请链接。
复制调试日志clipboard.writeText业务先把日志格式化成字符串,再传给 runtime。
复制配置或 JSONclipboard.writeText对象序列化由业务负责。
输入框粘贴处理组件自己的 paste 事件需要结合 selection、readonly 和业务规则。

基础使用

ts
import { createClipboard } from '@freenotes/web-runtime';

const clipboard = createClipboard();

try {
  await clipboard.writeText('hello');
  showToast('已复制');
} catch (error) {
  showToast('复制失败,请稍后重试');
  reportCopyError(error);
}

writeText 返回 Promise<void>:某种写入策略报告成功时 resolve,所有策略失败时 reject ClipboardError

错误的 kind 区分 invalid-inputunavailablewrite-failedcodeERR_CLIPBOARD_*。单个策略失败时 cause 保留原始异常,多个策略失败时 cause 是按尝试顺序排列的只读异常数组。可通过根入口导入 ClipboardError 并使用 instanceof 判断。

业务应该自己决定成功失败后的 UI 反馈和业务上报。

为什么不直接导出 writeText

不提供:

ts
writeText('hello');

writeText 脱离 clipboard 后语义太泛,后续容易和文件、编辑器、日志、bridge 等能力冲突。

推荐:

ts
await clipboard.writeText('hello');

这个写法和原生 API 对齐:

ts
await navigator.clipboard.writeText('hello');

同时也符合 runtime 的能力分组规则:

ts
createStorage('local').set('ready', true);
await createDb().open({ name: 'app', stores: { notes: { keyPath: 'id' } } });
await clipboard.writeText('hello');

可用性判断

ts
const available = clipboard.isAvailable();

isAvailable() 只表示当前环境看起来存在可用策略,例如 navigator.clipboard.writeTextdocument.execCommand('copy') fallback。

剪贴板写入经常依赖:

  • HTTPS 或安全上下文。
  • 浏览器权限。
  • 用户手势,例如点击按钮。
  • WebView 宿主策略。
  • iOS WebKit 对选区和复制时机的限制。

因此 isAvailable() 不能保证下一次 writeText() 一定成功。最终仍应以 writeText() 的 Promise 结果为准。

兼容策略

clipboard.writeText(text) 会按下面顺序尝试:

  1. navigator.clipboard.writeText(text)
  2. 临时 textarea + document.execCommand('copy')
  3. 临时 contenteditable + document.execCommand('copy')

fallback 元素会在复制后移除,并尽量恢复原来的选区和焦点。

不做什么

Clipboard 第一版不提供:

ts
clipboard.readText();
clipboard.cut();
clipboard.paste();

原因是:

  • 读取剪贴板涉及更强的权限和隐私约束,当前没有稳定通用场景。
  • 粘贴通常来自输入框的 paste 事件,需要由组件结合 selection、格式归一化和业务规则处理。
  • 剪切通常由浏览器原生输入控件完成,runtime 不应接管用户编辑行为。

Clipboard 也不接管 vConsole 复制按钮这类特殊事件链路。此类问题通常需要业务在对应工具初始化时单独 patch。

API 速查

API说明
clipboard.writeText(text)尽力把文本写入系统剪贴板。
clipboard.isAvailable()判断当前环境是否看起来存在复制策略。

让基础能力保持简单,让业务开发更加专注。