Skip to content
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

[Feat]支持 Sender 组件 content 自定义渲染,以支持类似的 speech 交互变体需求或者支持其他的content自定义渲染需求 #354

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

LofiSu
Copy link

@LofiSu LofiSu commented Dec 13, 2024

支持 Sender 组件 content 自定义渲染,以支持类似的 speech 交互变体需求或者支持其他的content自定义渲染需求
image
image

Link To : #290

Summary by CodeRabbit

  • 新功能

    • 添加了自定义内容组件,支持语音输入和状态管理。
    • 增加了中英文文档示例,展示如何实现自定义内容。
  • 文档

    • 更新了中英文文档,增加了自定义内容的代码示例。
  • 依赖更新

    • 新增依赖:styled-components 和开发依赖 @types/styled-components

Copy link
Contributor

coderabbitai bot commented Dec 13, 2024

📝 Walkthrough
📝 Walkthrough

Walkthrough

本次更改引入了新的功能和文档更新,包括为 CustomContent 组件添加中英文支持。新增的 CustomContent.tsx 文件实现了一个自定义语音输入接口,允许用户通过 Ant Design 框架进行交互。相关文档也更新了示例,以展示如何在 Sender 组件中使用自定义内容。package.json 文件中添加了 styled-components 作为新依赖项。

Changes

文件路径 更改摘要
components/sender/demo/CustomContent.md 新增中英文部分,描述 content 组件的功能。
components/sender/demo/CustomContent.tsx 新增 CustomContent.tsx 文件,包含 CustomContentProps 接口和 Demo 组件,管理录音状态和用户交互。
components/sender/index.en-US.md 在示例部分新增 "Custom content" 的代码引用。
components/sender/index.tsx 更新 SenderComponents 接口,新增可选属性 content,并添加条件渲染逻辑。
components/sender/index.zh-CN.md 在示例部分新增 "自定义内容" 的代码引用。
package.json 新增依赖项 styled-components 和开发依赖项 @types/styled-components

Possibly related issues

Possibly related PRs

Suggested reviewers

  • afc163
  • YumoImer

🐰 在兔子洞里,内容自定义,
语言双语,功能齐全!
录音波动,欢声笑语,
发送消息,乐无穷!
快来体验,兔子说,
自定义内容,真不错! 🎉


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ac2dcf5 and 2caba89.

