@lobehub/chat 1.111.5 → 1.111.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,78 @@
1
+ name: Claude Code Review
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize]
6
+ # Optional: Only run on specific file changes
7
+ # paths:
8
+ # - "src/**/*.ts"
9
+ # - "src/**/*.tsx"
10
+ # - "src/**/*.js"
11
+ # - "src/**/*.jsx"
12
+
13
+ jobs:
14
+ claude-review:
15
+ # Optional: Filter by PR author
16
+ # if: |
17
+ # github.event.pull_request.user.login == 'external-contributor' ||
18
+ # github.event.pull_request.user.login == 'new-developer' ||
19
+ # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
20
+
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ contents: read
24
+ pull-requests: read
25
+ issues: read
26
+ id-token: write
27
+
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@v4
31
+ with:
32
+ fetch-depth: 1
33
+
34
+ - name: Run Claude Code Review
35
+ id: claude-review
36
+ uses: anthropics/claude-code-action@beta
37
+ with:
38
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
39
+
40
+ # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4)
41
+ # model: "claude-opus-4-20250514"
42
+
43
+ # Direct prompt for automated review (no @claude mention needed)
44
+ direct_prompt: |
45
+ Please review this pull request and provide feedback on:
46
+ - Code quality and best practices
47
+ - Potential bugs or issues
48
+ - Performance considerations
49
+ - Security concerns
50
+ - Test coverage
51
+
52
+ Be constructive and helpful in your feedback.
53
+
54
+ # Optional: Use sticky comments to make Claude reuse the same comment on subsequent pushes to the same PR
55
+ # use_sticky_comment: true
56
+
57
+ # Optional: Customize review based on file types
58
+ # direct_prompt: |
59
+ # Review this PR focusing on:
60
+ # - For TypeScript files: Type safety and proper interface usage
61
+ # - For API endpoints: Security, input validation, and error handling
62
+ # - For React components: Performance, accessibility, and best practices
63
+ # - For tests: Coverage, edge cases, and test quality
64
+
65
+ # Optional: Different prompts for different authors
66
+ # direct_prompt: |
67
+ # ${{ github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' &&
68
+ # 'Welcome! Please review this PR from a first-time contributor. Be encouraging and provide detailed explanations for any suggestions.' ||
69
+ # 'Please provide a thorough code review focusing on our coding standards and best practices.' }}
70
+
71
+ # Optional: Add specific tools for running tests or linting
72
+ # allowed_tools: "Bash(npm run test),Bash(npm run lint),Bash(npm run typecheck)"
73
+
74
+ # Optional: Skip review for certain conditions
75
+ # if: |
76
+ # !contains(github.event.pull_request.title, '[skip-review]') &&
77
+ # !contains(github.event.pull_request.title, '[WIP]')
78
+
@@ -0,0 +1,64 @@
1
+ name: Claude Code
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+ pull_request_review_comment:
7
+ types: [created]
8
+ issues:
9
+ types: [opened, assigned]
10
+ pull_request_review:
11
+ types: [submitted]
12
+
13
+ jobs:
14
+ claude:
15
+ if: |
16
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
17
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
18
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
19
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: read
23
+ pull-requests: read
24
+ issues: read
25
+ id-token: write
26
+ actions: read # Required for Claude to read CI results on PRs
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@v4
30
+ with:
31
+ fetch-depth: 1
32
+
33
+ - name: Run Claude Code
34
+ id: claude
35
+ uses: anthropics/claude-code-action@beta
36
+ with:
37
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38
+
39
+ # This is an optional setting that allows Claude to read CI results on PRs
40
+ additional_permissions: |
41
+ actions: read
42
+
43
+ # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4)
44
+ # model: "claude-opus-4-20250514"
45
+
46
+ # Optional: Customize the trigger phrase (default: @claude)
47
+ # trigger_phrase: "/claude"
48
+
49
+ # Optional: Trigger when specific user is assigned to an issue
50
+ # assignee_trigger: "claude-bot"
51
+
52
+ # Optional: Allow Claude to run specific commands
53
+ # allowed_tools: "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)"
54
+
55
+ # Optional: Add custom instructions for Claude to customize its behavior for your project
56
+ # custom_instructions: |
57
+ # Follow our coding standards
58
+ # Ensure all new code has tests
59
+ # Use TypeScript for new files
60
+
61
+ # Optional: Custom environment variables for Claude
62
+ # claude_env: |
63
+ # NODE_ENV: test
64
+
@@ -35,7 +35,7 @@ jobs:
35
35
  - name: Setup pnpm
