Skip to content

feat: support paste upload file #543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 10, 2025
Merged

Conversation

madocto
Copy link
Contributor

@madocto madocto commented Jan 19, 2024

ref: ant-design/ant-design#46429

Summary by CodeRabbit

  • 文档

    • 新增两个演示文档页面,展示文件上传示例和导航配置。
  • 新功能

    • 优化文件上传体验,新增支持拖拽和粘贴上传的交互方式。
    • 引入全新示例组件,直观演示文件上传操作及多文件处理行为。
    • API 文档中新增 pastable 属性,支持粘贴上传功能。
  • 测试

    • 增加多项测试用例,验证粘贴上传、多文件限制以及错误处理,确保上传功能的稳定性。

Copy link

vercel bot commented Jan 19, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
upload ✅ Ready (Inspect) Visit Preview 💬 Add feedback Apr 9, 2025 11:57am

Copy link

codecov bot commented Jan 20, 2024

Codecov Report

Attention: Patch coverage is 93.75000% with 2 lines in your changes missing coverage. Please review.

Project coverage is 89.03%. Comparing base (02ea32a) to head (8b5d9c7).
Report is 3 commits behind head on master.

Files with missing lines Patch % Lines
src/AjaxUploader.tsx 93.75% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #543      +/-   ##
==========================================
+ Coverage   88.84%   89.03%   +0.18%     
==========================================
  Files           6        6              
  Lines         278      301      +23     
  Branches       73       83      +10     
==========================================
+ Hits          247      268      +21     
- Misses         31       33       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@afc163
Copy link
Member

afc163 commented Jan 20, 2024

图片

@crazyair
Copy link

crazyair commented Mar 25, 2024

是不是要跟拖拽上传一样风格

<Dragger {...props}>

@afc163
Copy link
Member

afc163 commented Mar 21, 2025

This branch has conflicts that must be resolved.

Copy link

coderabbitai bot commented Mar 21, 2025

Walkthrough

此次变更新增了两个 Markdown 文件(paste.mdpasteDirectory.md),分别配置前置信息与引用外部 TypeScript 示例。同时在 docs/examples 文件夹中添加了两个 React 组件,利用 rc-upload 库实现上传功能(支持拖拽及目录上传)。此外,对 src/AjaxUploader.tsx 文件中的上传逻辑进行了扩展和重命名,新增了针对鼠标事件与粘贴事件的处理方法,并更新了事件监听。测试文件中也新增了多个用例,以验证上述新增功能的行为。

Changes

文件/文件组 改动描述
docs/demo/paste.md
docs/demo/pasteDirectory.md
新增 Markdown 文件,包含前置信息和代码块,引用各自的外部 TS 示例
docs/examples/paste.tsx
docs/examples/pasteDirectory.tsx
新增 React 组件 Test,使用 rc-upload 实现拖拽上传(后者支持目录上传)
src/AjaxUploader.tsx 调整上传逻辑:重命名方法为 onFileDropOrPaste;新增 onPrePastehandleMouseEnterhandleMouseLeave 方法;更新事件监听
tests/uploader.spec.tsx 新增并调整多个测试用例,针对粘贴上传、文件类型筛选、多文件处理以及错误处理逻辑进行验证
README.md 新增属性 pastable,支持粘贴上传功能的文档说明
src/interface.tsx UploadProps 接口中新增可选属性 pastable

Sequence Diagram(s)

sequenceDiagram
    participant User as 用户
    participant Uploader as AjaxUploader
    participant RCUpload as rc-upload 组件

    User->>Uploader: 鼠标进入上传区域 (handleMouseEnter)
    User->>Uploader: 粘贴文件 (paste event)
    Uploader->>Uploader: onPrePaste 检测 isMouseEnter
    alt 鼠标在范围内
        Uploader->>Uploader: 执行 onFileDropOrPaste 处理粘贴文件
        Uploader->>RCUpload: 触发文件上传流程
    else
        Uploader-->>User: 忽略粘贴事件
    end
    User->>Uploader: 鼠标离开上传区域 (handleMouseLeave)
Loading

Poem

在代码森林中我蹦跳,
新增语句如花在枝头飘。
拖拽、粘贴巧协同,
测试守候不容稍,
小兔叹息欢欣笑 🐇✨
微风拂面代码飘。

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.