📒 Files selected for processing (1)
  • package.json (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 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. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @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.

Copy link

Prepare preview

Copy link
Contributor

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

🧹 Outside diff range and nitpick comments (4)
components/sender/demo/CustomContent.tsx (3)

6-12: 建议完善接口属性的类型定义

CustomContentProps 接口缺少必要的属性注释,建议添加 TypeScript 文档注释来说明每个属性的用途。

建议按照以下方式添加注释:

 interface CustomContentProps {
+  /** 内部值 */
   innerValue?: string;
+  /** 值变更回调 */
   onValueChange?: (newValue: string) => void;
+  /** 提交回调 */
   onSubmit?: () => void;
+  /** 加载状态 */
   loading?: boolean;
+  /** 禁用状态 */
   disabled?: boolean;
 }

33-40: 建议优化动画性能

当前实现中的动画可能会导致性能问题:

  1. 使用 transform 触发合成层优化
  2. 考虑添加 will-change 属性

建议修改样式实现:

 const WaveBar = styled.div<{ delay: number }>`
   background-color: white;
   width: 6px;
   height: 24px;
   border-radius: 4px;
+  will-change: transform;
   animation: ${waveAnimation} 1s ease-in-out infinite;
   animation-delay: ${({ delay }) => delay}s;
 `;

145-149: 建议添加组件测试

当前实现缺少单元测试,建议添加测试用例覆盖以下场景:

  1. 录音状态切换
  2. 回调函数调用
  3. 错误处理
  4. 键盘操作
  5. 加载和禁用状态

需要我帮您生成测试用例代码吗?

components/sender/index.tsx (1)

266-268: 建议:优化默认组件实现

空的 div 作为默认组件实现可能不够优雅,建议考虑以下改进:

-const CustomContent = getComponent(components, ['content'], () => <div />);
+const CustomContent = getComponent(components, ['content'], null);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f14f817 and ac2dcf5.

📒 Files selected for processing (6)
  • components/sender/demo/CustomContent.md (1 hunks)
  • components/sender/demo/CustomContent.tsx (1 hunks)
  • components/sender/index.en-US.md (1 hunks)
  • components/sender/index.tsx (3 hunks)
  • components/sender/index.zh-CN.md (1 hunks)
  • package.json (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • components/sender/demo/CustomContent.md
🔇 Additional comments (6)
components/sender/index.zh-CN.md (1)

25-25: 文档更新正确且完整!

新增的自定义内容示例与组件功能相符,文档结构清晰。

components/sender/index.en-US.md (1)

24-24: 中英文文档保持一致!

英文文档的更新与中文文档同步,保持了文档的一致性。

package.json (2)

154-154: 类型定义添加正确

@types/styled-components 作为开发依赖添加是正确的做法。


96-97: 建议:验证 styled-components 的兼容性和性能影响

新增的 styled-components 依赖可能会对包大小和运行时性能产生影响。

✅ Verification successful

Let me analyze the usage and configuration before providing the final response.


styled-components 的使用和大小限制已得到验证

根据分析结果:

  • 项目已设置了包大小限制(350 KiB),这个限制是合理的
  • styled-components 仅在少数文件中使用,主要用于自定义内容渲染
  • 没有发现重复导入的问题

建议可以安全地继续使用 styled-components,因为:

  • 使用范围受控,不会造成全局性影响
  • 项目有明确的包大小限制保护
  • 文档中已包含相关使用说明
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 检查包大小影响
npm run size-limit

# 检查是否有重复的 styled-components 安装
rg -A 3 "styled-components" package-lock.json

Length of output: 201


Script:

#!/bin/bash
# Check if styled-components is used in the codebase
rg -l "styled-components"

# Check for potential duplicate styled-components imports
ast-grep --pattern 'import $_ from "styled-components"'

# Check package size related configurations
fd "size" --type f --extension json
cat package.json | grep -A 5 -B 5 "size"

Length of output: 2922

components/sender/index.tsx (2)

24-25: 接口设计合理

新增的 content 自定义组件接口设计清晰,并且提供了良好的 TypeScript 类型支持。


301-309: 验证:确保事件处理的兼容性

需要验证自定义内容组件是否会影响现有的事件处理逻辑。

✅ Verification successful

事件处理逻辑已经过验证,无需担心兼容性问题

通过代码分析,我们可以确认:

  • InputTextArea 组件是从 components 属性中获取的,默认使用 Input.TextArea
  • 事件处理逻辑保持一致:
    • onChange 事件正确处理文本输入
    • onPressEnter 事件与 onInternalKeyPress 正确绑定
    • 所有事件处理函数都经过适当的类型检查

自定义内容组件不会影响现有的事件处理逻辑,因为它是作为可选的替代渲染内容提供的。

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 检查组件中的事件处理使用情况
ast-grep --pattern 'onChange={$_}'

Length of output: 36


Script:

#!/bin/bash
# 搜索事件处理相关的代码
rg "onChange|onPressEnter|onKeyPress" -A 3 -B 3

# 查找 InputTextArea 组件的使用
rg "InputTextArea" -A 5 -B 5

# 检查事件处理函数的定义
ast-grep --pattern 'function $_(e) { 
  $$$
}'

Length of output: 28376

Comment on lines +90 to +143
const Demo: React.FC = () => {
const { message } = App.useApp();
const [recording, setRecording] = useState(false);
const [value, setValue] = useState<string>('');

return (
<Sender
value={value}
components={{
content: ({ onValueChange, onSubmit }: CustomContentProps) => (
<CustomSpeechBox
recording={recording}
onClick={() => {
if (recording) {
message.success('录音结束');
onValueChange?.('');
onSubmit?.();
} else {
message.info('开始录音');
onValueChange?.('录音内容...');
}
setRecording(!recording);
}}
>
<SpeechContent>
{recording ? (
<div style={{ textAlign: 'center' }}>
<AudioWave>
<WaveBar delay={0} />
<WaveBar delay={0.2} />
<WaveBar delay={0.4} />
<WaveBar delay={0.6} />
<WaveBar delay={0.8} />
</AudioWave>
<RecordingText>正在听...</RecordingText>
</div>
) : (
<>
<Dots>· · · ·</Dots>
<SpeechContentText>可以开始说话了</SpeechContentText>
</>
)}
</SpeechContent>
</CustomSpeechBox>
),
}}
actions={() => null}
onChange={setValue}
onSubmit={() => {
message.success('语音消息已发送!');
}}
/>
);
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

需要增强错误处理和可访问性

主要问题:

  1. 缺少错误处理机制
  2. 缺少键盘操作支持
  3. 缺少适当的 ARIA 属性
  4. 缺少加载和禁用状态的处理

建议进行以下改进:

 const Demo: React.FC = () => {
   const { message } = App.useApp();
   const [recording, setRecording] = useState(false);
   const [value, setValue] = useState<string>('');
+  const [error, setError] = useState<string | null>(null);

   return (
     <Sender
       value={value}
       components={{
         content: ({ onValueChange, onSubmit, loading, disabled }: CustomContentProps) => (
           <CustomSpeechBox
             recording={recording}
+            role="button"
+            tabIndex={0}
+            aria-label={recording ? "正在录音" : "点击开始录音"}
+            aria-disabled={disabled}
+            disabled={disabled}
+            onKeyDown={(e) => {
+              if (e.key === 'Enter' || e.key === ' ') {
+                e.preventDefault();
+                if (!disabled && !loading) {
+                  // 触发点击事件
+                  e.currentTarget.click();
+                }
+              }
+            }}
             onClick={() => {
+              if (disabled || loading) return;
+
               if (recording) {
                 message.success('录音结束');
                 onValueChange?.('');
                 onSubmit?.();
               } else {
                 message.info('开始录音');
                 onValueChange?.('录音内容...');
               }
               setRecording(!recording);
             }}
           >
             <SpeechContent>
               {loading ? (
+                <LoadingIndicator />
+              ) : disabled ? (
+                <DisabledState />
+              ) : recording ? (
                 // ... 现有的录音状态UI
               ) : (
                 // ... 现有的非录音状态UI
               )}
             </SpeechContent>
           </CustomSpeechBox>
         ),
       }}
       actions={() => null}
       onChange={setValue}
       onSubmit={() => {
         message.success('语音消息已发送!');
       }}
     />
   );
 };

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +297 to +310
{/* 自定义 content 渲染 */}
{CustomContent ? (
<CustomContent />
) : (
<InputTextArea
{...inputProps}
disabled={disabled}
value={innerValue}
onChange={(e) => triggerValueChange((e.target as HTMLTextAreaElement).value)}
onPressEnter={onInternalKeyPress}
variant="borderless"
readOnly={readOnly}
/>
)}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

建议:改进条件渲染逻辑

当前的条件渲染逻辑可以更加简洁,同时建议添加错误边界处理。

-        {/* 自定义 content 渲染 */}
-        {CustomContent ? (
-          <CustomContent />
-        ) : (
-          <InputTextArea
-            {...inputProps}
-            disabled={disabled}
-            value={innerValue}
-            onChange={(e) => triggerValueChange((e.target as HTMLTextAreaElement).value)}
-            onPressEnter={onInternalKeyPress}
-            variant="borderless"
-            readOnly={readOnly}
-          />
-        )}
+        {/* 自定义 content 渲染 */}
+        <React.Suspense fallback={null}>
+          {CustomContent ? (
+            <ErrorBoundary>
+              <CustomContent />
+            </ErrorBoundary>
+          ) : (
+            <InputTextArea
+              {...inputProps}
+              disabled={disabled}
+              value={innerValue}
+              onChange={(e) => triggerValueChange((e.target as HTMLTextAreaElement).value)}
+              onPressEnter={onInternalKeyPress}
+              variant="borderless"
+              readOnly={readOnly}
+            />
+          )}
+        </React.Suspense>

Committable suggestion skipped: line range outside the PR's diff.

Copy link

socket-security bot commented Dec 13, 2024

New and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/@types/[email protected] None 0 23.2 kB types
npm/[email protected] environment 0 1.76 MB probablyup

🚮 Removed packages: npm/[email protected], npm/[email protected]

View full report↗︎

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.

1 participant