Skip to content

feat: watermark 水印#1464

Open
lqr131115 wants to merge 2 commits intoant-design:masterfrom
lqr131115:feat/watermark
Open

feat: watermark 水印#1464
lqr131115 wants to merge 2 commits intoant-design:masterfrom
lqr131115:feat/watermark

Conversation

@lqr131115
Copy link
Contributor

@lqr131115 lqr131115 commented Jan 28, 2026

First of all, thank you for your contribution! :-)

Please makes sure that these checkboxes are checked before submitting your PR, thank you!

  • Make sure that you follow antd's code convention.
  • Run npm run lint and fix those errors before submitting in order to keep consistent code style.
  • Rebase before creating a PR to keep commit history clear.
  • Add some descriptions and refer relative issues for you PR.

Extra checklist:

if isBugFix :

  • Make sure that you add at least one unit test for the bug which you had fixed.

elif isNewFeature :

  • Update API docs for the component.
  • Update/Add demo to demonstrate new feature.
  • Update TypeScript definition for the component.
  • Add unit tests for the feature.

Summary by CodeRabbit

发布说明

  • 新功能

    • 新增水印组件,支持文本与图片两种内容形式,支持前景/背景显示
    • 可配置宽高、间距、旋转角度与样式,支持多行文本
  • 文档

    • 提供完整中英文文档与 API 说明
  • 演示

    • 新增交互式示例,可切换文本/图片与前后景
  • 测试

    • 添加了水印组件的示例测试调用

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 28, 2026

📝 Walkthrough

Walkthrough

新增 Watermark 组件及其类型、样式、文档、演示与测试,组件实现支持文本或图片水印平铺、布局测量和前景/背景渲染,并将该组件导出到入口文件与类型导出中。

Changes

Cohort / File(s) Summary
核心实现
components/watermark/index.tsx, components/watermark/style/index.tsx, components/watermark/PropsType.tsx
新增 Watermark 组件实现、样式定义和 WatermarkProps 类型;实现平铺逻辑、布局测量、旋转、间距、前景/背景控制等。
入口与类型导出
components/index.tsx, components/types.ts
在库主导出与类型导出中新增 WatermarkWatermarkProps 的公开导出。
演示与测试
components/watermark/demo/basic.tsx, components/watermark/demo/basic.md, components/watermark/__tests__/demo.test.js, rn-kitchen-sink/demoList.js
新增交互演示组件与示例文档、演示注册项及一个 demo 测试调用。
文档
components/watermark/index.en-US.md, components/watermark/index.zh-CN.md
新增英文与中文文档,包含组件描述与完整 API 参数表。

Sequence Diagram(s)

(无)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

庆祝诗

我是小兔画水印,🐰
文字图片轻轻洒,
方寸间排满花,
前景后景随心挂,
库中新颜笑哈哈。

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 拉取请求标题准确地总结了主要变更:添加新的 Watermark(水印)组件功能。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @lqr131115, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request delivers a new Watermark component, enhancing the library's capabilities by allowing the overlay of text or image watermarks onto UI elements. This feature is designed to help protect content and identify copyright, offering a flexible and configurable solution for developers to integrate into their applications.

Highlights

  • New Watermark Component: Introduced a new Watermark component, allowing users to add customizable watermarks to their React Native applications for copyright identification or information protection.
  • Flexible Content Options: The Watermark component supports both text-based watermarks (single or multi-line) and image-based watermarks, providing versatility for different use cases.
  • Customizable Appearance and Positioning: Developers can configure various properties such as content style, image style, width, height, horizontal and vertical gaps, rotation angle, and whether the watermark appears in the foreground or background layer.
  • Comprehensive Integration and Documentation: The new component is fully integrated into the component library, includes detailed API documentation in both English and Chinese, and features a basic demo to showcase its capabilities.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
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 new "Watermark" component. A potential Denial of Service (DoS) vulnerability was identified in the rendering logic where an unbounded number of watermark items could be created if small dimensions are provided. This is mitigated by implementing the maxCount prop and enforcing minimum dimension values in the calculation. Additionally, there's a correctness bug in how the number of watermark items is calculated, which could result in incomplete coverage. Improvements are also suggested for better theme integration by removing hardcoded styles, addressing inconsistencies in the demo code and documentation, and enhancing unit tests to cover actual watermark rendering.

Comment on lines +1 to +3
import rnDemoTest from '../../../tests/shared/demoTest'

rnDemoTest('watermark')
Copy link
Contributor

Choose a reason for hiding this comment

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

high

The current test setup using react-test-renderer does not test the rendering of the watermarks themselves. The Watermark component relies on the onLayout event to determine its size and render the watermark elements, but react-test-renderer does not trigger onLayout. As a result, the generated snapshot (demo.test.js.snap) only contains the children of the Watermark component, and the watermark layer is missing.

To properly test this component, you should consider using a testing library that supports firing layout events, such as @testing-library/react-native. This would allow you to simulate a layout event and assert that the watermarks are rendered correctly.

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: 4

