@lobehub/chat 0.149.0 → 0.149.2
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 +42 -0
- package/locales/ar/chat.json +4 -1
- package/locales/ar/modelProvider.json +1 -3
- package/locales/bg-BG/chat.json +4 -1
- package/locales/bg-BG/modelProvider.json +1 -3
- package/locales/de-DE/chat.json +4 -1
- package/locales/de-DE/modelProvider.json +1 -3
- package/locales/en-US/chat.json +7 -4
- package/locales/en-US/modelProvider.json +1 -3
- package/locales/es-ES/chat.json +4 -1
- package/locales/es-ES/modelProvider.json +1 -3
- package/locales/fr-FR/chat.json +7 -4
- package/locales/fr-FR/modelProvider.json +1 -3
- package/locales/it-IT/chat.json +4 -1
- package/locales/it-IT/modelProvider.json +16 -17
- package/locales/ja-JP/chat.json +4 -1
- package/locales/ja-JP/modelProvider.json +14 -16
- package/locales/ko-KR/chat.json +4 -1
- package/locales/ko-KR/modelProvider.json +1 -3
- package/locales/nl-NL/chat.json +4 -1
- package/locales/nl-NL/modelProvider.json +1 -3
- package/locales/pl-PL/chat.json +4 -1
- package/locales/pl-PL/modelProvider.json +1 -3
- package/locales/pt-BR/chat.json +4 -1
- package/locales/pt-BR/modelProvider.json +1 -3
- package/locales/ru-RU/chat.json +4 -1
- package/locales/ru-RU/modelProvider.json +1 -3
- package/locales/tr-TR/chat.json +4 -1
- package/locales/tr-TR/modelProvider.json +1 -3
- package/locales/vi-VN/chat.json +4 -1
- package/locales/vi-VN/modelProvider.json +1 -3
- package/locales/zh-CN/chat.json +4 -1
- package/locales/zh-CN/modelProvider.json +1 -3
- package/locales/zh-TW/chat.json +4 -1
- package/locales/zh-TW/modelProvider.json +1 -3
- package/package.json +1 -1
- package/src/app/chat/(desktop)/features/ChatInput/Footer/SendMore.tsx +117 -0
- package/src/app/chat/(desktop)/features/ChatInput/Footer/index.tsx +9 -56
- package/src/app/chat/(desktop)/features/ChatInput/TextArea.tsx +1 -1
- package/src/app/chat/(desktop)/features/HotKeys.tsx +3 -3
- package/src/app/chat/features/TopicListContent/Topic/TopicContent.tsx +15 -6
- package/src/components/HotKeys/index.tsx +14 -18
- package/src/const/hotkeys.ts +1 -1
- package/src/features/ChatInput/ActionBar/Clear.tsx +3 -3
- package/src/features/ChatInput/Topic/index.tsx +3 -3
- package/src/features/Conversation/Actions/Assistant.tsx +1 -1
- package/src/features/Conversation/Error/OllamaBizError/SetupGuide.tsx +159 -70
- package/src/locales/default/chat.ts +4 -1
- package/src/locales/default/modelProvider.ts +1 -3
- package/src/store/chat/slices/message/action.ts +15 -0
- package/src/store/chat/slices/topic/action.test.ts +8 -4
- package/src/store/chat/slices/topic/action.ts +70 -28
- package/src/store/chat/slices/topic/initialState.ts +2 -1
- package/src/store/chat/slices/topic/reducer.test.ts +3 -5
- package/src/store/chat/slices/topic/reducer.ts +9 -9
|
@@ -147,15 +147,13 @@
|
|
|
147
147
|
"windows": "No Windows, acesse o 'Painel de Controle' e edite as variáveis de ambiente do sistema. Crie uma nova variável de ambiente chamada 'OLLAMA_ORIGINS' para sua conta de usuário, com o valor '*', e clique em 'OK/Aplicar' para salvar."
|
|
148
148
|
},
|
|
149
149
|
"install": {
|
|
150
|
-
"description": "Certifique-se de que o Ollama
|
|
150
|
+
"description": "Certifique-se de que você ativou o Ollama. Se ainda não o fez, baixe o Ollama no site oficial <1>aqui</1>.",
|
|
151
151
|
"docker": "Se preferir usar o Docker, o Ollama também oferece uma imagem oficial. Você pode puxá-la com o comando:",
|
|
152
152
|
"linux": {
|
|
153
153
|
"command": "Instale com o comando a seguir:",
|
|
154
154
|
"manual": "Ou, se preferir, consulte o <1>Guia de Instalação Manual do Linux</1> para instalar manualmente."
|
|
155
155
|
},
|
|
156
|
-
"macos": "Baixe o Ollama para macOS, descompacte e instale:",
|
|
157
156
|
"title": "Instale e inicie o aplicativo Ollama localmente",
|
|
158
|
-
"windows": "Baixe o Ollama para Windows, descompacte e instale:",
|
|
159
157
|
"windowsTab": "Windows (Versão de Visualização)"
|
|
160
158
|
}
|
|
161
159
|
},
|
package/locales/ru-RU/chat.json
CHANGED
|
@@ -25,8 +25,9 @@
|
|
|
25
25
|
"title": "Просто поболтаем"
|
|
26
26
|
},
|
|
27
27
|
"input": {
|
|
28
|
+
"addAi": "Добавить сообщение AI",
|
|
29
|
+
"addUser": "Добавить сообщение пользователя",
|
|
28
30
|
"more": "больше",
|
|
29
|
-
"onlyAdd": "Только добавить сообщение",
|
|
30
31
|
"send": "Отправить",
|
|
31
32
|
"sendWithCmdEnter": "Отправить с помощью {{meta}} + Enter",
|
|
32
33
|
"sendWithEnter": "Отправить с помощью Enter",
|
|
@@ -101,6 +102,8 @@
|
|
|
101
102
|
"confirmRemoveTopic": "Вы уверены, что хотите удалить эту тему? После этого ее нельзя будет восстановить.",
|
|
102
103
|
"confirmRemoveUnstarred": "Вы уверены, что хотите удалить неотмеченные темы? После этого их нельзя будет восстановить.",
|
|
103
104
|
"defaultTitle": "Стандартная тема",
|
|
105
|
+
"duplicateLoading": "Копирование темы...",
|
|
106
|
+
"duplicateSuccess": "Тема успешно скопирована",
|
|
104
107
|
"guide": {
|
|
105
108
|
"desc": "Нажмите на кнопку слева, чтобы сохранить текущий разговор в качестве исторической темы и начать новый разговор",
|
|
106
109
|
"title": "Список тем"
|
|
@@ -147,15 +147,13 @@
|
|
|
147
147
|
"windows": "На Windows откройте \"Панель управления\", зайдите в настройки системных переменных. Создайте новую переменную среды для вашей учетной записи с именем \"OLLAMA_ORIGINS\" и значением * , затем нажмите \"OK/Применить\" для сохранения."
|
|
148
148
|
},
|
|
149
149
|
"install": {
|
|
150
|
-
"description": "
|
|
150
|
+
"description": "Пожалуйста, убедитесь, что вы установили Ollama. Если вы еще не скачали Ollama, перейдите на официальный сайт <1> для загрузки</1>",
|
|
151
151
|
"docker": "Если вы предпочитаете использовать Docker, Ollama также предоставляет официальное образ Docker. Вы можете загрузить его с помощью следующей команды:",
|
|
152
152
|
"linux": {
|
|
153
153
|
"command": "Установите с помощью следующей команды:",
|
|
154
154
|
"manual": "Или вы можете установить его вручную, следуя <1>руководству по установке на Linux</1>."
|
|
155
155
|
},
|
|
156
|
-
"macos": "Скачайте и установите версию Ollama для macOS, распакуйте архив.",
|
|
157
156
|
"title": "Установка и запуск приложения Ollama локально",
|
|
158
|
-
"windows": "Скачайте и установите версию Ollama для Windows, распакуйте архив.",
|
|
159
157
|
"windowsTab": "Windows (превью)"
|
|
160
158
|
}
|
|
161
159
|
},
|
package/locales/tr-TR/chat.json
CHANGED
|
@@ -25,8 +25,9 @@
|
|
|
25
25
|
"title": "Sohbet Et"
|
|
26
26
|
},
|
|
27
27
|
"input": {
|
|
28
|
+
"addAi": "Bir AI mesajı ekleyin",
|
|
29
|
+
"addUser": "Bir kullanıcı mesajı ekleyin",
|
|
28
30
|
"more": "Daha fazla",
|
|
29
|
-
"onlyAdd": "Sadece mesaj ekle",
|
|
30
31
|
"send": "Gönder",
|
|
31
32
|
"sendWithCmdEnter": "{{meta}} + Enter tuşuna basarak gönder",
|
|
32
33
|
"sendWithEnter": "Enter tuşuna basarak gönder",
|
|
@@ -101,6 +102,8 @@
|
|
|
101
102
|
"confirmRemoveTopic": "Bu konuyu silmek üzeresiniz. Bir kere silindiğinde, geri alınamaz. Lütfen dikkatli bir şekilde devam edin.",
|
|
102
103
|
"confirmRemoveUnstarred": "Yıldızlanmamış konuları silmek üzeresiniz. Bir kere silindiğinde, geri alınamazlar. Lütfen dikkatli bir şekilde devam edin.",
|
|
103
104
|
"defaultTitle": "Konu",
|
|
105
|
+
"duplicateLoading": "Konu kopyalanıyor...",
|
|
106
|
+
"duplicateSuccess": "Konu başarıyla kopyalandı",
|
|
104
107
|
"guide": {
|
|
105
108
|
"desc": "Mevcut oturumu geçmiş konu olarak kaydetmek ve yeni bir oturum başlatmak için sol taraftaki düğmeye tıklayın",
|
|
106
109
|
"title": "Konu Listesi"
|
|
@@ -147,15 +147,13 @@
|
|
|
147
147
|
"windows": "Windows'ta, 'Control Panel'ı tıklayarak sistem ortam değişkenlerini düzenleyin. Kullanıcı hesabınıza * değerinde 'OLLAMA_ORIGINS' adında bir ortam değişkeni oluşturun ve 'OK/Apply' düğmesine tıklayarak kaydedin"
|
|
148
148
|
},
|
|
149
149
|
"install": {
|
|
150
|
-
"description": "Ollama'
|
|
150
|
+
"description": "Ollama'nın açık olduğundan emin olun. Ollama'yı indirmediyseniz, lütfen resmi web sitesine giderek <1>indirin</1>.",
|
|
151
151
|
"docker": "Docker kullanmayı tercih ediyorsanız, Ollama resmi Docker görüntüsünü aşağıdaki komutla çekebilirsiniz:",
|
|
152
152
|
"linux": {
|
|
153
153
|
"command": "Aşağıdaki komutları kullanarak yükleyin:",
|
|
154
154
|
"manual": "Ya da, <1>Linux için el ile kurulum kılavuzuna</1> bakarak kendiniz kurabilirsiniz"
|
|
155
155
|
},
|
|
156
|
-
"macos": "<0>macOS sürümü Ollama'yı indirin</0>, açın ve kurun",
|
|
157
156
|
"title": "Yerel olarak Ollama uygulamasını kurun ve başlatın",
|
|
158
|
-
"windows": "<0>Windows sürümü Ollama'yı indirin</0>, açın ve kurun",
|
|
159
157
|
"windowsTab": "Windows (Önizleme)"
|
|
160
158
|
}
|
|
161
159
|
},
|
package/locales/vi-VN/chat.json
CHANGED
|
@@ -25,8 +25,9 @@
|
|
|
25
25
|
"title": "Chuyện phiếm"
|
|
26
26
|
},
|
|
27
27
|
"input": {
|
|
28
|
+
"addAi": "Thêm một tin nhắn AI",
|
|
29
|
+
"addUser": "Thêm một tin nhắn người dùng",
|
|
28
30
|
"more": "Thêm",
|
|
29
|
-
"onlyAdd": "Chỉ thêm tin nhắn",
|
|
30
31
|
"send": "Gửi",
|
|
31
32
|
"sendWithCmdEnter": "Nhấn {{meta}} + Enter để gửi",
|
|
32
33
|
"sendWithEnter": "Nhấn Enter để gửi",
|
|
@@ -101,6 +102,8 @@
|
|
|
101
102
|
"confirmRemoveTopic": "Bạn sắp xóa chủ đề này. Hành động này không thể hoàn tác, vui lòng xác nhận.",
|
|
102
103
|
"confirmRemoveUnstarred": "Bạn sắp xóa các chủ đề chưa được đánh dấu. Hành động này không thể hoàn tác, vui lòng xác nhận.",
|
|
103
104
|
"defaultTitle": "Chủ đề mặc định",
|
|
105
|
+
"duplicateLoading": "Đang sao chép chủ đề...",
|
|
106
|
+
"duplicateSuccess": "Chủ đề đã được sao chép thành công",
|
|
104
107
|
"guide": {
|
|
105
108
|
"desc": "Nhấn vào nút bên trái để lưu cuộc trò chuyện hiện tại như một chủ đề lịch sử và bắt đầu một cuộc trò chuyện mới",
|
|
106
109
|
"title": "Danh sách chủ đề"
|
|
@@ -147,15 +147,13 @@
|
|
|
147
147
|
"windows": "Trên Windows, nhấp vào «Control Panel», vào chỉnh sửa biến môi trường hệ thống. Tạo biến môi trường tên là «OLLAMA_ORIGINS» cho tài khoản người dùng của bạn, giá trị là * , nhấp vào «OK/Áp dụng» để lưu lại"
|
|
148
148
|
},
|
|
149
149
|
"install": {
|
|
150
|
-
"description": "Vui lòng xác nhận rằng bạn đã
|
|
150
|
+
"description": "Vui lòng xác nhận rằng bạn đã bật Ollama. Nếu chưa tải Ollama, vui lòng truy cập trang web chính thức để <1>tải xuống</1>",
|
|
151
151
|
"docker": "Nếu bạn muốn sử dụng Docker, Ollama cũng cung cấp hình ảnh Docker chính thức, bạn có thể kéo theo lệnh sau:",
|
|
152
152
|
"linux": {
|
|
153
153
|
"command": "Cài đặt bằng lệnh sau:",
|
|
154
154
|
"manual": "Hoặc bạn cũng có thể tham khảo <1>Hướng dẫn cài đặt thủ công trên Linux</1> để tự cài đặt"
|
|
155
155
|
},
|
|
156
|
-
"macos": "<0>Tải xuống phiên bản Ollama cho macOS</0>, giải nén và cài đặt",
|
|
157
156
|
"title": "Cài đặt và mở Ollama ứng dụng trên máy cục bộ",
|
|
158
|
-
"windows": "<0>Tải xuống phiên bản Ollama cho Windows</0>, giải nén và cài đặt",
|
|
159
157
|
"windowsTab": "Windows (Bản xem trước)"
|
|
160
158
|
}
|
|
161
159
|
},
|
package/locales/zh-CN/chat.json
CHANGED
|
@@ -25,8 +25,9 @@
|
|
|
25
25
|
"title": "随便聊聊"
|
|
26
26
|
},
|
|
27
27
|
"input": {
|
|
28
|
+
"addAi": "添加一条 AI 消息",
|
|
29
|
+
"addUser": "添加一条用户消息",
|
|
28
30
|
"more": "更多",
|
|
29
|
-
"onlyAdd": "仅添加消息",
|
|
30
31
|
"send": "发送",
|
|
31
32
|
"sendWithCmdEnter": "按 {{meta}} + Enter 键发送",
|
|
32
33
|
"sendWithEnter": "按 Enter 键发送",
|
|
@@ -101,6 +102,8 @@
|
|
|
101
102
|
"confirmRemoveTopic": "即将删除该话题,删除后将不可恢复,请谨慎操作。",
|
|
102
103
|
"confirmRemoveUnstarred": "即将删除未收藏话题,删除后将不可恢复,请谨慎操作。",
|
|
103
104
|
"defaultTitle": "默认话题",
|
|
105
|
+
"duplicateLoading": "话题复制中...",
|
|
106
|
+
"duplicateSuccess": "话题复制成功",
|
|
104
107
|
"guide": {
|
|
105
108
|
"desc": "点击发送左侧按钮可将当前会话保存为历史话题,并开启新一轮会话",
|
|
106
109
|
"title": "话题列表"
|
|
@@ -147,15 +147,13 @@
|
|
|
147
147
|
"windows": "在 Windows 上,点击「控制面板」,进入编辑系统环境变量。为您的用户账户新建名为 「OLLAMA_ORIGINS」 的环境变量,值为 * ,点击 「OK/应用」 保存"
|
|
148
148
|
},
|
|
149
149
|
"install": {
|
|
150
|
-
"description": "请确认你已经开启 Ollama ,如果没有下载 Ollama
|
|
150
|
+
"description": "请确认你已经开启 Ollama ,如果没有下载 Ollama ,请前往官网<1>下载</1>",
|
|
151
151
|
"docker": "如果你更倾向于使用 Docker,Ollama 也提供了官方 Docker 镜像,你可以通过以下命令拉取:",
|
|
152
152
|
"linux": {
|
|
153
153
|
"command": "通过以下命令安装:",
|
|
154
154
|
"manual": "或者,你也可以参考 <1>Linux 手动安装指南</1> 自行安装"
|
|
155
155
|
},
|
|
156
|
-
"macos": "<0>下载 macOS 版 Ollama</0>,解压并安装",
|
|
157
156
|
"title": "在本地安装并开启 Ollama 应用",
|
|
158
|
-
"windows": "<0>下载 Windows 版 Ollama</0>,解压并安装",
|
|
159
157
|
"windowsTab": "Windows (预览版)"
|
|
160
158
|
}
|
|
161
159
|
},
|
package/locales/zh-TW/chat.json
CHANGED
|
@@ -25,8 +25,9 @@
|
|
|
25
25
|
"title": "隨便聊聊"
|
|
26
26
|
},
|
|
27
27
|
"input": {
|
|
28
|
+
"addAi": "新增一條 AI 訊息",
|
|
29
|
+
"addUser": "新增一條使用者訊息",
|
|
28
30
|
"more": "更多",
|
|
29
|
-
"onlyAdd": "僅新增訊息",
|
|
30
31
|
"send": "發送",
|
|
31
32
|
"sendWithCmdEnter": "按 {{meta}} + Enter 鍵發送",
|
|
32
33
|
"sendWithEnter": "按 Enter 鍵發送",
|
|
@@ -101,6 +102,8 @@
|
|
|
101
102
|
"confirmRemoveTopic": "即將刪除該話題,刪除後將不可恢復,請謹慎操作。",
|
|
102
103
|
"confirmRemoveUnstarred": "即將刪除未收藏話題,刪除後將不可恢復,請謹慎操作。",
|
|
103
104
|
"defaultTitle": "默認話題",
|
|
105
|
+
"duplicateLoading": "話題複製中...",
|
|
106
|
+
"duplicateSuccess": "話題複製成功",
|
|
104
107
|
"guide": {
|
|
105
108
|
"desc": "點擊發送左側按鈕可將當前對話保存為歷史話題,並開啟新一輪對話",
|
|
106
109
|
"title": "話題列表"
|
|
@@ -147,15 +147,13 @@
|
|
|
147
147
|
"windows": "在 Windows 上,點擊「控制面板」,進入編輯系統環境變數。為您的使用者帳戶新增名為「OLLAMA_ORIGINS」的環境變數,值為 *,點擊「確定/應用」保存"
|
|
148
148
|
},
|
|
149
149
|
"install": {
|
|
150
|
-
"description": "
|
|
150
|
+
"description": "請確認您已經啟用 Ollama,如果尚未下載 Ollama,請前往官網<1>下載</1>",
|
|
151
151
|
"docker": "如果您更傾向於使用 Docker,Ollama 也提供了官方 Docker 映像,您可以透過以下命令拉取:",
|
|
152
152
|
"linux": {
|
|
153
153
|
"command": "透過以下命令安裝:",
|
|
154
154
|
"manual": "或者,您也可以參考 <1>Linux 手動安裝指南</1> 自行安裝"
|
|
155
155
|
},
|
|
156
|
-
"macos": "<0>下載 macOS 版 Ollama</0>,解壓並安裝",
|
|
157
156
|
"title": "在本地安裝並啟動 Ollama 應用",
|
|
158
|
-
"windows": "<0>下載 Windows 版 Ollama</0>,解壓並安裝",
|
|
159
157
|
"windowsTab": "Windows (預覽版)"
|
|
160
158
|
}
|
|
161
159
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.149.
|
|
3
|
+
"version": "0.149.2",
|
|
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",
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Icon } from '@lobehub/ui';
|
|
2
|
+
import { Button, Dropdown } from 'antd';
|
|
3
|
+
import { createStyles } from 'antd-style';
|
|
4
|
+
import { BotMessageSquare, LucideCheck, LucideChevronDown, MessageSquarePlus } from 'lucide-react';
|
|
5
|
+
import { memo } from 'react';
|
|
6
|
+
import { useHotkeys } from 'react-hotkeys-hook';
|
|
7
|
+
import { useTranslation } from 'react-i18next';
|
|
8
|
+
import { Flexbox } from 'react-layout-kit';
|
|
9
|
+
|
|
10
|
+
import HotKeys from '@/components/HotKeys';
|
|
11
|
+
import { ALT_KEY } from '@/const/hotkeys';
|
|
12
|
+
import { useSendMessage } from '@/features/ChatInput/useSend';
|
|
13
|
+
import { useChatStore } from '@/store/chat';
|
|
14
|
+
import { useGlobalStore } from '@/store/global';
|
|
15
|
+
import { preferenceSelectors } from '@/store/global/selectors';
|
|
16
|
+
import { isMacOS } from '@/utils/platform';
|
|
17
|
+
|
|
18
|
+
const useStyles = createStyles(({ css, prefixCls }) => {
|
|
19
|
+
return {
|
|
20
|
+
arrow: css`
|
|
21
|
+
&.${prefixCls}-btn.${prefixCls}-btn-icon-only {
|
|
22
|
+
width: 28px;
|
|
23
|
+
}
|
|
24
|
+
`,
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const isMac = isMacOS();
|
|
29
|
+
|
|
30
|
+
const SendMore = memo(() => {
|
|
31
|
+
const { t } = useTranslation('chat');
|
|
32
|
+
|
|
33
|
+
const { styles } = useStyles();
|
|
34
|
+
|
|
35
|
+
const [useCmdEnterToSend, updatePreference] = useGlobalStore((s) => [
|
|
36
|
+
preferenceSelectors.useCmdEnterToSend(s),
|
|
37
|
+
s.updatePreference,
|
|
38
|
+
]);
|
|
39
|
+
const addAIMessage = useChatStore((s) => s.addAIMessage);
|
|
40
|
+
|
|
41
|
+
const sendMessage = useSendMessage();
|
|
42
|
+
|
|
43
|
+
const hotKey = [ALT_KEY, 'enter'].join('+');
|
|
44
|
+
useHotkeys(
|
|
45
|
+
hotKey,
|
|
46
|
+
(keyboardEvent, hotkeysEvent) => {
|
|
47
|
+
console.log(keyboardEvent, hotkeysEvent);
|
|
48
|
+
sendMessage(true);
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
enableOnFormTags: true,
|
|
52
|
+
preventDefault: true,
|
|
53
|
+
},
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<Dropdown
|
|
58
|
+
menu={{
|
|
59
|
+
items: [
|
|
60
|
+
{
|
|
61
|
+
icon: !useCmdEnterToSend ? <Icon icon={LucideCheck} /> : <div />,
|
|
62
|
+
key: 'sendWithEnter',
|
|
63
|
+
label: t('input.sendWithEnter'),
|
|
64
|
+
onClick: () => {
|
|
65
|
+
updatePreference({ useCmdEnterToSend: false });
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
icon: useCmdEnterToSend ? <Icon icon={LucideCheck} /> : <div />,
|
|
70
|
+
key: 'sendWithCmdEnter',
|
|
71
|
+
label: t('input.sendWithCmdEnter', {
|
|
72
|
+
meta: isMac ? 'Cmd' : 'Ctrl',
|
|
73
|
+
}),
|
|
74
|
+
onClick: () => {
|
|
75
|
+
updatePreference({ useCmdEnterToSend: true });
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{ type: 'divider' },
|
|
79
|
+
{
|
|
80
|
+
icon: <Icon icon={BotMessageSquare} />,
|
|
81
|
+
key: 'addAi',
|
|
82
|
+
label: t('input.addAi'),
|
|
83
|
+
onClick: () => {
|
|
84
|
+
addAIMessage();
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
icon: <Icon icon={MessageSquarePlus} />,
|
|
89
|
+
key: 'addUser',
|
|
90
|
+
label: (
|
|
91
|
+
<Flexbox gap={24} horizontal>
|
|
92
|
+
{t('input.addUser')}
|
|
93
|
+
<HotKeys keys={hotKey} />
|
|
94
|
+
</Flexbox>
|
|
95
|
+
),
|
|
96
|
+
onClick: () => {
|
|
97
|
+
sendMessage(true);
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
}}
|
|
102
|
+
placement={'topRight'}
|
|
103
|
+
trigger={['hover']}
|
|
104
|
+
>
|
|
105
|
+
<Button
|
|
106
|
+
aria-label={t('input.more')}
|
|
107
|
+
className={styles.arrow}
|
|
108
|
+
icon={<Icon icon={LucideChevronDown} />}
|
|
109
|
+
type={'primary'}
|
|
110
|
+
/>
|
|
111
|
+
</Dropdown>
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
SendMore.displayName = 'SendMore';
|
|
116
|
+
|
|
117
|
+
export default SendMore;
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import { Icon } from '@lobehub/ui';
|
|
2
|
-
import { Button,
|
|
2
|
+
import { Button, Space } from 'antd';
|
|
3
3
|
import { createStyles } from 'antd-style';
|
|
4
|
-
import {
|
|
5
|
-
ChevronUp,
|
|
6
|
-
CornerDownLeft,
|
|
7
|
-
LucideCheck,
|
|
8
|
-
LucideChevronDown,
|
|
9
|
-
LucideCommand,
|
|
10
|
-
LucidePlus,
|
|
11
|
-
} from 'lucide-react';
|
|
4
|
+
import { ChevronUp, CornerDownLeft, LucideCommand } from 'lucide-react';
|
|
12
5
|
import { rgba } from 'polished';
|
|
13
6
|
import { memo } from 'react';
|
|
14
7
|
import { useTranslation } from 'react-i18next';
|
|
@@ -26,6 +19,7 @@ import { isMacOS } from '@/utils/platform';
|
|
|
26
19
|
|
|
27
20
|
import DragUpload from './DragUpload';
|
|
28
21
|
import { LocalFiles } from './LocalFiles';
|
|
22
|
+
import SendMore from './SendMore';
|
|
29
23
|
|
|
30
24
|
const useStyles = createStyles(({ css, prefixCls, token }) => {
|
|
31
25
|
return {
|
|
@@ -69,13 +63,13 @@ const Footer = memo<FooterProps>(({ setExpand }) => {
|
|
|
69
63
|
!!s.chatLoadingId,
|
|
70
64
|
s.stopGenerateMessage,
|
|
71
65
|
]);
|
|
72
|
-
const [useCmdEnterToSend, updatePreference] = useGlobalStore((s) => [
|
|
73
|
-
preferenceSelectors.useCmdEnterToSend(s),
|
|
74
|
-
s.updatePreference,
|
|
75
|
-
]);
|
|
76
66
|
|
|
77
67
|
const model = useSessionStore(agentSelectors.currentAgentModel);
|
|
78
|
-
|
|
68
|
+
|
|
69
|
+
const [useCmdEnterToSend, canUpload] = useGlobalStore((s) => [
|
|
70
|
+
preferenceSelectors.useCmdEnterToSend(s),
|
|
71
|
+
modelProviderSelectors.isModelEnabledUpload(model)(s),
|
|
72
|
+
]);
|
|
79
73
|
|
|
80
74
|
const sendMessage = useSendMessage();
|
|
81
75
|
|
|
@@ -147,48 +141,7 @@ const Footer = memo<FooterProps>(({ setExpand }) => {
|
|
|
147
141
|
>
|
|
148
142
|
{t('input.send')}
|
|
149
143
|
</Button>
|
|
150
|
-
<
|
|
151
|
-
menu={{
|
|
152
|
-
items: [
|
|
153
|
-
{
|
|
154
|
-
icon: !useCmdEnterToSend ? <Icon icon={LucideCheck} /> : <div />,
|
|
155
|
-
key: 'sendWithEnter',
|
|
156
|
-
label: t('input.sendWithEnter'),
|
|
157
|
-
onClick: () => {
|
|
158
|
-
updatePreference({ useCmdEnterToSend: false });
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
icon: useCmdEnterToSend ? <Icon icon={LucideCheck} /> : <div />,
|
|
163
|
-
key: 'sendWithCmdEnter',
|
|
164
|
-
label: t('input.sendWithCmdEnter', {
|
|
165
|
-
meta: isMac ? 'Cmd' : 'Ctrl',
|
|
166
|
-
}),
|
|
167
|
-
onClick: () => {
|
|
168
|
-
updatePreference({ useCmdEnterToSend: true });
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
{ type: 'divider' },
|
|
172
|
-
{
|
|
173
|
-
icon: <Icon icon={LucidePlus} />,
|
|
174
|
-
key: 'onlyAdd',
|
|
175
|
-
label: t('input.onlyAdd'),
|
|
176
|
-
onClick: () => {
|
|
177
|
-
sendMessage(true);
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
],
|
|
181
|
-
}}
|
|
182
|
-
placement={'topRight'}
|
|
183
|
-
trigger={['hover']}
|
|
184
|
-
>
|
|
185
|
-
<Button
|
|
186
|
-
aria-label={t('input.more')}
|
|
187
|
-
className={styles.arrow}
|
|
188
|
-
icon={<Icon icon={LucideChevronDown} />}
|
|
189
|
-
type={'primary'}
|
|
190
|
-
/>
|
|
191
|
-
</Dropdown>
|
|
144
|
+
<SendMore />
|
|
192
145
|
</Space.Compact>
|
|
193
146
|
)}
|
|
194
147
|
</Flexbox>
|
|
@@ -88,7 +88,7 @@ const InputArea = memo<InputAreaProps>(({ setExpand }) => {
|
|
|
88
88
|
isChineseInput.current = true;
|
|
89
89
|
}}
|
|
90
90
|
onPressEnter={(e) => {
|
|
91
|
-
if (loading || e.shiftKey || isChineseInput.current) return;
|
|
91
|
+
if (loading || e.altKey || e.shiftKey || isChineseInput.current) return;
|
|
92
92
|
|
|
93
93
|
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
94
94
|
const send = () => {
|
|
@@ -2,13 +2,13 @@ import isEqual from 'fast-deep-equal';
|
|
|
2
2
|
import { useCallback } from 'react';
|
|
3
3
|
import { useHotkeys } from 'react-hotkeys-hook';
|
|
4
4
|
|
|
5
|
-
import { CLEAN_MESSAGE_KEY, META_KEY,
|
|
5
|
+
import { ALT_KEY, CLEAN_MESSAGE_KEY, META_KEY, REGENERATE_KEY } from '@/const/hotkeys';
|
|
6
6
|
import { useChatStore } from '@/store/chat';
|
|
7
7
|
import { chatSelectors } from '@/store/chat/selectors';
|
|
8
8
|
import { useFileStore } from '@/store/file';
|
|
9
9
|
|
|
10
10
|
const HotKeys = () => {
|
|
11
|
-
const resendHotkeys = [
|
|
11
|
+
const resendHotkeys = [ALT_KEY, REGENERATE_KEY].join('+');
|
|
12
12
|
|
|
13
13
|
const [regenerateMessage, clearMessage] = useChatStore((s) => [
|
|
14
14
|
s.regenerateMessage,
|
|
@@ -17,7 +17,7 @@ const HotKeys = () => {
|
|
|
17
17
|
const lastMessage = useChatStore(chatSelectors.latestMessage, isEqual);
|
|
18
18
|
|
|
19
19
|
const [clearImageList] = useFileStore((s) => [s.clearImageList]);
|
|
20
|
-
const clearHotkeys = [META_KEY,
|
|
20
|
+
const clearHotkeys = [META_KEY, ALT_KEY, CLEAN_MESSAGE_KEY].join('+');
|
|
21
21
|
|
|
22
22
|
const resetConversation = useCallback(() => {
|
|
23
23
|
clearMessage();
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { ActionIcon, EditableText, Icon } from '@lobehub/ui';
|
|
2
2
|
import { App, Dropdown, type MenuProps, Typography } from 'antd';
|
|
3
3
|
import { createStyles } from 'antd-style';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
LucideCopy,
|
|
6
|
+
LucideLoader2,
|
|
7
|
+
MoreVertical,
|
|
8
|
+
PencilLine,
|
|
9
|
+
Star,
|
|
10
|
+
Trash,
|
|
11
|
+
Wand2,
|
|
12
|
+
} from 'lucide-react';
|
|
5
13
|
import { memo, useMemo } from 'react';
|
|
6
14
|
import { useTranslation } from 'react-i18next';
|
|
7
15
|
import { Flexbox } from 'react-layout-kit';
|
|
@@ -40,7 +48,7 @@ const TopicContent = memo<TopicContentProps>(({ id, title, fav, showMore }) => {
|
|
|
40
48
|
removeTopic,
|
|
41
49
|
autoRenameTopicTitle,
|
|
42
50
|
duplicateTopic,
|
|
43
|
-
|
|
51
|
+
isLoading,
|
|
44
52
|
] = useChatStore((s) => [
|
|
45
53
|
s.topicRenamingId === id,
|
|
46
54
|
s.favoriteTopic,
|
|
@@ -48,7 +56,7 @@ const TopicContent = memo<TopicContentProps>(({ id, title, fav, showMore }) => {
|
|
|
48
56
|
s.removeTopic,
|
|
49
57
|
s.autoRenameTopicTitle,
|
|
50
58
|
s.duplicateTopic,
|
|
51
|
-
s.
|
|
59
|
+
s.topicLoadingIds.includes(id),
|
|
52
60
|
]);
|
|
53
61
|
const { styles, theme } = useStyles();
|
|
54
62
|
|
|
@@ -137,15 +145,16 @@ const TopicContent = memo<TopicContentProps>(({ id, title, fav, showMore }) => {
|
|
|
137
145
|
}}
|
|
138
146
|
>
|
|
139
147
|
<ActionIcon
|
|
140
|
-
color={fav ? theme.colorWarning : undefined}
|
|
141
|
-
fill={fav ? theme.colorWarning : 'transparent'}
|
|
142
|
-
icon={Star}
|
|
148
|
+
color={fav && !isLoading ? theme.colorWarning : undefined}
|
|
149
|
+
fill={fav && !isLoading ? theme.colorWarning : 'transparent'}
|
|
150
|
+
icon={isLoading ? LucideLoader2 : Star}
|
|
143
151
|
onClick={(e) => {
|
|
144
152
|
e.stopPropagation();
|
|
145
153
|
if (!id) return;
|
|
146
154
|
favoriteTopic(id, !fav);
|
|
147
155
|
}}
|
|
148
156
|
size={'small'}
|
|
157
|
+
spin={isLoading}
|
|
149
158
|
/>
|
|
150
159
|
{!editing ? (
|
|
151
160
|
<Paragraph
|
|
@@ -4,53 +4,49 @@ import { Icon } from '@lobehub/ui';
|
|
|
4
4
|
import { createStyles } from 'antd-style';
|
|
5
5
|
import { isString } from 'lodash-es';
|
|
6
6
|
import { Command, Delete, Option } from 'lucide-react';
|
|
7
|
+
import { rgba } from 'polished';
|
|
7
8
|
import { memo, useEffect, useState } from 'react';
|
|
8
9
|
import { Flexbox } from 'react-layout-kit';
|
|
9
10
|
|
|
10
|
-
import { CLEAN_MESSAGE_KEY, META_KEY
|
|
11
|
+
import { ALT_KEY, CLEAN_MESSAGE_KEY, META_KEY } from '@/const/hotkeys';
|
|
11
12
|
import { usePlatform } from '@/hooks/usePlatform';
|
|
12
13
|
|
|
13
14
|
const useStyles = createStyles(
|
|
14
|
-
({ css, token }) => css`
|
|
15
|
+
({ css, token }, inverseTheme: boolean) => css`
|
|
15
16
|
font-size: 12px;
|
|
16
17
|
|
|
17
|
-
span {
|
|
18
|
-
font-weight: 600;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
18
|
kbd {
|
|
22
19
|
min-width: 16px;
|
|
23
|
-
|
|
20
|
+
height: 22px;
|
|
21
|
+
padding-inline: 8px;
|
|
24
22
|
|
|
25
|
-
line-height:
|
|
26
|
-
color: ${token.
|
|
23
|
+
line-height: 22px;
|
|
24
|
+
color: ${inverseTheme ? token.colorTextTertiary : token.colorTextSecondary};
|
|
27
25
|
text-align: center;
|
|
28
26
|
|
|
29
|
-
background: ${token.
|
|
30
|
-
border: 1px solid ${token.colorBorderSecondary};
|
|
31
|
-
border-bottom-color: ${token.colorBorder};
|
|
27
|
+
background: ${inverseTheme ? rgba(token.colorTextTertiary, 0.15) : token.colorFillTertiary};
|
|
32
28
|
border-radius: ${token.borderRadius}px;
|
|
33
|
-
box-shadow: inset 0 -1px 0 ${token.colorBorder};
|
|
34
29
|
}
|
|
35
30
|
`,
|
|
36
31
|
);
|
|
37
32
|
|
|
38
33
|
export interface HotKeysProps {
|
|
39
34
|
desc?: string;
|
|
35
|
+
inverseTheme?: boolean;
|
|
40
36
|
keys: string;
|
|
41
37
|
}
|
|
42
38
|
|
|
43
|
-
const HotKeys = memo<HotKeysProps>(({ keys, desc }) => {
|
|
44
|
-
const { styles } = useStyles();
|
|
39
|
+
const HotKeys = memo<HotKeysProps>(({ keys, desc, inverseTheme }) => {
|
|
40
|
+
const { styles } = useStyles(inverseTheme);
|
|
45
41
|
const [keysGroup, setKeysGroup] = useState(keys.split('+'));
|
|
46
42
|
const visibility = typeof window === 'undefined' ? 'hidden' : 'visible';
|
|
47
43
|
const { isApple } = usePlatform();
|
|
48
44
|
|
|
49
45
|
useEffect(() => {
|
|
50
46
|
const mapping: Record<string, any> = {
|
|
47
|
+
[ALT_KEY]: isApple ? <Icon icon={Option} /> : 'alt',
|
|
51
48
|
[CLEAN_MESSAGE_KEY]: isApple ? <Icon icon={Delete} /> : 'backspace',
|
|
52
49
|
[META_KEY]: isApple ? <Icon icon={Command} /> : 'ctrl',
|
|
53
|
-
[PREFIX_KEY]: isApple ? <Icon icon={Option} /> : 'alt',
|
|
54
50
|
};
|
|
55
51
|
const newValue = keys
|
|
56
52
|
.split('+')
|
|
@@ -60,7 +56,7 @@ const HotKeys = memo<HotKeysProps>(({ keys, desc }) => {
|
|
|
60
56
|
}, [keys]);
|
|
61
57
|
|
|
62
58
|
const content = (
|
|
63
|
-
<Flexbox align={'center'} className={styles} gap={
|
|
59
|
+
<Flexbox align={'center'} className={styles} gap={4} horizontal>
|
|
64
60
|
{keysGroup.map((key, index) => (
|
|
65
61
|
<kbd key={index}>
|
|
66
62
|
<span style={{ visibility }}>{isString(key) ? key.toUpperCase() : key}</span>
|
|
@@ -71,7 +67,7 @@ const HotKeys = memo<HotKeysProps>(({ keys, desc }) => {
|
|
|
71
67
|
|
|
72
68
|
if (!desc) return content;
|
|
73
69
|
return (
|
|
74
|
-
<Flexbox
|
|
70
|
+
<Flexbox gap={16} horizontal>
|
|
75
71
|
{desc}
|
|
76
72
|
{content}
|
|
77
73
|
</Flexbox>
|
package/src/const/hotkeys.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { memo, useCallback, useState } from 'react';
|
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
|
|
7
7
|
import HotKeys from '@/components/HotKeys';
|
|
8
|
-
import { CLEAN_MESSAGE_KEY, META_KEY
|
|
8
|
+
import { ALT_KEY, CLEAN_MESSAGE_KEY, META_KEY } from '@/const/hotkeys';
|
|
9
9
|
import { useChatStore } from '@/store/chat';
|
|
10
10
|
import { useFileStore } from '@/store/file';
|
|
11
11
|
|
|
@@ -13,7 +13,7 @@ const Clear = memo(() => {
|
|
|
13
13
|
const { t } = useTranslation('setting');
|
|
14
14
|
const [clearMessage] = useChatStore((s) => [s.clearMessage]);
|
|
15
15
|
const [clearImageList] = useFileStore((s) => [s.clearImageList]);
|
|
16
|
-
const hotkeys = [META_KEY,
|
|
16
|
+
const hotkeys = [META_KEY, ALT_KEY, CLEAN_MESSAGE_KEY].join('+');
|
|
17
17
|
const [confirmOpened, updateConfirmOpened] = useState(false);
|
|
18
18
|
|
|
19
19
|
const resetConversation = useCallback(async () => {
|
|
@@ -24,7 +24,7 @@ const Clear = memo(() => {
|
|
|
24
24
|
const actionTitle: any = confirmOpened ? (
|
|
25
25
|
void 0
|
|
26
26
|
) : (
|
|
27
|
-
<HotKeys desc={t('clearCurrentMessages', { ns: 'chat' })} keys={hotkeys} />
|
|
27
|
+
<HotKeys desc={t('clearCurrentMessages', { ns: 'chat' })} inverseTheme keys={hotkeys} />
|
|
28
28
|
);
|
|
29
29
|
|
|
30
30
|
return (
|