tests/uploader.spec.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "prettier" to extend from. Please check that the name of the config is correct.

The config "prettier" was referenced from the config file in "/.eslintrc.js".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@madocto
Copy link
Contributor Author

madocto commented Mar 21, 2025

@afc163 done

Copy link

@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 (10)
docs/demo/paste.md (1)

8-8: 代码标签格式需要修正

代码引用标签的格式有误。当前的 <code src="../examples/paste.tsx"/></code> 同时包含了自闭合标签和关闭标签,这是不正确的 Markdown 语法。

建议修改为以下格式:

-<code src="../examples/paste.tsx"/></code>
+<code src="../examples/paste.tsx" />
docs/demo/pasteDirectory.md (1)

8-8: 代码标签格式需要修正

代码引用标签的格式有误。当前的 <code src="../examples/pasteDirectory.tsx"/></code> 同时包含了自闭合标签和关闭标签,这是不正确的 Markdown 语法。

建议修改为以下格式:

-<code src="../examples/pasteDirectory.tsx"/></code>
+<code src="../examples/pasteDirectory.tsx" />
docs/examples/paste.tsx (2)

6-8: 建议增加更多文件类型支持

当前仅接受 .png 文件类型,考虑到粘贴上传的场景,用户可能会粘贴其他格式的图片(如 JPEG、GIF 等)。

-  accept: '.png',
+  accept: 'image/*',

36-36: 考虑国际化支持

组件中硬编码了中文文本 "开始上传",这可能不利于国际化。

考虑使用配置项或国际化工具来处理文本:

-          <a>开始上传</a>
+          <a>{props.buttonText || '开始上传'}</a>

或者在实际的项目中,使用国际化工具如 i18n:

-          <a>开始上传</a>
+          <a>{intl.get('upload.start') || '开始上传'}</a>
docs/examples/pasteDirectory.tsx (2)

8-9: 建议增加更多文件类型支持

当前仅接受 .png 文件类型,考虑到目录上传的场景,用户可能会上传各种格式的文件。

-  accept: '.png',
+  accept: '*/*',

37-37: 考虑国际化支持

组件中硬编码了中文文本 "开始上传",这可能不利于国际化。

考虑使用配置项或国际化工具来处理文本:

-          <a>开始上传</a>
+          <a>{props.buttonText || '开始上传'}</a>

或者在实际的项目中,使用国际化工具如 i18n:

-          <a>开始上传</a>
+          <a>{intl.get('upload.start') || '开始上传'}</a>
tests/uploader.spec.tsx (3)

59-59: 改进错误处理方式

这里的修改改进了错误处理,但可以进一步优化使用可选链操作符。

-            return error && error(new Error('read file error'));
+            return error?.(new Error('read file error'));
🧰 Tools
🪛 Biome (1.9.4)

[error] 59-59: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


376-379: 考虑直接在 rcUpload 上触发粘贴事件

目前测试在 input 上触发粘贴事件,但在真实场景中,粘贴事件是在文档级别被捕获的,并且在实现中只有当鼠标位于上传组件上时才处理。为保持一致性,建议直接在 rcUpload 元素上触发粘贴事件。

