@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.
- package/.github/workflows/claude-code-review.yml +78 -0
- package/.github/workflows/claude.yml +64 -0
- package/.github/workflows/desktop-pr-build.yml +2 -2
- package/.github/workflows/release-desktop-beta.yml +2 -2
- package/CHANGELOG.md +25 -0
- package/README.md +2 -2
- package/README.zh-CN.md +2 -2
- package/changelog/v1.json +9 -0
- package/package.json +2 -2
- package/src/features/Conversation/components/ChatItem/ShareMessageModal/ShareImage/Preview.tsx +55 -48
- package/src/features/Conversation/components/ChatItem/ShareMessageModal/ShareImage/index.tsx +82 -75
- package/src/features/Conversation/components/ChatItem/ShareMessageModal/index.tsx +5 -2
@@ -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:
|
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:
|
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:
|
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:
|
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
|
+
[](#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>**
|
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>**
|
385
|
+
> 📊 Total plugins: [<kbd>**42**</kbd>](https://lobechat.com/discover/plugins)
|
386
386
|
|
387
387
|
<!-- PLUGIN LIST -->
|
388
388
|
|
package/changelog/v1.json
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.111.
|
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.
|
366
|
+
"packageManager": "pnpm@10.14.0",
|
367
367
|
"publishConfig": {
|
368
368
|
"access": "public",
|
369
369
|
"registry": "https://registry.npmjs.org"
|
package/src/features/Conversation/components/ChatItem/ShareMessageModal/ShareImage/Preview.tsx
CHANGED
@@ -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>(
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
42
|
+
const { t } = useTranslation('chat');
|
43
|
+
const { styles } = useStyles(withBackground);
|
44
|
+
const { styles: containerStyles } = useContainerStyles();
|
43
45
|
|
44
|
-
|
45
|
-
|
46
|
+
const displayTitle = isInbox ? t('inbox.title') : title;
|
47
|
+
const displayDesc = isInbox ? t('inbox.desc') : description;
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
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
|
-
|
66
|
-
|
67
|
-
|
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
|
-
|
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
|
-
|
80
|
-
|
81
|
-
|
86
|
+
);
|
87
|
+
},
|
88
|
+
);
|
82
89
|
|
83
90
|
export default Preview;
|
package/src/features/Conversation/components/ChatItem/ShareMessageModal/ShareImage/index.tsx
CHANGED
@@ -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 }>(
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
33
|
+
// 生成唯一的预览ID,避免DOM冲突
|
34
|
+
const previewId = uniqueId ? `preview-${uniqueId}` : 'preview';
|
63
35
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
<
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
{
|
95
|
-
</
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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 &&
|
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>
|