36
36
  uses: pnpm/action-setup@v2
37
37
  with:
38
- version: 9
38
+ version: 10
39
39
 
40
40
  - name: Install deps
41
41
  run: pnpm install
@@ -107,7 +107,7 @@ jobs:
107
107
  - name: Setup pnpm
108
108
  uses: pnpm/action-setup@v2
109
109
  with:
110
- version: 9
110
+ version: 10
111
111
 
112
112
  # node-linker=hoisted 模式将可以确保 asar 压缩可用
113
113
  - name: Install deps
@@ -31,7 +31,7 @@ jobs:
31
31
  - name: Setup pnpm
32
32
  uses: pnpm/action-setup@v2
33
33
  with:
34
- version: 9
34
+ version: 10
35
35
 
36
36
  - name: Install deps
37
37
  run: pnpm install
@@ -94,7 +94,7 @@ jobs:
94
94
  - name: Setup pnpm
95
95
  uses: pnpm/action-setup@v2
96
96
  with:
97
- version: 9
97
+ version: 10
98
98
 
99
99
  # node-linker=hoisted 模式将可以确保 asar 压缩可用
100
100
  - name: Install deps
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.111.6](https://github.com/lobehub/lobe-chat/compare/v1.111.5...v1.111.6)
6
+
7
+ <sup>Released on **2025-08-11**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Solve the cache problem caused by the same dom id when sharing pictures.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Solve the cache problem caused by the same dom id when sharing pictures, closes [#8704](https://github.com/lobehub/lobe-chat/issues/8704) ([68aad95](https://github.com/lobehub/lobe-chat/commit/68aad95))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ### [Version 1.111.5](https://github.com/lobehub/lobe-chat/compare/v1.111.4...v1.111.5)
6
31
 
7
32
  <sup>Released on **2025-08-10**</sup>
package/README.md CHANGED
@@ -385,11 +385,11 @@ In addition, these plugins are not limited to news aggregation, but can also ext
385
385
  | Recent Submits | Description |
386
386
  | ---------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
387
387
  | [PortfolioMeta](https://lobechat.com/discover/plugin/StockData)<br/><sup>By **portfoliometa** on **2025-07-21**</sup> | Analyze stocks and get comprehensive real-time investment data and analytics.<br/>`stock` |
388
- | [Speak](https://lobechat.com/discover/plugin/speak)<br/><sup>By **speak** on **2025-07-18**</sup> | Learn how to say anything in another language with Speak, your AI-powered language tutor.<br/>`education` `language` |
389
388
  | [Web](https://lobechat.com/discover/plugin/web)<br/><sup>By **Proghit** on **2025-01-24**</sup> | Smart web search that reads and analyzes pages to deliver comprehensive answers from Google results.<br/>`web` `search` |
390
389
  | [Bing_websearch](https://lobechat.com/discover/plugin/Bingsearch-identifier)<br/><sup>By **FineHow** on **2024-12-22**</sup> | Search for information from the internet base BingApi<br/>`bingsearch` |
390
+ | [Google CSE](https://lobechat.com/discover/plugin/google-cse)<br/><sup>By **vsnthdev** on **2024-12-02**</sup> | Searches Google through their official CSE API.<br/>`web` `search` |
391
391
 
392
- > 📊 Total plugins: [<kbd>**43**</kbd>](https://lobechat.com/discover/plugins)
392
+ > 📊 Total plugins: [<kbd>**42**</kbd>](https://lobechat.com/discover/plugins)
393
393
 
394
394
  <!-- PLUGIN LIST -->
395
395
 
package/README.zh-CN.md CHANGED
@@ -378,11 +378,11 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
378
378
  | 最近新增 | 描述 |
379
379
  | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
380
380
  | [PortfolioMeta](https://lobechat.com/discover/plugin/StockData)<br/><sup>By **portfoliometa** on **2025-07-21**</sup> | 分析股票并获取全面的实时投资数据和分析。<br/>`股票` |
381
- | [Speak](https://lobechat.com/discover/plugin/speak)<br/><sup>By **speak** on **2025-07-18**</sup> | 使用 Speak,您的 AI 语言导师,学习如何用另一种语言说任何事情。<br/>`教育` `语言` |
382
381
  | [网页](https://lobechat.com/discover/plugin/web)<br/><sup>By **Proghit** on **2025-01-24**</sup> | 智能网页搜索,读取和分析页面,以提供来自 Google 结果的全面答案。<br/>`网页` `搜索` |
383
382
  | [必应网页搜索](https://lobechat.com/discover/plugin/Bingsearch-identifier)<br/><sup>By **FineHow** on **2024-12-22**</sup> | 通过 BingApi 搜索互联网上的信息<br/>`bingsearch` |
383
+ | [谷歌自定义搜索引擎](https://lobechat.com/discover/plugin/google-cse)<br/><sup>By **vsnthdev** on **2024-12-02**</sup> | 通过他们的官方自定义搜索引擎 API 搜索谷歌。<br/>`网络` `搜索` |
384
384
 
385
- > 📊 Total plugins: [<kbd>**43**</kbd>](https://lobechat.com/discover/plugins)
385
+ > 📊 Total plugins: [<kbd>**42**</kbd>](https://lobechat.com/discover/plugins)
386
386
 
387
387
  <!-- PLUGIN LIST -->
388
388
 
package/changelog/v1.json CHANGED
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "fixes": [
5
+ "Solve the cache problem caused by the same dom id when sharing pictures."
6
+ ]
7
+ },
8
+ "date": "2025-08-11",
9
+ "version": "1.111.6"
10
+ },
2
11
  {
3
12
  "children": {
4
13
  "improvements": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.111.5",
3
+ "version": "1.111.6",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -363,7 +363,7 @@
363
363
  "vitest": "^3.2.4",
364
364
  "vitest-canvas-mock": "^0.3.3"
365
365
  },
366
- "packageManager": "pnpm@10.10.0",
366
+ "packageManager": "pnpm@10.14.0",
367
367
  "publishConfig": {
368
368
  "access": "public",
369
369
  "registry": "https://registry.npmjs.org"
@@ -21,63 +21,70 @@ import { FieldType } from './type';
21
21
 
22
22
  interface PreviewProps extends FieldType {
23
23
  message: ChatMessage;
24
+ previewId?: string;
24
25
  title?: string;
25
26
  }
26
27
 
27
- const Preview = memo<PreviewProps>(({ title, withBackground, withFooter, message }) => {
28
- const [model, plugins] = useAgentStore((s) => [
29
- agentSelectors.currentAgentModel(s),
30
- agentSelectors.currentAgentPlugins(s),
31
- ]);
28
+ const Preview = memo<PreviewProps>(
29
+ ({ title, withBackground, withFooter, message, previewId = 'preview' }) => {
30
+ const [model, plugins] = useAgentStore((s) => [
31
+ agentSelectors.currentAgentModel(s),
32
+ agentSelectors.currentAgentPlugins(s),
33
+ ]);
32
34
 
33
- const [isInbox, description, avatar, backgroundColor] = useSessionStore((s) => [
34
- sessionSelectors.isInboxSession(s),
35
- sessionMetaSelectors.currentAgentDescription(s),
36
- sessionMetaSelectors.currentAgentAvatar(s),
37
- sessionMetaSelectors.currentAgentBackgroundColor(s),
38
- ]);
35
+ const [isInbox, description, avatar, backgroundColor] = useSessionStore((s) => [
36
+ sessionSelectors.isInboxSession(s),
37
+ sessionMetaSelectors.currentAgentDescription(s),
38
+ sessionMetaSelectors.currentAgentAvatar(s),
39
+ sessionMetaSelectors.currentAgentBackgroundColor(s),
40
+ ]);
39
41
 
40
- const { t } = useTranslation('chat');
41
- const { styles } = useStyles(withBackground);
42
- const { styles: containerStyles } = useContainerStyles();
42
+ const { t } = useTranslation('chat');
43
+ const { styles } = useStyles(withBackground);
44
+ const { styles: containerStyles } = useContainerStyles();
43
45
 
44
- const displayTitle = isInbox ? t('inbox.title') : title;
45
- const displayDesc = isInbox ? t('inbox.desc') : description;
46
+ const displayTitle = isInbox ? t('inbox.title') : title;
47
+ const displayDesc = isInbox ? t('inbox.desc') : description;
46
48
 
47
- return (
48
- <div className={containerStyles.preview}>
49
- <div className={withBackground ? styles.background : undefined} id={'preview'}>
50
- <Flexbox className={styles.container} gap={16}>
51
- <div className={styles.header}>
52
- <Flexbox align={'flex-start'} gap={12} horizontal>
53
- <Avatar avatar={avatar} background={backgroundColor} size={40} title={title} />
54
- <ChatHeaderTitle
55
- desc={displayDesc}
56
- tag={
57
- <Flexbox gap={4} horizontal>
58
- <ModelTag model={model} />
59
- {plugins?.length > 0 && <PluginTag plugins={plugins} />}
60
- </Flexbox>
61
- }
62
- title={displayTitle}
63
- />
49
+ return (
50
+ <div className={containerStyles.preview}>
51
+ <div className={withBackground ? styles.background : undefined} id={previewId}>
52
+ <Flexbox className={styles.container} gap={16}>
53
+ <div className={styles.header}>
54
+ <Flexbox align={'flex-start'} gap={12} horizontal>
55
+ <Avatar avatar={avatar} background={backgroundColor} size={40} title={title} />
56
+ <ChatHeaderTitle
57
+ desc={displayDesc}
58
+ tag={
59
+ <Flexbox gap={4} horizontal>
60
+ <ModelTag model={model} />
61
+ {plugins?.length > 0 && <PluginTag plugins={plugins} />}
62
+ </Flexbox>
63
+ }
64
+ title={displayTitle}
65
+ />
66
+ </Flexbox>
67
+ </div>
68
+ <Flexbox
69
+ height={'100%'}
70
+ style={{ paddingTop: 24, position: 'relative' }}
71
+ width={'100%'}
72
+ >
73
+ <ChatItem id={message.id} index={0} />
64
74
  </Flexbox>
65
- </div>
66
- <Flexbox height={'100%'} style={{ paddingTop: 24, position: 'relative' }} width={'100%'}>
67
- <ChatItem id={message.id} index={0} />
75
+ {withFooter ? (
76
+ <Flexbox align={'center'} className={styles.footer} gap={4}>
77
+ <ProductLogo type={'combine'} />
78
+ <div className={styles.url}>{pkg.homepage}</div>
79
+ </Flexbox>
80
+ ) : (
81
+ <div />
82
+ )}
68
83
  </Flexbox>
69
- {withFooter ? (
70
- <Flexbox align={'center'} className={styles.footer} gap={4}>
71
- <ProductLogo type={'combine'} />
72
- <div className={styles.url}>{pkg.homepage}</div>
73
- </Flexbox>
74
- ) : (
75
- <div />
76
- )}
77
- </Flexbox>
84
+ </div>
78
85
  </div>
79
- </div>
80
- );
81
- });
86
+ );
87
+ },
88
+ );
82
89
 
83
90
  export default Preview;
@@ -23,84 +23,91 @@ const DEFAULT_FIELD_VALUE: FieldType = {
23
23
  withFooter: true,
24
24
  };
25
25
 
26
- const ShareImage = memo<{ message: ChatMessage; mobile?: boolean }>(({ message }) => {
27
- const currentAgentTitle = useSessionStore(sessionMetaSelectors.currentAgentTitle);
28
- const [fieldValue, setFieldValue] = useState<FieldType>(DEFAULT_FIELD_VALUE);
29
- const { t } = useTranslation(['chat', 'common']);
30
- const { styles } = useStyles();
31
- const { loading, onDownload, title } = useScreenshot({
32
- imageType: fieldValue.imageType,
33
- title: currentAgentTitle,
34
- });
35
- const { loading: copyLoading, onCopy } = useImgToClipboard();
36
- const settings: FormItemProps[] = [
37
- {
38
- children: <Switch />,
39
- label: t('shareModal.withBackground'),
40
- layout: 'horizontal',
41
- minWidth: undefined,
42
- name: 'withBackground',
43
- valuePropName: 'checked',
44
- },
45
- {
46
- children: <Switch />,
47
- label: t('shareModal.withFooter'),
48
- layout: 'horizontal',
49
- minWidth: undefined,
50
- name: 'withFooter',
51
- valuePropName: 'checked',
52
- },
53
- {
54
- children: <Segmented options={imageTypeOptions} />,
55
- label: t('shareModal.imageType'),
56
- layout: 'horizontal',
57
- minWidth: undefined,
58
- name: 'imageType',
59
- },
60
- ];
26
+ const ShareImage = memo<{ message: ChatMessage; mobile?: boolean; uniqueId?: string }>(
27
+ ({ message, uniqueId }) => {
28
+ const currentAgentTitle = useSessionStore(sessionMetaSelectors.currentAgentTitle);
29
+ const [fieldValue, setFieldValue] = useState<FieldType>(DEFAULT_FIELD_VALUE);
30
+ const { t } = useTranslation(['chat', 'common']);
31
+ const { styles } = useStyles();
61
32
 
62
- const isMobile = useIsMobile();
33
+ // 生成唯一的预览ID,避免DOM冲突
34
+ const previewId = uniqueId ? `preview-${uniqueId}` : 'preview';
63
35
 
64
- const button = (
65
- <>
66
- <Button
67
- block
68
- icon={CopyIcon}
69
- loading={copyLoading}
70
- onClick={() => onCopy()}
71
- size={isMobile ? undefined : 'large'}
72
- type={'primary'}
73
- >
74
- {t('copy', { ns: 'common' })}
75
- </Button>
76
- <Button block loading={loading} onClick={onDownload} size={isMobile ? undefined : 'large'}>
77
- {t('shareModal.download')}
78
- </Button>
79
- </>
80
- );
36
+ const { loading, onDownload, title } = useScreenshot({
37
+ id: `#${previewId}`,
38
+ imageType: fieldValue.imageType,
39
+ title: currentAgentTitle,
40
+ });
41
+ const { loading: copyLoading, onCopy } = useImgToClipboard({ id: `#${previewId}` });
42
+ const settings: FormItemProps[] = [
43
+ {
44
+ children: <Switch />,
45
+ label: t('shareModal.withBackground'),
46
+ layout: 'horizontal',
47
+ minWidth: undefined,
48
+ name: 'withBackground',
49
+ valuePropName: 'checked',
50
+ },
51
+ {
52
+ children: <Switch />,
53
+ label: t('shareModal.withFooter'),
54
+ layout: 'horizontal',
55
+ minWidth: undefined,
56
+ name: 'withFooter',
57
+ valuePropName: 'checked',
58
+ },
59
+ {
60
+ children: <Segmented options={imageTypeOptions} />,
61
+ label: t('shareModal.imageType'),
62
+ layout: 'horizontal',
63
+ minWidth: undefined,
64
+ name: 'imageType',
65
+ },
66
+ ];
81
67
 
82
- return (
83
- <>
84
- <Flexbox className={styles.body} gap={16} horizontal={!isMobile}>
85
- <Preview title={title} {...fieldValue} message={message} />
86
- <Flexbox className={styles.sidebar} gap={12}>
87
- <Form
88
- initialValues={DEFAULT_FIELD_VALUE}
89
- items={settings}
90
- itemsType={'flat'}
91
- onValuesChange={(_, v) => setFieldValue(v)}
92
- {...FORM_STYLE}
93
- />
94
- {!isMobile && button}
95
- </Flexbox>
96
- </Flexbox>
97
- {isMobile && (
98
- <Flexbox className={styles.footer} gap={8} horizontal>
99
- {button}
68
+ const isMobile = useIsMobile();
69
+
70
+ const button = (
71
+ <>
72
+ <Button
73
+ block
74
+ icon={CopyIcon}
75
+ loading={copyLoading}
76
+ onClick={() => onCopy()}
77
+ size={isMobile ? undefined : 'large'}
78
+ type={'primary'}
79
+ >
80
+ {t('copy', { ns: 'common' })}
81
+ </Button>
82
+ <Button block loading={loading} onClick={onDownload} size={isMobile ? undefined : 'large'}>
83
+ {t('shareModal.download')}
84
+ </Button>
85
+ </>
86
+ );
87
+
88
+ return (
89
+ <>
90
+ <Flexbox className={styles.body} gap={16} horizontal={!isMobile}>
91
+ <Preview title={title} {...fieldValue} message={message} previewId={previewId} />
92
+ <Flexbox className={styles.sidebar} gap={12}>
93
+ <Form
94
+ initialValues={DEFAULT_FIELD_VALUE}
95
+ items={settings}
96
+ itemsType={'flat'}
97
+ onValuesChange={(_, v) => setFieldValue(v)}
98
+ {...FORM_STYLE}
99
+ />
100
+ {!isMobile && button}
101
+ </Flexbox>
100
102
  </Flexbox>
101
- )}
102
- </>
103
- );
104
- });
103
+ {isMobile && (
104
+ <Flexbox className={styles.footer} gap={8} horizontal>
105
+ {button}
106
+ </Flexbox>
107
+ )}
108
+ </>
109
+ );
110
+ },
111
+ );
105
112
 
106
113
  export default ShareImage;
@@ -1,5 +1,5 @@
1
1
  import { Modal, Segmented, type SegmentedProps } from '@lobehub/ui';
2
- import { memo, useMemo, useState } from 'react';
2
+ import { memo, useId, useMemo, useState } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import { Flexbox } from 'react-layout-kit';
5
5
 
@@ -23,6 +23,7 @@ interface ShareModalProps {
23
23
  const ShareModal = memo<ShareModalProps>(({ onCancel, open, message }) => {
24
24
  const [tab, setTab] = useState<Tab>(Tab.Screenshot);
25
25
  const { t } = useTranslation('chat');
26
+ const uniqueId = useId();
26
27
 
27
28
  const options: SegmentedProps['options'] = useMemo(
28
29
  () => [
@@ -58,7 +59,9 @@ const ShareModal = memo<ShareModalProps>(({ onCancel, open, message }) => {
58
59
  value={tab}
59
60
  variant={'filled'}
60
61
  />
61
- {tab === Tab.Screenshot && <ShareImage message={message} mobile={isMobile} />}
62
+ {tab === Tab.Screenshot && (
63
+ <ShareImage message={message} mobile={isMobile} uniqueId={uniqueId} />
64
+ )}
62
65
  {tab === Tab.Text && <ShareText item={message} />}
63
66
  </Flexbox>
64
67
  </Modal>