@lobehub/chat 1.6.13 → 1.6.14

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/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.6.14](https://github.com/lobehub/lobe-chat/compare/v1.6.13...v1.6.14)
6
+
7
+ <sup>Released on **2024-07-26**</sup>
8
+
9
+ #### 💄 Styles
10
+
11
+ - **misc**: Improve input file upload.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Styles
19
+
20
+ - **misc**: Improve input file upload, closes [#3314](https://github.com/lobehub/lobe-chat/issues/3314) ([de85553](https://github.com/lobehub/lobe-chat/commit/de85553))
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.6.13](https://github.com/lobehub/lobe-chat/compare/v1.6.12...v1.6.13)
6
31
 
7
32
  <sup>Released on **2024-07-25**</sup>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.6.13",
3
+ "version": "1.6.14",
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",
@@ -7,20 +7,17 @@ import { memo, useEffect, useState } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
  import { Center, Flexbox } from 'react-layout-kit';
9
9
 
10
- import DragUpload from '@/components/DragUpload';
11
10
  import StopLoadingIcon from '@/components/StopLoading';
12
11
  import SaveTopic from '@/features/ChatInput/Topic';
13
12
  import { useSendMessage } from '@/features/ChatInput/useSend';
14
- import { useAgentStore } from '@/store/agent';
15
- import { agentSelectors } from '@/store/agent/slices/chat';
16
13
  import { useChatStore } from '@/store/chat';
17
14
  import { chatSelectors, topicSelectors } from '@/store/chat/selectors';
18
15
  import { filesSelectors, useFileStore } from '@/store/file';
19
16
  import { useUserStore } from '@/store/user';
20
- import { modelProviderSelectors, preferenceSelectors } from '@/store/user/selectors';
17
+ import { preferenceSelectors } from '@/store/user/selectors';
21
18
  import { isMacOS } from '@/utils/platform';
22
19
 
23
- import { LocalFiles } from './LocalFiles';
20
+ import LocalFiles from '../LocalFiles';
24
21
  import SendMore from './SendMore';
25
22
 
26
23
  const useStyles = createStyles(({ css, prefixCls, token }) => {
@@ -51,10 +48,11 @@ const useStyles = createStyles(({ css, prefixCls, token }) => {
51
48
  });
52
49
 
53
50
  interface FooterProps {
51
+ expand: boolean;
54
52
  setExpand?: (expand: boolean) => void;
55
53
  }
56
54
 
57
- const Footer = memo<FooterProps>(({ setExpand }) => {
55
+ const Footer = memo<FooterProps>(({ setExpand, expand }) => {
58
56
  const { t } = useTranslation('chat');
59
57
 
60
58
  const { theme, styles } = useStyles();
@@ -75,28 +73,7 @@ const Footer = memo<FooterProps>(({ setExpand }) => {
75
73
 
76
74
  const isImageUploading = useFileStore(filesSelectors.isImageUploading);
77
75
 
78
- const model = useAgentStore(agentSelectors.currentAgentModel);
79
-
80
- const enabledFiles = useUserStore(modelProviderSelectors.isModelEnabledFiles(model));
81
-
82
- const [useCmdEnterToSend, canUpload] = useUserStore((s) => [
83
- preferenceSelectors.useCmdEnterToSend(s),
84
- modelProviderSelectors.isModelEnabledUpload(model)(s),
85
- ]);
86
-
87
- const uploadFile = useFileStore((s) => s.uploadFile);
88
-
89
- const uploadImages = async (fileList: FileList | undefined) => {
90
- if (!fileList || fileList.length === 0) return;
91
-
92
- const pools = Array.from(fileList).map(async (file) => {
93
- // skip none-file items
94
- if (!file.type.startsWith('image') && !enabledFiles) return;
95
- await uploadFile(file);
96
- });
97
-
98
- await Promise.all(pools);
99
- };
76
+ const [useCmdEnterToSend] = useUserStore((s) => [preferenceSelectors.useCmdEnterToSend(s)]);
100
77
 
101
78
  const sendMessage = useSendMessage();
102
79
 
@@ -142,12 +119,7 @@ const Footer = memo<FooterProps>(({ setExpand }) => {
142
119
  padding={'0 24px'}
143
120
  >
144
121
  <Flexbox align={'center'} gap={8} horizontal style={{ overflow: 'hidden' }}>
145
- {canUpload && (
146
- <>
147
- <DragUpload enabledFiles={enabledFiles} onUploadFiles={uploadImages} />
148
- <LocalFiles />
149
- </>
150
- )}
122
+ {expand && <LocalFiles />}
151
123
  </Flexbox>
152
124
  <Flexbox align={'center'} flex={'none'} gap={8} horizontal>
153
125
  <Flexbox
@@ -0,0 +1,46 @@
1
+ import { memo } from 'react';
2
+
3
+ import DragUpload from '@/components/DragUpload';
4
+ import { EditableFileList } from '@/features/FileList';
5
+ import { useAgentStore } from '@/store/agent';
6
+ import { agentSelectors } from '@/store/agent/slices/chat';
7
+ import { useFileStore } from '@/store/file';
8
+ import { useUserStore } from '@/store/user';
9
+ import { modelProviderSelectors } from '@/store/user/selectors';
10
+
11
+ interface LocalFilesProps {
12
+ padding?: number | string;
13
+ }
14
+
15
+ const LocalFiles = memo<LocalFilesProps>(({ padding }) => {
16
+ const model = useAgentStore(agentSelectors.currentAgentModel);
17
+
18
+ const enabledFiles = useUserStore(modelProviderSelectors.isModelEnabledFiles(model));
19
+ const canUpload = useUserStore(modelProviderSelectors.isModelEnabledUpload(model));
20
+
21
+ const inputFilesList = useFileStore((s) => s.inputFilesList);
22
+ const uploadFile = useFileStore((s) => s.uploadFile);
23
+
24
+ const uploadImages = async (fileList: FileList | undefined) => {
25
+ if (!fileList || fileList.length === 0) return;
26
+
27
+ const pools = Array.from(fileList).map(async (file) => {
28
+ // skip none-file items
29
+ if (!file.type.startsWith('image') && !enabledFiles) return;
30
+ await uploadFile(file);
31
+ });
32
+
33
+ await Promise.all(pools);
34
+ };
35
+
36
+ return (
37
+ canUpload && (
38
+ <>
39
+ <DragUpload enabledFiles={enabledFiles} onUploadFiles={uploadImages} />
40
+ <EditableFileList items={inputFilesList} padding={padding ?? 0} />
41
+ </>
42
+ )
43
+ );
44
+ });
45
+
46
+ export default LocalFiles;
@@ -14,6 +14,7 @@ import { systemStatusSelectors } from '@/store/global/selectors';
14
14
 
15
15
  import Footer from './Footer';
16
16
  import Head from './Header';
17
+ import LocalFiles from './LocalFiles';
17
18
  import TextArea from './TextArea';
18
19
 
19
20
  const DesktopChatInput = memo(() => {
@@ -25,33 +26,37 @@ const DesktopChatInput = memo(() => {
25
26
  ]);
26
27
 
27
28
  return (
28
- <DraggablePanel
29
- fullscreen={expand}
30
- headerHeight={HEADER_HEIGHT}
31
- maxHeight={CHAT_TEXTAREA_MAX_HEIGHT}
32
- minHeight={CHAT_TEXTAREA_HEIGHT}
33
- onSizeChange={(_, size) => {
34
- if (!size) return;
35
-
36
- updatePreference({
37
- inputHeight: typeof size.height === 'string' ? Number.parseInt(size.height) : size.height,
38
- });
39
- }}
40
- placement="bottom"
41
- size={{ height: inputHeight, width: '100%' }}
42
- style={{ zIndex: 10 }}
43
- >
44
- <Flexbox
45
- gap={8}
46
- height={'100%'}
47
- padding={'12px 0 16px'}
48
- style={{ minHeight: CHAT_TEXTAREA_HEIGHT, position: 'relative' }}
29
+ <>
30
+ {!expand && <LocalFiles padding={'8px 16px'} />}
31
+ <DraggablePanel
32
+ fullscreen={expand}
33
+ headerHeight={HEADER_HEIGHT}
34
+ maxHeight={CHAT_TEXTAREA_MAX_HEIGHT}
35
+ minHeight={CHAT_TEXTAREA_HEIGHT}
36
+ onSizeChange={(_, size) => {
37
+ if (!size) return;
38
+
39
+ updatePreference({
40
+ inputHeight:
41
+ typeof size.height === 'string' ? Number.parseInt(size.height) : size.height,
42
+ });
43
+ }}
44
+ placement="bottom"
45
+ size={{ height: inputHeight, width: '100%' }}
46
+ style={{ zIndex: 10 }}
49
47
  >
50
- <Head expand={expand} setExpand={setExpand} />
51
- <TextArea setExpand={setExpand} />
52
- <Footer setExpand={setExpand} />
53
- </Flexbox>
54
- </DraggablePanel>
48
+ <Flexbox
49
+ gap={8}
50
+ height={'100%'}
51
+ padding={'12px 0 16px'}
52
+ style={{ minHeight: CHAT_TEXTAREA_HEIGHT, position: 'relative' }}
53
+ >
54
+ <Head expand={expand} setExpand={setExpand} />
55
+ <TextArea setExpand={setExpand} />
56
+ <Footer expand={expand} setExpand={setExpand} />
57
+ </Flexbox>
58
+ </DraggablePanel>
59
+ </>
55
60
  );
56
61
  });
57
62
 
@@ -4,7 +4,7 @@ export const HEADER_HEIGHT = 64;
4
4
  export const MOBILE_NABBAR_HEIGHT = 44;
5
5
  export const MOBILE_TABBAR_HEIGHT = 48;
6
6
  export const CHAT_TEXTAREA_MAX_HEIGHT = 800;
7
- export const CHAT_TEXTAREA_HEIGHT = 230;
7
+ export const CHAT_TEXTAREA_HEIGHT = 160;
8
8
  export const CHAT_TEXTAREA_HEIGHT_MOBILE = 108;
9
9
  export const CHAT_SIDEBAR_WIDTH = 280;
10
10
 
@@ -1,10 +0,0 @@
1
- import { memo } from 'react';
2
-
3
- import { EditableFileList } from '@/features/FileList';
4
- import { useFileStore } from '@/store/file';
5
-
6
- export const LocalFiles = memo(() => {
7
- const inputFilesList = useFileStore((s) => s.inputFilesList);
8
-
9
- return <EditableFileList items={inputFilesList} padding={0} />;
10
- });