fireEvent.mouseEnter(rcUpload);
-fireEvent.paste(input, {
+fireEvent.paste(rcUpload, {
  clipboardData: { files },
});

444-446: 与之前建议一致,考虑在 rcUpload 上触发粘贴事件

同样的问题出现在这个测试中,建议在 rcUpload 上触发粘贴事件而不是 input。

fireEvent.mouseEnter(rcUpload);
-fireEvent.paste(input, { clipboardData: { files } });
+fireEvent.paste(rcUpload, { clipboardData: { files } });
src/AjaxUploader.tsx (1)

108-112: 粘贴事件预处理方法可以优化

此方法实现粘贴功能,但有两点可以改进:

  1. 缺少对禁用状态的检查
  2. 没有考虑到如果用户正在编辑文本时,阻止默认行为可能会干扰正常文本粘贴
onPrePaste(e: ClipboardEvent) {
-  if (this.isMouseEnter) {
+  // 检查组件是否启用并且鼠标在组件上
+  if (this.isMouseEnter && !this.props.disabled) {
+    // 只有在剪贴板包含文件时才阻止默认行为
+    if (e.clipboardData?.files?.length > 0) {
     this.onFileDropOrPaste(e);
+    }
  }
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 02ea32a and 4efc79a.

📒 Files selected for processing (6)
  • docs/demo/paste.md (1 hunks)
  • docs/demo/pasteDirectory.md (1 hunks)
  • docs/examples/paste.tsx (1 hunks)
  • docs/examples/pasteDirectory.tsx (1 hunks)
  • src/AjaxUploader.tsx (4 hunks)
  • tests/uploader.spec.tsx (10 hunks)
🧰 Additional context used
🧬 Code Definitions (2)
src/AjaxUploader.tsx (2)
src/interface.tsx (1) (1)
  • RcFile (78-80)
src/attr-accept.ts (1) (1)
  • file (4-53)
tests/uploader.spec.tsx (2)
src/AjaxUploader.tsx (1) (1)
  • render (295-361)
src/Upload.tsx (1) (1)
  • render (37-39)
🪛 Biome (1.9.4)
tests/uploader.spec.tsx

[error] 59-59: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (15)
docs/demo/paste.md (1)

1-8: 文件结构与元数据设置正确

Markdown 文件的 frontmatter 部分设置合理,包含了标题和导航路径的定义,这有助于在文档系统中正确显示和定位此示例。

docs/demo/pasteDirectory.md (1)

1-8: 文件结构与元数据设置正确

Markdown 文件的 frontmatter 部分设置合理,包含了标题和导航路径的定义,这有助于在文档系统中正确显示和定位此示例。

docs/examples/paste.tsx (2)

5-25: 配置对象结构清晰

props 对象的配置结构清晰,包含了上传所需的各种回调函数和样式属性。日志输出有助于调试和理解上传流程。


27-41: 组件实现简洁,但缺少实际的粘贴功能说明

虽然文件名为 paste.tsx,但组件中并没有明确处理粘贴事件的代码。根据 PR 的目标(支持粘贴上传文件),建议添加一些注释或文本说明,告知用户如何使用粘贴功能。

  return (
    <div
      style={{
        margin: 100,
      }}
    >
      <div>
+       <p style={{ marginBottom: 10 }}>支持粘贴上传文件 (Ctrl+V)</p>
        <Upload {...props}>
          <a>开始上传</a>
        </Upload>
      </div>
    </div>
  );
docs/examples/pasteDirectory.tsx (2)

5-26: 配置对象结构清晰

props 对象的配置结构清晰,包含了上传所需的各种回调函数和样式属性。日志输出有助于调试和理解上传流程。


28-42: 组件实现简洁,但缺少实际的粘贴功能说明

虽然文件名为 pasteDirectory.tsx,但组件中并没有明确处理粘贴事件的代码,也没有关于如何通过粘贴方式上传目录的说明。根据 PR 的目标(支持粘贴上传文件),建议添加一些注释或文本说明。

  return (
    <div
      style={{
        margin: 100,
      }}
    >
      <div>
+       <p style={{ marginBottom: 10 }}>支持粘贴上传目录 (Ctrl+V)</p>
        <Upload {...props}>
          <a>开始上传</a>
        </Upload>
      </div>
    </div>
  );
tests/uploader.spec.tsx (5)

352-384: 新增粘贴上传功能测试看起来很全面

这个测试用例验证了粘贴文件上传功能的正常工作,覆盖了鼠标进入、粘贴事件触发和请求响应等关键流程。设计合理,模拟了真实用户交互。


386-407: 不符合类型的粘贴文件测试逻辑完善

这个测试正确验证了当粘贴不符合 accept 类型的文件时,不会触发 onStart 回调。测试场景考虑全面。


479-492: 使用箭头函数和期望对象更新了测试断言

将函数声明更新为箭头函数并更新了期望对象中的断言,代码风格更加现代化和一致。


506-519: 添加鼠标进入和离开事件测试

这个测试很好地验证了 onMouseEnter 和 onMouseLeave 回调函数是否正确调用,支持新增的粘贴功能所需的鼠标状态跟踪。


785-805: 粘贴目录功能测试覆盖全面

测试正确验证了粘贴包含目录结构的功能,清晰地模拟了用户交互并验证了预期行为。

src/AjaxUploader.tsx (4)

31-31: 新增鼠标状态跟踪属性

添加 isMouseEnter 属性用于跟踪鼠标是否悬停在上传组件上,为支持粘贴上传功能奠定基础。


71-106: 重构方法支持文件拖放和粘贴

将 onFileDrop 重命名并扩展为 onFileDropOrPaste,支持处理拖放和粘贴事件。实现逻辑清晰,根据事件类型正确获取文件和项目。


283-293: 鼠标事件处理方法实现良好

handleMouseEnter 和 handleMouseLeave 方法实现简洁明了,既更新内部状态又调用可选的外部回调函数。


329-332: 事件监听更新支持新功能

事件处理器的更新正确使用了新添加的方法,支持粘贴上传和鼠标状态跟踪功能。

@ideaviewes
Copy link

这个什么时候可以合并呢?

}
};

onPrePaste(e: ClipboardEvent) {
if (this.isMouseEnter) {
Copy link
Member

Choose a reason for hiding this comment

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

可以做成一个开关来开启, hover 来做判断是非常不符合用户直觉的。

@madocto
Copy link
Contributor Author

madocto commented Apr 9, 2025

加一个 allowPasteUpload?: boolean ,默认为 false,控制是否允许粘贴上传。

componentDidMount() {
  this._isMounted = true;

  if (this.props.allowPasteUpload) {
    document.addEventListener('paste', this.onPrePaste.bind(this));
  }
}

onPrePaste(e: ClipboardEvent) {
  const { allowPasteUpload } = this.props;

  if (allowPasteUpload) {
    this.onFileDropOrPaste(e);
  }
}

如果页面上有两个 <Upload {...props} allowPasteUpload /> 都允许粘贴,那么同时触发粘贴事件吗?hover 的判断是不是要保留? @zombieJ

@zombieJ
Copy link
Member

zombieJ commented Apr 9, 2025

如果页面上有两个 <Upload {...props} allowPasteUpload /> 都允许粘贴,那么同时触发粘贴事件吗?hover 的判断是不是要保留? @zombieJ

如果都开就都同时黏贴。Hover 是不准的,比如 X 里一个 Attachment 会有多个 Upload,有一部分是隐藏态只是用来负责 trigger 上传的。让用户自己选择控制就好:

https://ant-design-x.antgroup.com/components/attachments-cn

Copy link

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

♻️ Duplicate comments (2)
src/AjaxUploader.tsx (2)

116-122: 🛠️ Refactor suggestion

在这里直接使用 .bind(this) 可能导致无法准确解绑事件。
应在类中预先绑定函数引用,以便在 componentWillUnmount 中移除相同的引用,避免潜在的内存泄漏。建议如下:

+ constructor(props) {
+   super(props);
+   this.boundOnPrePaste = this.onPrePaste.bind(this);
+ }

componentDidMount() {
  ...
- document.addEventListener('paste', this.onPrePaste.bind(this));
+ document.addEventListener('paste', this.boundOnPrePaste);
  ...
}

127-127: ⚠️ Potential issue

同理,在卸载组件时需移除相同的事件监听器引用。
如果不使用同一个绑定函数,则无法正确移除事件监听器,可能产生副作用。示例:

componentWillUnmount() {
  ...
- document.removeEventListener('paste', this.onPrePaste.bind(this));
+ document.removeEventListener('paste', this.boundOnPrePaste);
}
🧹 Nitpick comments (1)
tests/uploader.spec.tsx (1)

59-59: 建议使用可选链替代 error && error(...)
为避免重复条件判断,提高可读性,可使用可选链来调用回调函数,例如:

-            return error && error(new Error('read file error'));
+            return error?.(new Error('read file error'));
🧰 Tools
🪛 Biome (1.9.4)

[error] 59-59: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4efc79a and 1ad93d6.

📒 Files selected for processing (4)
  • README.md (1 hunks)
  • src/AjaxUploader.tsx (2 hunks)
  • src/interface.tsx (1 hunks)
  • tests/uploader.spec.tsx (10 hunks)
🧰 Additional context used
🧠 Learnings (1)
src/AjaxUploader.tsx (1)
Learnt from: zombieJ
PR: react-component/upload#543
File: src/AjaxUploader.tsx:116-116
Timestamp: 2025-04-09T06:22:00.335Z
Learning: 在 react-component/upload 项目中,黏贴上传功能应该是可配置的,只有当启用此功能时才应添加 paste 事件监听器,而不是无条件添加。同时,事件监听器绑定应使用预先绑定的方法而非直接使用 .bind(this) 以避免内存泄漏。
🧬 Code Graph Analysis (1)
src/AjaxUploader.tsx (2)
src/interface.tsx (1)
  • RcFile (79-81)
src/attr-accept.ts (1)
  • file (4-53)
🪛 Biome (1.9.4)
tests/uploader.spec.tsx

[error] 59-59: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (11)
src/interface.tsx (1)

47-47: 可选属性 allowPasteUpload 的添加非常有用。
此属性为用户提供了启用或禁用黏贴上传功能的灵活度,与更新后的文档说明一致,值得肯定。

README.md (1)

87-87: 文档说明与接口定义保持一致。
在使用表格的形式补充了 allowPasteUpload 属性的介绍,默认值和用途都写得清晰,可进一步帮助使用者了解黏贴上传的功能。

tests/uploader.spec.tsx (6)

352-383: 黏贴上传的测试用例逻辑清晰。
该用例验证了在启用 allowPasteUpload 后,能正确触发黏贴事件并完成上传流程,测试覆盖度不错。


385-406: 验证不接受的文件类型时不触发 onStart
用例准确地测试了对不符合 accept 条件的文件进行黏贴不会触发上传,覆盖场景全面。


408-447: “paste files with multiple=false” 实现可控性良好。
该用例确认了黏贴多个文件时只会上传首个文件,与 multiple={false} 功能保持一致,测试覆盖细致。


476-488: 检查 customRequest 接收的文件结构。
通过断言传入的 file 对象来确保上传事件能获得正确的 filename 等字段,有助于避免请求参数错误。


502-516: 为鼠标事件添加测试场景,全面验证交互细节。
此测试涵盖了 onMouseEnteronMouseLeave,可以帮助及时发现相关事件处理中的疏漏。


689-736: 异步文件读取抛出错误时的场景处理到位。
该单测验证 readEntries 异常时只会解析部分文件,可对整体健壮性提供保障,测试逻辑合理。

src/AjaxUploader.tsx (3)

69-104: 整合 onFileDropOrPaste 用于处理拖拽和黏贴逻辑十分巧妙。
dragover 事件与 droppaste 区分处理,让代码结构更简洁,同时正确过滤不符合 accept 的文件,提升了可维护性。


106-113: onPrePaste 方法配合 allowPasteUpload
通过提前判断是否启用黏贴上传,有效规避了不必要的逻辑执行,设计思路不错。


326-327: 拖拽事件绑定到相同方法使逻辑更加集中。
通过 onFileDropOrPaste 同时处理 onDroponDragOver,减少重复代码,但请注意在 dragover 时需要阻止默认行为,避免文件在浏览器中被直接打开。

README.md Outdated
@@ -84,6 +84,7 @@ React.render(<Upload />, container);
|customRequest | function | null | provide an override for the default xhr behavior for additional customization|
|withCredentials | boolean | false | ajax upload with cookie send |
|openFileDialogOnClick | boolean | true | useful for drag only upload as it does not trigger on enter key or click event |
|allowPasteUpload | boolean | false | support paste upload |
Copy link
Member

Choose a reason for hiding this comment

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

这个命名不符合 antd 的 name standard,用 pastable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Select 有 allowClear 🐶

componentDidMount() {
this._isMounted = true;

const { allowPasteUpload } = this.props;
Copy link
Member

Choose a reason for hiding this comment

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

动态切换就不行了,componentDidUpdate 也需要确定

}
};

onPrePaste(e: ClipboardEvent) {
Copy link
Member

Choose a reason for hiding this comment

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

onPrePaste(e: ClipboardEvent) {} 改成 onPrePaste = (e: ClipboardEvent) => {}

这样你下面就不需要 this.onPrePaste.bind

Copy link

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

♻️ Duplicate comments (3)
src/AjaxUploader.tsx (3)

106-112: 🛠️ Refactor suggestion

新增onPrePaste方法正确实现可配置的粘贴上传

此方法正确地检查了pastable属性,只有当该属性为true时才处理粘贴事件,这符合之前的讨论约定。不过,建议将方法定义为箭头函数,以避免this绑定问题,符合之前的审阅反馈。

-  onPrePaste = (e: ClipboardEvent) => {
+  onPrePaste = (e: ClipboardEvent) => {
     const { pastable } = this.props;

     if (pastable) {
       this.onFileDropOrPaste(e);
     }
   };

114-122: 🛠️ Refactor suggestion

生命周期方法处理粘贴事件监听器

componentDidMount中根据pastable属性条件添加粘贴事件监听器的实现是正确的。不过,目前使用的是类方法直接引用,而没有使用预先绑定的函数,这可能在某些情况下导致this上下文问题。

结合上一条建议将onPrePaste改为箭头函数后,这里不需要额外绑定this


124-128: ⚠️ Potential issue

移除事件监听器存在潜在问题

componentWillUnmount中,移除事件监听器时没有检查pastable属性,可能会在pastable为false时尝试移除不存在的监听器。应该与添加逻辑保持一致,只在pastable为true时才移除。

  componentWillUnmount() {
    this._isMounted = false;
    this.abort();
-   document.removeEventListener('paste', this.onPrePaste);
+   if (this.props.pastable) {
+     document.removeEventListener('paste', this.onPrePaste);
+   }
  }
🧹 Nitpick comments (1)
tests/uploader.spec.tsx (1)

59-59: 改进了错误处理逻辑

在异步文件读取过程中,错误处理逻辑现在正确地使用了可选链,这符合最佳实践。不过建议进一步优化这部分代码以提高代码质量。

-            return error && error(new Error('read file error'));
+            return error?.(new Error('read file error'));
🧰 Tools
🪛 Biome (1.9.4)

[error] 59-59: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f62c96e and b45b533.

📒 Files selected for processing (6)
  • README.md (1 hunks)
  • docs/examples/paste.tsx (1 hunks)
  • docs/examples/pasteDirectory.tsx (1 hunks)
  • src/AjaxUploader.tsx (2 hunks)
  • src/interface.tsx (1 hunks)
  • tests/uploader.spec.tsx (10 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/interface.tsx
  • docs/examples/pasteDirectory.tsx
  • README.md
  • docs/examples/paste.tsx
🧰 Additional context used
🧠 Learnings (1)
src/AjaxUploader.tsx (1)
Learnt from: zombieJ
PR: react-component/upload#543
File: src/AjaxUploader.tsx:116-116
Timestamp: 2025-04-09T06:22:00.335Z
Learning: 在 react-component/upload 项目中,黏贴上传功能应该是可配置的,只有当启用此功能时才应添加 paste 事件监听器,而不是无条件添加。同时,事件监听器绑定应使用预先绑定的方法而非直接使用 .bind(this) 以避免内存泄漏。
🧬 Code Graph Analysis (2)
tests/uploader.spec.tsx (2)
src/AjaxUploader.tsx (1)
  • render (298-366)
src/attr-accept.ts (1)
  • file (4-53)
src/AjaxUploader.tsx (2)
src/interface.tsx (2)
  • RcFile (79-81)
  • UploadProps (7-48)
src/attr-accept.ts (1)
  • file (4-53)
🪛 Biome (1.9.4)
tests/uploader.spec.tsx

[error] 59-59: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (9)
tests/uploader.spec.tsx (6)

352-383: 测试用例实现良好

新增的"paste to upload"测试用例很好地验证了粘贴上传的基本功能,覆盖了关键流程。测试结构清晰,与现有的拖拽上传测试保持一致的风格,这有助于维护代码的一致性。


385-406: 测试用例完善了边界情况

这个测试用例验证了当粘贴不符合accept条件的文件类型时,不会触发onStart回调,这是一个重要的边界条件测试。测试逻辑与现有的拖拽上传的类似测试保持一致,有助于确保功能的完整性。


408-447: 测试用例完整覆盖了multiple=false的场景

这个测试用例验证了当multiple设置为false时,即使粘贴多个文件也只会上传第一个文件。测试结构与拖拽上传的类似测试保持一致,通过triggerTimes变量有效地验证了只触发一次上传。


476-488: 更新了Jest断言语法

将测试断言更新为使用更现代的Jest匹配器语法,提高了代码可读性和测试的可维护性。代码中的注释也指明了这与PR #574相关,表明了良好的变更追踪。


503-516: 添加了鼠标事件测试

新增对onMouseEnter和onMouseLeave事件的测试用例,确保这些事件在组件中正确工作。这些测试有助于确保用户交互体验的完整性。


782-803: 添加了粘贴目录的测试用例

此测试用例验证了粘贴包含目录结构的内容的功能,确保系统能够正确处理复杂的粘贴场景。测试用例结构清晰,且逻辑完善。

src/AjaxUploader.tsx (3)

69-104: 方法重命名和扩展功能实现良好

onFileDrop改名为onFileDropOrPaste并扩展其功能以同时处理拖放和粘贴事件,这是一种非常好的复用方式。代码逻辑清晰,通过检查事件类型来区分不同的处理流程。方法的参数类型声明也很准确。


130-138: 组件更新时正确处理事件监听器

componentDidUpdate中处理pastable属性变化时添加或移除粘贴事件监听器的实现是正确的。这确保了动态切换粘贴上传功能的正确行为。


336-337: 更新事件处理程序引用

更新了拖放相关事件处理程序以使用新的onFileDropOrPaste方法,保持了代码的一致性。

@@ -400,6 +499,21 @@ describe('uploader', () => {

fireEvent.change(input, { target: { files } });
});

it('support onMouseEnter and onMouseLeave', async () => {
Copy link
Member

Choose a reason for hiding this comment

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

这个测试不需要了

clipboardData: { files },
});

setTimeout(() => {
Copy link
Member

Choose a reason for hiding this comment

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

应该是不需要 setTimeout 的,如果要用那就改成 await sleep,下同

Copy link

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

🧹 Nitpick comments (1)
tests/uploader.spec.tsx (1)

59-59: 考虑使用可选链运算符提高代码可读性和健壮性

当前实现使用 error && error(...) 的模式来调用可能不存在的 error 函数。建议使用 ES2020 的可选链运算符,使代码更简洁、更易读。

-            return error && error(new Error('read file error'));
+            return error?.(new Error('read file error'));
🧰 Tools
🪛 Biome (1.9.4)

[error] 59-59: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b45b533 and 8b5d9c7.

📒 Files selected for processing (1)
  • tests/uploader.spec.tsx (9 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
tests/uploader.spec.tsx

[error] 59-59: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (5)
tests/uploader.spec.tsx (5)

352-381: 新增粘贴上传测试用例实现正确

这个测试用例完整验证了粘贴上传功能的基本流程,包括触发粘贴事件、处理文件和响应上传结果。代码使用 await sleep 替代 setTimeout,符合最佳实践。


383-402: 验证不接受类型的粘贴上传测试实现合理

这个测试用例验证了当粘贴不符合 accept 属性的文件类型时,不会触发 onStart 回调,这是正确的行为。测试逻辑简洁明了。


404-436: 多文件粘贴时 multiple=false 的行为测试实现正确

这个测试用例正确验证了在 multiple=false 的情况下粘贴多个文件时,只会处理第一个文件。使用 await sleep 而不是 setTimeout 符合之前的代码评审建议。


465-477: 自定义请求测试增强了验证内容

should pass file to request 测试的重构改进了断言的明确性,使用了更现代的 Jest 断言语法,同时保持了原有的测试目的。代码注释中引用了相关 PR (#574) 提供了有用的上下文。


756-775: 目录粘贴上传测试实现完善

这个测试用例验证了粘贴上传目录结构的功能,模拟了鼠标进入和粘贴事件,并验证了 onStart 回调被正确触发。使用 await sleep 处理异步逻辑符合最佳实践。

@zombieJ zombieJ merged commit 8564e5f into react-component:master Apr 10, 2025
9 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.

5 participants