🤖 Fix all issues with AI agents
In `@components/watermark/demo/basic.md`:
- Around line 10-17: 在导入行中移除未使用的 React hook 引入:删除 useState 从 import React, {
useState } ... 中,因为组件是类组件 WatermarkExample 并未使用该 hook;保持其他导入如
Dimensions、StyleSheet、View、Button、Watermark、WhiteSpace 不变以避免破坏示例。

In `@components/watermark/index.en-US.md`:
- Around line 17-30: The docs table is missing the styles prop from
WatermarkProps; add a new row describing "styles" as the override entry for
per-part styling (type `Partial<WatermarkStyle>`), with a short description like
"Custom style overrides for watermark parts" and no default; reference the
WatermarkProps declaration and WatermarkStyle type so users can locate the shape
to override when editing the component docs.

In `@components/watermark/index.tsx`:
- Around line 38-42: The current computation of _width, _height and count can
produce Infinity/NaN if width or height are zero/negative; update the watermark
sizing logic (variables _width, _height and count) to guard against
zero/negative values by clamping _width and _height to a safe minimum (e.g.,
Math.max(1, width + gapX * 2) / Math.max(1, height + gapY * 2)) or by returning
early with count = 0 when width or height are invalid; ensure all uses of count
and layout.width/layout.height handle the guarded values to avoid
division-by-zero.

In `@components/watermark/index.zh-CN.md`:
- Around line 18-31: The API table is missing the styles prop from
WatermarkProps; add a new row describing "styles" with type
"Partial<WatermarkStyle>" and a short description like
"自定义水印各元素样式(可选),会合并到默认样式中" and indicate default as "-" or "undefined"; reference
the WatermarkProps and WatermarkStyle symbols so readers can find the
interface/type and ensure the docs state it's optional and merged with default
styles.
🧹 Nitpick comments (5)
components/watermark/PropsType.tsx (1)

5-18: 建议将 style 改为 StyleProp<ViewStyle> 以匹配 RN 习惯
当前 ViewStyle 不支持样式数组或注册样式对象,使用 StyleProp<ViewStyle> 更符合 RN 组件 API。

♻️ 建议修改
 export interface WatermarkProps {
   content?: string | string[]
   contentStyle?: StyleProp<TextStyle>
   image?: string | React.ReactNode
   imageStyle?: StyleProp<ImageStyle>
   width?: number
   height?: number
   gapX?: number
   gapY?: number
   rotate?: number
   foreground?: boolean
   children?: React.ReactNode
-  style?: ViewStyle
+  style?: StyleProp<ViewStyle>
   styles?: Partial<WatermarkStyle>
 }
rn-kitchen-sink/demoList.js (1)

268-273: 考虑使用独特的图标。

Watermark 条目的图标与 Card 组件使用了相同的图标 (daARhPjKcxlSuuZ.png)。建议为 Watermark 提供一个独特的图标以便于区分。

components/watermark/demo/basic.tsx (2)

73-79: 建议使用函数式 setState 来避免潜在的状态竞争。

当基于前一个状态值更新状态时,使用函数式 setState 可以确保获取最新的状态值。

♻️ 建议修改
          <Button
            type="primary"
            onPress={() => {
-              this.setState({ foreground: !this.state.foreground })
+              this.setState((prevState) => ({ foreground: !prevState.foreground }))
            }}>
            {this.state.foreground ? '前景层' : '背景层'}
          </Button>

7-14: 考虑为 state 添加类型定义。

使用 any 类型会失去 TypeScript 的类型检查优势。建议为 state 定义明确的接口。

♻️ 建议修改
+interface WatermarkExampleState {
+  props: Record<string, any>
+  foreground: boolean
+}
+
-export default class WatermarkExample extends React.Component<any, any> {
+export default class WatermarkExample extends React.Component<any, WatermarkExampleState> {
   constructor(props: any) {
     super(props)
     this.state = {
       props: {},
       foreground: false,
     }
   }
components/watermark/index.tsx (1)

40-42: 建议使用 Math.floor 替代 parseInt(String(...), 10)

当前写法较为冗长,可以简化为更直观的数学运算。

♻️ 建议修改
   const count =
-    parseInt(String(layout.width / _width), 10) *
-    parseInt(String(layout.height / _height), 10)
+    Math.floor(layout.width / _width) * Math.floor(layout.height / _height)

@lqr131115
Copy link
Contributor Author

TODO: use canvas !!! 😢

2026-01-28.21.31.33.mov

@1uokun
Copy link
Collaborator

1uokun commented Jan 29, 2026

👍

@1uokun
Copy link
Collaborator

1uokun commented Feb 2, 2026

建议参考
https://github.com/ant-design/ant-design-mobile/blob/master/src/components/water-mark/water-mark.tsx
使用 canvas或者svg实现,同时优化Divider也改成同类实现 @lqr131115

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.

3 participants