diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 48050d3f..3b92776f 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,5 +1,5 @@ module.exports = { - plugins: ['unused-imports'], + plugins: ['unused-imports', 'simple-import-sort'], extends: [ 'eslint:recommended', 'plugin:react/recommended', @@ -14,12 +14,7 @@ module.exports = { 'unused-imports/no-unused-imports': 'error', '@typescript-eslint/no-non-null-asserted-optional-chain': 'off', 'react/prop-types': 'off', - 'sort-imports': [ - 'error', - { - ignoreCase: true, - ignoreDeclarationSort: true - } - ] + 'simple-import-sort/imports': 'error', + 'simple-import-sort/exports': 'error' } } diff --git a/electron.vite.config.ts b/electron.vite.config.ts index 8b7aa3c3..668c5c3e 100644 --- a/electron.vite.config.ts +++ b/electron.vite.config.ts @@ -1,5 +1,5 @@ -import { defineConfig, externalizeDepsPlugin } from 'electron-vite' import react from '@vitejs/plugin-react' +import { defineConfig, externalizeDepsPlugin } from 'electron-vite' import { resolve } from 'path' export default defineConfig({ diff --git a/package.json b/package.json index aa4f82f7..eda1c7f2 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "electron-log": "^5.1.5", "electron-store": "^8.2.0", "electron-updater": "^6.1.7", - "electron-window-state": "^5.0.3" + "electron-window-state": "^5.0.3", + "eslint-plugin-simple-import-sort": "^12.1.1" }, "devDependencies": { "@anthropic-ai/sdk": "^0.24.3", diff --git a/src/main/event.ts b/src/main/event.ts index 47785a20..b6b12163 100644 --- a/src/main/event.ts +++ b/src/main/event.ts @@ -1,6 +1,6 @@ import { dialog, SaveDialogOptions, SaveDialogReturnValue } from 'electron' -import { writeFile } from 'fs' import logger from 'electron-log' +import { writeFile } from 'fs' export async function saveFile(_: Electron.IpcMainInvokeEvent, fileName: string, content: string): Promise { try { diff --git a/src/main/index.ts b/src/main/index.ts index f694a6a4..3f108c6e 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -4,6 +4,7 @@ import { app, BrowserWindow, ipcMain, Menu, MenuItem, session, shell } from 'ele import installExtension, { REDUX_DEVTOOLS } from 'electron-devtools-installer' import windowStateKeeper from 'electron-window-state' import { join } from 'path' + import icon from '../../resources/icon.png?asset' import { appConfig, titleBarOverlayDark, titleBarOverlayLight } from './config' import { saveFile } from './event' diff --git a/src/main/updater.ts b/src/main/updater.ts index 05b8aca4..07b24328 100644 --- a/src/main/updater.ts +++ b/src/main/updater.ts @@ -1,6 +1,6 @@ -import { AppUpdater as _AppUpdater, autoUpdater, UpdateInfo } from 'electron-updater' -import logger from 'electron-log' import { BrowserWindow, dialog } from 'electron' +import logger from 'electron-log' +import { AppUpdater as _AppUpdater, autoUpdater, UpdateInfo } from 'electron-updater' export default class AppUpdater { autoUpdater: _AppUpdater = autoUpdater diff --git a/src/preload/index.ts b/src/preload/index.ts index 1b3a34f7..4b3a9c65 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -1,5 +1,5 @@ -import { contextBridge, ipcRenderer } from 'electron' import { electronAPI } from '@electron-toolkit/preload' +import { contextBridge, ipcRenderer } from 'electron' // Custom APIs for renderer const api = { diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 010e014e..28348bc5 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -2,6 +2,7 @@ import store, { persistor } from '@renderer/store' import { Provider } from 'react-redux' import { HashRouter, Route, Routes } from 'react-router-dom' import { PersistGate } from 'redux-persist/integration/react' + import Sidebar from './components/app/Sidebar' import TopViewContainer from './components/TopView' import AppsPage from './pages/apps/AppsPage' diff --git a/src/renderer/src/components/Popups/AssistantSettingPopup.tsx b/src/renderer/src/components/Popups/AssistantSettingPopup.tsx index 3c752668..f6612f83 100644 --- a/src/renderer/src/components/Popups/AssistantSettingPopup.tsx +++ b/src/renderer/src/components/Popups/AssistantSettingPopup.tsx @@ -1,11 +1,12 @@ -import { Input, Modal } from 'antd' -import { useState } from 'react' -import { TopView } from '../TopView' -import { Box } from '../Layout' import { Assistant } from '@renderer/types' +import { Input, Modal } from 'antd' import TextArea from 'antd/es/input/TextArea' +import { useState } from 'react' import { useTranslation } from 'react-i18next' +import { Box } from '../Layout' +import { TopView } from '../TopView' + interface AssistantSettingPopupShowParams { assistant: Assistant } diff --git a/src/renderer/src/components/Popups/PromptPopup.tsx b/src/renderer/src/components/Popups/PromptPopup.tsx index db6969d5..3fc15629 100644 --- a/src/renderer/src/components/Popups/PromptPopup.tsx +++ b/src/renderer/src/components/Popups/PromptPopup.tsx @@ -1,7 +1,8 @@ import { Input, InputProps, Modal } from 'antd' import { useState } from 'react' -import { TopView } from '../TopView' + import { Box } from '../Layout' +import { TopView } from '../TopView' interface PromptPopupShowParams { title: string diff --git a/src/renderer/src/components/Popups/TemplatePopup.tsx b/src/renderer/src/components/Popups/TemplatePopup.tsx index 10adf006..1befc411 100644 --- a/src/renderer/src/components/Popups/TemplatePopup.tsx +++ b/src/renderer/src/components/Popups/TemplatePopup.tsx @@ -1,7 +1,8 @@ import { Modal } from 'antd' import { useState } from 'react' -import { TopView } from '../TopView' + import { Box } from '../Layout' +import { TopView } from '../TopView' interface ShowParams { title: string diff --git a/src/renderer/src/components/app/Sidebar.tsx b/src/renderer/src/components/app/Sidebar.tsx index 99c9cb86..24ffa373 100644 --- a/src/renderer/src/components/app/Sidebar.tsx +++ b/src/renderer/src/components/app/Sidebar.tsx @@ -1,10 +1,10 @@ -import { FC } from 'react' -import Logo from '@renderer/assets/images/logo.png' -import styled from 'styled-components' -import { Link, useLocation } from 'react-router-dom' -import useAvatar from '@renderer/hooks/useAvatar' -import { isWindows } from '@renderer/config/constant' import { TranslationOutlined } from '@ant-design/icons' +import Logo from '@renderer/assets/images/logo.png' +import { isWindows } from '@renderer/config/constant' +import useAvatar from '@renderer/hooks/useAvatar' +import { FC } from 'react' +import { Link, useLocation } from 'react-router-dom' +import styled from 'styled-components' const Sidebar: FC = () => { const { pathname } = useLocation() diff --git a/src/renderer/src/config/provider.ts b/src/renderer/src/config/provider.ts index 917ea856..762f4056 100644 --- a/src/renderer/src/config/provider.ts +++ b/src/renderer/src/config/provider.ts @@ -1,28 +1,28 @@ -import OpenAiProviderLogo from '@renderer/assets/images/providers/openai.jpeg' -import SiliconFlowProviderLogo from '@renderer/assets/images/providers/silicon.png' -import DeepSeekProviderLogo from '@renderer/assets/images/providers/deepseek.png' -import YiProviderLogo from '@renderer/assets/images/providers/yi.svg' -import GroqProviderLogo from '@renderer/assets/images/providers/groq.png' -import ZhipuProviderLogo from '@renderer/assets/images/providers/zhipu.png' -import OllamaProviderLogo from '@renderer/assets/images/providers/ollama.png' -import MoonshotProviderLogo from '@renderer/assets/images/providers/moonshot.jpeg' -import OpenRouterProviderLogo from '@renderer/assets/images/providers/openrouter.png' -import BaichuanProviderLogo from '@renderer/assets/images/providers/baichuan.png' -import DashScopeProviderLogo from '@renderer/assets/images/providers/dashscope.png' -import AnthropicProviderLogo from '@renderer/assets/images/providers/anthropic.jpeg' -import AiHubMixProviderLogo from '@renderer/assets/images/providers/aihubmix.jpg' -import ChatGPTModelLogo from '@renderer/assets/images/models/chatgpt.jpeg' +import BaichuanModelLogo from '@renderer/assets/images/models/baichuan.png' import ChatGLMModelLogo from '@renderer/assets/images/models/chatglm.jpeg' +import ChatGPTModelLogo from '@renderer/assets/images/models/chatgpt.jpeg' +import ClaudeModelLogo from '@renderer/assets/images/models/claude.png' import DeepSeekModelLogo from '@renderer/assets/images/models/deepseek.png' import GemmaModelLogo from '@renderer/assets/images/models/gemma.jpeg' +import LlamaModelLogo from '@renderer/assets/images/models/llama.jpeg' +import MicrosoftModelLogo from '@renderer/assets/images/models/microsoft.png' +import MixtralModelLogo from '@renderer/assets/images/models/mixtral.jpeg' import QwenModelLogo from '@renderer/assets/images/models/qwen.png' import YiModelLogo from '@renderer/assets/images/models/yi.svg' -import LlamaModelLogo from '@renderer/assets/images/models/llama.jpeg' -import MixtralModelLogo from '@renderer/assets/images/models/mixtral.jpeg' +import AiHubMixProviderLogo from '@renderer/assets/images/providers/aihubmix.jpg' +import AnthropicProviderLogo from '@renderer/assets/images/providers/anthropic.jpeg' +import BaichuanProviderLogo from '@renderer/assets/images/providers/baichuan.png' +import DashScopeProviderLogo from '@renderer/assets/images/providers/dashscope.png' +import DeepSeekProviderLogo from '@renderer/assets/images/providers/deepseek.png' +import GroqProviderLogo from '@renderer/assets/images/providers/groq.png' +import MoonshotProviderLogo from '@renderer/assets/images/providers/moonshot.jpeg' import MoonshotModelLogo from '@renderer/assets/images/providers/moonshot.jpeg' -import MicrosoftModelLogo from '@renderer/assets/images/models/microsoft.png' -import BaichuanModelLogo from '@renderer/assets/images/models/baichuan.png' -import ClaudeModelLogo from '@renderer/assets/images/models/claude.png' +import OllamaProviderLogo from '@renderer/assets/images/providers/ollama.png' +import OpenAiProviderLogo from '@renderer/assets/images/providers/openai.jpeg' +import OpenRouterProviderLogo from '@renderer/assets/images/providers/openrouter.png' +import SiliconFlowProviderLogo from '@renderer/assets/images/providers/silicon.png' +import YiProviderLogo from '@renderer/assets/images/providers/yi.svg' +import ZhipuProviderLogo from '@renderer/assets/images/providers/zhipu.png' export function getProviderLogo(providerId: string) { switch (providerId) { diff --git a/src/renderer/src/env.d.ts b/src/renderer/src/env.d.ts index 8b1587ec..09429c03 100644 --- a/src/renderer/src/env.d.ts +++ b/src/renderer/src/env.d.ts @@ -1,8 +1,8 @@ /// +import type KeyvStorage from '@kangfenmao/keyv-storage' import { MessageInstance } from 'antd/es/message/interface' import { HookAPI } from 'antd/es/modal/useModal' -import type KeyvStorage from '@kangfenmao/keyv-storage' declare global { interface Window { diff --git a/src/renderer/src/hooks/useAppInit.ts b/src/renderer/src/hooks/useAppInit.ts index d77aaac8..0c7f627a 100644 --- a/src/renderer/src/hooks/useAppInit.ts +++ b/src/renderer/src/hooks/useAppInit.ts @@ -1,21 +1,22 @@ -import { i18nInit } from '@renderer/i18n' +import i18n from '@renderer/i18n' import LocalStorage from '@renderer/services/storage' import { useAppDispatch } from '@renderer/store' import { setAvatar } from '@renderer/store/runtime' import { runAsyncFunction } from '@renderer/utils' import { useEffect } from 'react' + import { useSettings } from './useSettings' export function useAppInit() { const dispatch = useAppDispatch() const { proxyUrl } = useSettings() + const { language } = useSettings() useEffect(() => { runAsyncFunction(async () => { const storedImage = await LocalStorage.getImage('avatar') storedImage && dispatch(setAvatar(storedImage)) }) - i18nInit() }, [dispatch]) useEffect(() => { @@ -28,4 +29,8 @@ export function useAppInit() { useEffect(() => { proxyUrl && window.api.setProxy(proxyUrl) }, [proxyUrl]) + + useEffect(() => { + i18n.changeLanguage(language || navigator.language || 'en-US') + }, [language]) } diff --git a/src/renderer/src/hooks/useProvider.ts b/src/renderer/src/hooks/useProvider.ts index 12b511d7..d25ca54a 100644 --- a/src/renderer/src/hooks/useProvider.ts +++ b/src/renderer/src/hooks/useProvider.ts @@ -1,3 +1,4 @@ +import { createSelector } from '@reduxjs/toolkit' import { useAppDispatch, useAppSelector } from '@renderer/store' import { addModel, @@ -8,8 +9,8 @@ import { updateProviders } from '@renderer/store/llm' import { Assistant, Model, Provider } from '@renderer/types' + import { useDefaultModel } from './useAssistant' -import { createSelector } from '@reduxjs/toolkit' const selectEnabledProviders = createSelector( (state) => state.llm.providers, diff --git a/src/renderer/src/hooks/useSettings.ts b/src/renderer/src/hooks/useSettings.ts index b1fec33d..d6e6d665 100644 --- a/src/renderer/src/hooks/useSettings.ts +++ b/src/renderer/src/hooks/useSettings.ts @@ -1,7 +1,7 @@ import { useAppDispatch, useAppSelector } from '@renderer/store' import { - setSendMessageShortcut as _setSendMessageShortcut, SendMessageShortcut, + setSendMessageShortcut as _setSendMessageShortcut, setTheme, ThemeMode } from '@renderer/store/settings' diff --git a/src/renderer/src/i18n/index.ts b/src/renderer/src/i18n/index.ts index ad069220..3046b3a8 100644 --- a/src/renderer/src/i18n/index.ts +++ b/src/renderer/src/i18n/index.ts @@ -1,4 +1,3 @@ -import store from '@renderer/store' import i18n from 'i18next' import { initReactI18next } from 'react-i18next' @@ -386,8 +385,4 @@ i18n.use(initReactI18next).init({ } }) -export function i18nInit() { - i18n.changeLanguage(store.getState().settings.language || 'en-US') -} - export default i18n diff --git a/src/renderer/src/init.ts b/src/renderer/src/init.ts index 8e70a2b0..ca6cbaf1 100644 --- a/src/renderer/src/init.ts +++ b/src/renderer/src/init.ts @@ -1,8 +1,9 @@ -import localforage from 'localforage' import KeyvStorage from '@kangfenmao/keyv-storage' import * as Sentry from '@sentry/electron/renderer' -import { isProduction, loadScript } from './utils' +import localforage from 'localforage' + import { ThemeMode } from './store/settings' +import { isProduction, loadScript } from './utils' async function initSentry() { if (await isProduction()) { diff --git a/src/renderer/src/main.tsx b/src/renderer/src/main.tsx index b8ff1d4e..efdbe8a8 100644 --- a/src/renderer/src/main.tsx +++ b/src/renderer/src/main.tsx @@ -1,10 +1,12 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App' import './assets/styles/index.scss' import './init' import './i18n' +import React from 'react' +import ReactDOM from 'react-dom/client' + +import App from './App' + ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( diff --git a/src/renderer/src/pages/apps/AppsPage.tsx b/src/renderer/src/pages/apps/AppsPage.tsx index 138294d5..6fdff1e9 100644 --- a/src/renderer/src/pages/apps/AppsPage.tsx +++ b/src/renderer/src/pages/apps/AppsPage.tsx @@ -1,13 +1,13 @@ import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar' +import SYSTEM_ASSISTANTS from '@renderer/config/assistants.json' +import { useAssistants } from '@renderer/hooks/useAssistant' +import { getDefaultAssistant } from '@renderer/services/assistant' +import { SystemAssistant } from '@renderer/types' import { Col, Row, Typography } from 'antd' import { find, groupBy } from 'lodash' import { FC } from 'react' -import styled from 'styled-components' -import { SystemAssistant } from '@renderer/types' -import { getDefaultAssistant } from '@renderer/services/assistant' -import { useAssistants } from '@renderer/hooks/useAssistant' import { useTranslation } from 'react-i18next' -import SYSTEM_ASSISTANTS from '@renderer/config/assistants.json' +import styled from 'styled-components' const { Title } = Typography diff --git a/src/renderer/src/pages/home/HomePage.tsx b/src/renderer/src/pages/home/HomePage.tsx index 36645ad7..e1742790 100644 --- a/src/renderer/src/pages/home/HomePage.tsx +++ b/src/renderer/src/pages/home/HomePage.tsx @@ -1,16 +1,17 @@ import { Navbar, NavbarLeft, NavbarRight } from '@renderer/components/app/Navbar' +import { isMac, isWindows } from '@renderer/config/constant' import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant' +import { useShowAssistants, useShowRightSidebar } from '@renderer/hooks/useStore' +import { useTheme } from '@renderer/providers/ThemeProvider' +import { Assistant } from '@renderer/types' +import { uuid } from '@renderer/utils' +import { Switch } from 'antd' import { FC, useState } from 'react' import styled from 'styled-components' -import Chat from './components/Chat' + import Assistants from './components/Assistants' -import { uuid } from '@renderer/utils' -import { useShowAssistants, useShowRightSidebar } from '@renderer/hooks/useStore' +import Chat from './components/Chat' import Navigation from './components/NavigationCenter' -import { isMac, isWindows } from '@renderer/config/constant' -import { Assistant } from '@renderer/types' -import { useTheme } from '@renderer/providers/ThemeProvider' -import { Switch } from 'antd' let _activeAssistant: Assistant diff --git a/src/renderer/src/pages/home/components/Assistants.tsx b/src/renderer/src/pages/home/components/Assistants.tsx index 66aa8267..ec9c5fa9 100644 --- a/src/renderer/src/pages/home/components/Assistants.tsx +++ b/src/renderer/src/pages/home/components/Assistants.tsx @@ -10,7 +10,7 @@ import { droppableReorder, uuid } from '@renderer/utils' import { Dropdown } from 'antd' import { ItemType } from 'antd/es/menu/interface' import { last } from 'lodash' -import { FC } from 'react' +import { FC, useCallback } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' @@ -22,65 +22,78 @@ interface Props { const Assistants: FC = ({ activeAssistant, setActiveAssistant, onCreateAssistant }) => { const { assistants, removeAssistant, addAssistant, updateAssistants } = useAssistants() - const { updateAssistant } = useAssistant(activeAssistant.id) const generating = useAppSelector((state) => state.runtime.generating) - + const { updateAssistant } = useAssistant(activeAssistant.id) const { t } = useTranslation() - const onDelete = (assistant: Assistant) => { - const _assistant = last(assistants.filter((a) => a.id !== assistant.id)) - _assistant ? setActiveAssistant(_assistant) : onCreateAssistant() - removeAssistant(assistant.id) - } + const onDelete = useCallback( + (assistant: Assistant) => { + const _assistant = last(assistants.filter((a) => a.id !== assistant.id)) + _assistant ? setActiveAssistant(_assistant) : onCreateAssistant() + removeAssistant(assistant.id) + }, + [assistants, onCreateAssistant, removeAssistant, setActiveAssistant] + ) - const getMenuItems = (assistant: Assistant) => - [ - { - label: t('common.edit'), - key: 'edit', - icon: , - async onClick() { - const _assistant = await AssistantSettingPopup.show({ assistant }) - updateAssistant(_assistant) + const getMenuItems = useCallback( + (assistant: Assistant) => + [ + { + label: t('common.edit'), + key: 'edit', + icon: , + async onClick() { + const _assistant = await AssistantSettingPopup.show({ assistant }) + updateAssistant(_assistant) + } + }, + { + label: t('common.duplicate'), + key: 'duplicate', + icon: , + onClick: async () => { + const _assistant: Assistant = { ...assistant, id: uuid(), topics: [getDefaultTopic()] } + addAssistant(_assistant) + setActiveAssistant(_assistant) + } + }, + { type: 'divider' }, + { + label: t('common.delete'), + key: 'delete', + icon: , + danger: true, + onClick: () => onDelete(assistant) } - }, - { - label: t('common.duplicate'), - key: 'duplicate', - icon: , - onClick: async () => { - const _assistant: Assistant = { ...assistant, id: uuid(), topics: [getDefaultTopic()] } - addAssistant(_assistant) - setActiveAssistant(_assistant) - } - }, - { type: 'divider' }, - { - label: t('common.delete'), - key: 'delete', - icon: , - danger: true, - onClick: () => onDelete(assistant) + ] as ItemType[], + [addAssistant, onDelete, setActiveAssistant, t, updateAssistant] + ) + + const onDragEnd = useCallback( + (result: DropResult) => { + if (result.destination) { + const sourceIndex = result.source.index + const destIndex = result.destination.index + const reorderAssistants = droppableReorder(assistants, sourceIndex, destIndex) + updateAssistants(reorderAssistants) } - ] as ItemType[] + }, + [assistants, updateAssistants] + ) - const onDragEnd = (result: DropResult) => { - if (result.destination) { - const sourceIndex = result.source.index - const destIndex = result.destination.index - const reorderAssistants = droppableReorder(assistants, sourceIndex, destIndex) - updateAssistants(reorderAssistants) - } - } - - const onSwitchAssistant = (assistant: Assistant) => { - if (generating) { - window.message.warning({ content: t('message.switch.disabled'), key: 'switch-assistant' }) - return - } - EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR) - setActiveAssistant(assistant) - } + const onSwitchAssistant = useCallback( + (assistant: Assistant): any => { + if (generating) { + return window.message.warning({ + content: t('message.switch.disabled'), + key: 'switch-assistant' + }) + } + EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR) + setActiveAssistant(assistant) + }, + [generating, setActiveAssistant, t] + ) return ( @@ -91,7 +104,11 @@ const Assistants: FC = ({ activeAssistant, setActiveAssistant, onCreateAs {assistants.map((assistant, index) => ( {(provided) => ( -
+
onSwitchAssistant(assistant)} @@ -130,7 +147,6 @@ const AssistantItem = styled.div` padding: 7px 10px; position: relative; border-radius: 3px; - margin-bottom: 5px; cursor: pointer; font-family: Poppins; .anticon { diff --git a/src/renderer/src/pages/home/components/Chat.tsx b/src/renderer/src/pages/home/components/Chat.tsx index 419c69bf..b713f5cd 100644 --- a/src/renderer/src/pages/home/components/Chat.tsx +++ b/src/renderer/src/pages/home/components/Chat.tsx @@ -1,12 +1,13 @@ -import { Assistant } from '@renderer/types' -import { FC } from 'react' -import styled from 'styled-components' -import Inputbar from './Inputbar' -import Messages from './Messages' -import { Flex } from 'antd' -import RightSidebar from './RightSidebar' import { useAssistant } from '@renderer/hooks/useAssistant' import { useActiveTopic } from '@renderer/hooks/useTopic' +import { Assistant } from '@renderer/types' +import { Flex } from 'antd' +import { FC } from 'react' +import styled from 'styled-components' + +import Inputbar from './input/Inputbar' +import Messages from './Messages' +import RightSidebar from './sidebar/RightSidebar' interface Props { assistant: Assistant diff --git a/src/renderer/src/pages/home/components/Message.tsx b/src/renderer/src/pages/home/components/Message.tsx index 90a0d432..66b811cb 100644 --- a/src/renderer/src/pages/home/components/Message.tsx +++ b/src/renderer/src/pages/home/components/Message.tsx @@ -21,6 +21,7 @@ import { upperFirst } from 'lodash' import { FC, memo, useCallback, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' + import Markdown from './markdown/Markdown' interface Props { diff --git a/src/renderer/src/pages/home/components/Messages.tsx b/src/renderer/src/pages/home/components/Messages.tsx index e588fa2a..35903588 100644 --- a/src/renderer/src/pages/home/components/Messages.tsx +++ b/src/renderer/src/pages/home/components/Messages.tsx @@ -1,16 +1,17 @@ +import { useAssistant } from '@renderer/hooks/useAssistant' +import { useProviderByAssistant } from '@renderer/hooks/useProvider' +import { fetchChatCompletion, fetchMessagesSummary } from '@renderer/services/api' import { EVENT_NAMES, EventEmitter } from '@renderer/services/event' +import LocalStorage from '@renderer/services/storage' import { Assistant, Message, Topic } from '@renderer/types' +import { estimateHistoryTokenCount, runAsyncFunction } from '@renderer/utils' +import { t } from 'i18next' import localforage from 'localforage' +import { debounce, reverse } from 'lodash' import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react' import styled from 'styled-components' + import MessageItem from './Message' -import { debounce, reverse } from 'lodash' -import { fetchChatCompletion, fetchMessagesSummary } from '@renderer/services/api' -import { useAssistant } from '@renderer/hooks/useAssistant' -import { estimateHistoryTokenCount, runAsyncFunction } from '@renderer/utils' -import LocalStorage from '@renderer/services/storage' -import { useProviderByAssistant } from '@renderer/hooks/useProvider' -import { t } from 'i18next' import Suggestions from './Suggestions' interface Props { diff --git a/src/renderer/src/pages/home/components/NavigationCenter.tsx b/src/renderer/src/pages/home/components/NavigationCenter.tsx index e3ee08ab..f6a1d6b1 100644 --- a/src/renderer/src/pages/home/components/NavigationCenter.tsx +++ b/src/renderer/src/pages/home/components/NavigationCenter.tsx @@ -1,18 +1,19 @@ import { CodeSandboxOutlined } from '@ant-design/icons' import { NavbarCenter } from '@renderer/components/app/Navbar' import { isMac } from '@renderer/config/constant' +import { getModelLogo } from '@renderer/config/provider' import { useAssistant } from '@renderer/hooks/useAssistant' import { useProviders } from '@renderer/hooks/useProvider' import { useShowAssistants } from '@renderer/hooks/useStore' import { Assistant } from '@renderer/types' +import { removeLeadingEmoji } from '@renderer/utils' import { Avatar, Button, Dropdown, MenuProps } from 'antd' import { first, upperFirst } from 'lodash' import { FC } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' + import { NewButton } from '../HomePage' -import { getModelLogo } from '@renderer/config/provider' -import { removeLeadingEmoji } from '@renderer/utils' interface Props { activeAssistant: Assistant diff --git a/src/renderer/src/pages/home/components/Suggestions.tsx b/src/renderer/src/pages/home/components/Suggestions.tsx index 65723aaa..bada4136 100644 --- a/src/renderer/src/pages/home/components/Suggestions.tsx +++ b/src/renderer/src/pages/home/components/Suggestions.tsx @@ -1,11 +1,11 @@ +import { fetchSuggestions } from '@renderer/services/api' import { EVENT_NAMES, EventEmitter } from '@renderer/services/event' import { Assistant, Message, Suggestion } from '@renderer/types' import { uuid } from '@renderer/utils' import dayjs from 'dayjs' import { FC, useEffect, useState } from 'react' -import styled from 'styled-components' import BeatLoader from 'react-spinners/BeatLoader' -import { fetchSuggestions } from '@renderer/services/api' +import styled from 'styled-components' interface Props { assistant: Assistant diff --git a/src/renderer/src/pages/home/components/Inputbar.tsx b/src/renderer/src/pages/home/components/input/Inputbar.tsx similarity index 99% rename from src/renderer/src/pages/home/components/Inputbar.tsx rename to src/renderer/src/pages/home/components/input/Inputbar.tsx index ba13633a..55e11a69 100644 --- a/src/renderer/src/pages/home/components/Inputbar.tsx +++ b/src/renderer/src/pages/home/components/input/Inputbar.tsx @@ -23,6 +23,7 @@ import { debounce, isEmpty } from 'lodash' import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' + import SendMessageButton from './SendMessageButton' interface Props { diff --git a/src/renderer/src/pages/home/components/SendMessageButton.tsx b/src/renderer/src/pages/home/components/input/SendMessageButton.tsx similarity index 100% rename from src/renderer/src/pages/home/components/SendMessageButton.tsx rename to src/renderer/src/pages/home/components/input/SendMessageButton.tsx index 88db4d1f..a45352b2 100644 --- a/src/renderer/src/pages/home/components/SendMessageButton.tsx +++ b/src/renderer/src/pages/home/components/input/SendMessageButton.tsx @@ -1,9 +1,9 @@ +import { ArrowUpOutlined, EnterOutlined } from '@ant-design/icons' +import { SendOutlined } from '@ant-design/icons' import { useSettings } from '@renderer/hooks/useSettings' import { Dropdown, MenuProps } from 'antd' import { FC } from 'react' -import { ArrowUpOutlined, EnterOutlined } from '@ant-design/icons' import { useTranslation } from 'react-i18next' -import { SendOutlined } from '@ant-design/icons' interface Props { sendMessage: () => void diff --git a/src/renderer/src/pages/home/components/markdown/CodeBlock.tsx b/src/renderer/src/pages/home/components/markdown/CodeBlock.tsx index 7b102635..17d67ef7 100644 --- a/src/renderer/src/pages/home/components/markdown/CodeBlock.tsx +++ b/src/renderer/src/pages/home/components/markdown/CodeBlock.tsx @@ -7,6 +7,7 @@ import { useTranslation } from 'react-i18next' import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter' import { atomDark, oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism' import styled from 'styled-components' + import Mermaid from './Mermaid' interface CodeBlockProps { diff --git a/src/renderer/src/pages/home/components/markdown/Markdown.tsx b/src/renderer/src/pages/home/components/markdown/Markdown.tsx index 970f2ca5..ad8fb52a 100644 --- a/src/renderer/src/pages/home/components/markdown/Markdown.tsx +++ b/src/renderer/src/pages/home/components/markdown/Markdown.tsx @@ -1,14 +1,16 @@ -import { FC, useCallback, useMemo } from 'react' -import ReactMarkdown from 'react-markdown' +import 'katex/dist/katex.min.css' + import { Message } from '@renderer/types' import { isEmpty } from 'lodash' +import { FC, useCallback, useMemo } from 'react' import { useTranslation } from 'react-i18next' -import CodeBlock from './CodeBlock' -import Link from './Link' +import ReactMarkdown from 'react-markdown' +import rehypeKatex from 'rehype-katex' import remarkGfm from 'remark-gfm' import remarkMath from 'remark-math' -import rehypeKatex from 'rehype-katex' -import 'katex/dist/katex.min.css' + +import CodeBlock from './CodeBlock' +import Link from './Link' interface Props { message: Message diff --git a/src/renderer/src/pages/home/components/RightSidebar.tsx b/src/renderer/src/pages/home/components/sidebar/RightSidebar.tsx similarity index 88% rename from src/renderer/src/pages/home/components/RightSidebar.tsx rename to src/renderer/src/pages/home/components/sidebar/RightSidebar.tsx index 3418e9fb..50ace29f 100644 --- a/src/renderer/src/pages/home/components/RightSidebar.tsx +++ b/src/renderer/src/pages/home/components/sidebar/RightSidebar.tsx @@ -1,11 +1,12 @@ +import { useShowRightSidebar } from '@renderer/hooks/useStore' +import { EVENT_NAMES, EventEmitter } from '@renderer/services/event' import { Assistant, Topic } from '@renderer/types' import { FC, useEffect, useState } from 'react' -import styled from 'styled-components' -import TopicsTab from './TopicsTab' -import SettingsTab from './SettingsTab' import { useTranslation } from 'react-i18next' -import { EVENT_NAMES, EventEmitter } from '@renderer/services/event' -import { useShowRightSidebar } from '@renderer/hooks/useStore' +import styled from 'styled-components' + +import SettingsTab from './SettingsTab' +import TopicsTab from './TopicsTab' interface Props { assistant: Assistant @@ -47,8 +48,12 @@ const RightSidebar: FC = (props) => { return () => unsubscribes.forEach((unsub) => unsub()) }, [hideRightSidebar, isSettingsTab, isTopicTab, rightSidebarShown, showRightSidebar]) + if (!rightSidebarShown) { + return null + } + return ( - + setTab('topic')}> {t('common.topics')} @@ -57,17 +62,20 @@ const RightSidebar: FC = (props) => { {t('settings.title')} - {tab === 'topic' && } - {tab === 'settings' && } + + {tab === 'topic' && } + {tab === 'settings' && } + ) } const Container = styled.div` + display: flex; + flex-direction: column; width: var(--topic-list-width); height: calc(100vh - var(--navbar-height)); border-left: 0.5px solid var(--color-border); - overflow-y: auto; .collapsed { width: 0; border-left: none; @@ -97,4 +105,10 @@ const Tab = styled.div` } ` +const TabContent = styled.div` + display: flex; + flex: 1; + overflow-y: auto; +` + export default RightSidebar diff --git a/src/renderer/src/pages/home/components/SettingsTab.tsx b/src/renderer/src/pages/home/components/sidebar/SettingsTab.tsx similarity index 98% rename from src/renderer/src/pages/home/components/SettingsTab.tsx rename to src/renderer/src/pages/home/components/sidebar/SettingsTab.tsx index 87332212..2666a111 100644 --- a/src/renderer/src/pages/home/components/SettingsTab.tsx +++ b/src/renderer/src/pages/home/components/sidebar/SettingsTab.tsx @@ -1,16 +1,16 @@ -import { Assistant } from '@renderer/types' -import styled from 'styled-components' +import { QuestionCircleOutlined, ReloadOutlined } from '@ant-design/icons' import { DEFAULT_CONEXTCOUNT, DEFAULT_TEMPERATURE } from '@renderer/config/constant' import { useAssistant } from '@renderer/hooks/useAssistant' +import { useSettings } from '@renderer/hooks/useSettings' +import { SettingDivider, SettingRow, SettingRowTitle, SettingSubtitle } from '@renderer/pages/settings/components' +import { useAppDispatch } from '@renderer/store' +import { setMessageFont, setShowInputEstimatedTokens, setShowMessageDivider } from '@renderer/store/settings' +import { Assistant } from '@renderer/types' import { Col, InputNumber, Row, Slider, Switch, Tooltip } from 'antd' import { debounce } from 'lodash' import { FC, useCallback, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { QuestionCircleOutlined, ReloadOutlined } from '@ant-design/icons' -import { SettingDivider, SettingRow, SettingRowTitle, SettingSubtitle } from '@renderer/pages/settings/components' -import { useSettings } from '@renderer/hooks/useSettings' -import { useAppDispatch } from '@renderer/store' -import { setMessageFont, setShowInputEstimatedTokens, setShowMessageDivider } from '@renderer/store/settings' +import styled from 'styled-components' interface Props { assistant: Assistant @@ -81,7 +81,7 @@ const SettingsTab: FC = (props) => { {t('settings.messages.model.title')}{' '} - + @@ -177,6 +177,9 @@ const SettingsTab: FC = (props) => { } const Container = styled.div` + display: flex; + flex: 1; + flex-direction: column; padding: 0 15px; ` diff --git a/src/renderer/src/pages/home/components/TopicsTab.tsx b/src/renderer/src/pages/home/components/sidebar/TopicsTab.tsx similarity index 93% rename from src/renderer/src/pages/home/components/TopicsTab.tsx rename to src/renderer/src/pages/home/components/sidebar/TopicsTab.tsx index 26ec808d..aa1d9805 100644 --- a/src/renderer/src/pages/home/components/TopicsTab.tsx +++ b/src/renderer/src/pages/home/components/sidebar/TopicsTab.tsx @@ -1,17 +1,16 @@ +import { DeleteOutlined, EditOutlined, OpenAIOutlined } from '@ant-design/icons' +import { DragDropContext, Draggable, Droppable, DropResult } from '@hello-pangea/dnd' import PromptPopup from '@renderer/components/Popups/PromptPopup' import { useAssistant } from '@renderer/hooks/useAssistant' -import { useShowRightSidebar } from '@renderer/hooks/useStore' import { fetchMessagesSummary } from '@renderer/services/api' +import LocalStorage from '@renderer/services/storage' +import { useAppSelector } from '@renderer/store' import { Assistant, Topic } from '@renderer/types' +import { droppableReorder } from '@renderer/utils' import { Dropdown, MenuProps } from 'antd' import { FC, useCallback } from 'react' -import styled from 'styled-components' -import { DeleteOutlined, EditOutlined, OpenAIOutlined } from '@ant-design/icons' -import LocalStorage from '@renderer/services/storage' -import { DragDropContext, Draggable, Droppable, DropResult } from '@hello-pangea/dnd' -import { droppableReorder } from '@renderer/utils' import { useTranslation } from 'react-i18next' -import { useAppSelector } from '@renderer/store' +import styled from 'styled-components' interface Props { assistant: Assistant @@ -20,7 +19,6 @@ interface Props { } const TopicsTab: FC = ({ assistant: _assistant, activeTopic, setActiveTopic }) => { - const { rightSidebarShown } = useShowRightSidebar() const { assistant, removeTopic, updateTopic, updateTopics } = useAssistant(_assistant.id) const { t } = useTranslation() const generating = useAppSelector((state) => state.runtime.generating) @@ -102,7 +100,7 @@ const TopicsTab: FC = ({ assistant: _assistant, activeTopic, setActiveTop ) return ( - + {(provided) => ( @@ -110,7 +108,11 @@ const TopicsTab: FC = ({ assistant: _assistant, activeTopic, setActiveTop {assistant.topics.map((topic, index) => ( {(provided) => ( -
+
= ({ assistant: _assistant, activeTopic, setActiveTop } const Container = styled.div` + display: flex; + flex: 1; + flex-direction: column; padding: 15px 10px; ` const TopicListItem = styled.div` padding: 8px 10px; - margin-bottom: 5px; cursor: pointer; border-radius: 3px; font-size: 14px; diff --git a/src/renderer/src/pages/settings/AboutSettings.tsx b/src/renderer/src/pages/settings/AboutSettings.tsx index 2367bda2..5b867ed6 100644 --- a/src/renderer/src/pages/settings/AboutSettings.tsx +++ b/src/renderer/src/pages/settings/AboutSettings.tsx @@ -1,11 +1,12 @@ -import { Avatar, Button, Progress, Row, Tag } from 'antd' -import { FC, useEffect, useState } from 'react' -import styled from 'styled-components' import Logo from '@renderer/assets/images/logo.png' import { runAsyncFunction } from '@renderer/utils' -import { useTranslation } from 'react-i18next' -import { debounce } from 'lodash' +import { Avatar, Button, Progress, Row, Tag } from 'antd' import { ProgressInfo } from 'electron-updater' +import { debounce } from 'lodash' +import { FC, useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import styled from 'styled-components' + import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from './components' const AboutSettings: FC = () => { diff --git a/src/renderer/src/pages/settings/AssistantSettings.tsx b/src/renderer/src/pages/settings/AssistantSettings.tsx index 551f46e9..b05fb77e 100644 --- a/src/renderer/src/pages/settings/AssistantSettings.tsx +++ b/src/renderer/src/pages/settings/AssistantSettings.tsx @@ -3,11 +3,12 @@ import { DEFAULT_CONEXTCOUNT, DEFAULT_TEMPERATURE } from '@renderer/config/const import { useDefaultAssistant } from '@renderer/hooks/useAssistant' import { Button, Col, Input, InputNumber, Row, Slider, Tooltip } from 'antd' import TextArea from 'antd/es/input/TextArea' +import { debounce } from 'lodash' import { FC, useCallback, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' + import { SettingContainer, SettingDivider, SettingSubtitle, SettingTitle } from './components' -import { debounce } from 'lodash' const AssistantSettings: FC = () => { const { defaultAssistant, updateDefaultAssistant } = useDefaultAssistant() diff --git a/src/renderer/src/pages/settings/GeneralSettings.tsx b/src/renderer/src/pages/settings/GeneralSettings.tsx index dfca3f7e..7500f9bc 100644 --- a/src/renderer/src/pages/settings/GeneralSettings.tsx +++ b/src/renderer/src/pages/settings/GeneralSettings.tsx @@ -1,17 +1,17 @@ -import { FC, useState } from 'react' -import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from './components' -import { Avatar, Input, Select, Upload } from 'antd' -import styled from 'styled-components' -import LocalStorage from '@renderer/services/storage' -import { compressImage, isValidProxyUrl } from '@renderer/utils' import useAvatar from '@renderer/hooks/useAvatar' +import { useSettings } from '@renderer/hooks/useSettings' +import LocalStorage from '@renderer/services/storage' import { useAppDispatch } from '@renderer/store' import { setAvatar } from '@renderer/store/runtime' -import { useSettings } from '@renderer/hooks/useSettings' import { setLanguage, setUserName, ThemeMode } from '@renderer/store/settings' -import { useTranslation } from 'react-i18next' import { setProxyUrl as _setProxyUrl } from '@renderer/store/settings' -import i18n from '@renderer/i18n' +import { compressImage, isValidProxyUrl } from '@renderer/utils' +import { Avatar, Input, Select, Upload } from 'antd' +import { FC, useState } from 'react' +import { useTranslation } from 'react-i18next' +import styled from 'styled-components' + +import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from './components' const GeneralSettings: FC = () => { const avatar = useAvatar() @@ -22,7 +22,6 @@ const GeneralSettings: FC = () => { const onSelectLanguage = (value: string) => { dispatch(setLanguage(value)) - i18n.changeLanguage(value) localStorage.setItem('language', value) } diff --git a/src/renderer/src/pages/settings/ModelSettings.tsx b/src/renderer/src/pages/settings/ModelSettings.tsx index 2fa73d6f..75d10f5d 100644 --- a/src/renderer/src/pages/settings/ModelSettings.tsx +++ b/src/renderer/src/pages/settings/ModelSettings.tsx @@ -1,12 +1,13 @@ -import { FC } from 'react' -import { SettingContainer, SettingDivider, SettingTitle } from './components' -import { Select } from 'antd' -import { useProviders } from '@renderer/hooks/useProvider' -import { useDefaultModel } from '@renderer/hooks/useAssistant' -import { find } from 'lodash' -import { Model } from '@renderer/types' -import { useTranslation } from 'react-i18next' import { EditOutlined, MessageOutlined, TranslationOutlined } from '@ant-design/icons' +import { useDefaultModel } from '@renderer/hooks/useAssistant' +import { useProviders } from '@renderer/hooks/useProvider' +import { Model } from '@renderer/types' +import { Select } from 'antd' +import { find } from 'lodash' +import { FC } from 'react' +import { useTranslation } from 'react-i18next' + +import { SettingContainer, SettingDivider, SettingTitle } from './components' const ModelSettings: FC = () => { const { defaultModel, topicNamingModel, translateModel, setDefaultModel, setTopicNamingModel, setTranslateModel } = diff --git a/src/renderer/src/pages/settings/ProviderSettings.tsx b/src/renderer/src/pages/settings/ProviderSettings.tsx index 41861cb4..c8f8e32e 100644 --- a/src/renderer/src/pages/settings/ProviderSettings.tsx +++ b/src/renderer/src/pages/settings/ProviderSettings.tsx @@ -1,16 +1,17 @@ +import { PlusOutlined } from '@ant-design/icons' +import { DeleteOutlined, EditOutlined } from '@ant-design/icons' import { DragDropContext, Draggable, Droppable, DropResult } from '@hello-pangea/dnd' -import { useAllProviders, useProviders } from '@renderer/hooks/useProvider' import { getProviderLogo } from '@renderer/config/provider' +import { useAllProviders, useProviders } from '@renderer/hooks/useProvider' import { Provider } from '@renderer/types' import { droppableReorder, generateColorFromChar, getFirstCharacter, uuid } from '@renderer/utils' import { Avatar, Button, Dropdown, MenuProps, Tag } from 'antd' import { FC, useState } from 'react' -import styled from 'styled-components' -import ProviderSetting from './components/ProviderSetting' import { useTranslation } from 'react-i18next' -import { PlusOutlined } from '@ant-design/icons' -import { DeleteOutlined, EditOutlined } from '@ant-design/icons' +import styled from 'styled-components' + import AddProviderPopup from './components/AddProviderPopup' +import ProviderSetting from './components/ProviderSetting' const ProviderSettings: FC = () => { const providers = useAllProviders() @@ -92,7 +93,11 @@ const ProviderSettings: FC = () => { {providers.map((provider, index) => ( {(provided) => ( -
+
@@ -166,7 +171,6 @@ const ProviderListItem = styled.div` flex-direction: row; align-items: center; padding: 5px 8px; - margin-bottom: 5px; width: 100%; cursor: pointer; border-radius: 5px; diff --git a/src/renderer/src/pages/settings/SettingsPage.tsx b/src/renderer/src/pages/settings/SettingsPage.tsx index 0b5d196c..c758592f 100644 --- a/src/renderer/src/pages/settings/SettingsPage.tsx +++ b/src/renderer/src/pages/settings/SettingsPage.tsx @@ -1,13 +1,14 @@ import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar' import { FC } from 'react' +import { useTranslation } from 'react-i18next' import { Link, Route, Routes, useLocation } from 'react-router-dom' import styled from 'styled-components' -import GeneralSettings from './GeneralSettings' + import AboutSettings from './AboutSettings' import AssistantSettings from './AssistantSettings' +import GeneralSettings from './GeneralSettings' import ModelSettings from './ModelSettings' import ProviderSettings from './ProviderSettings' -import { useTranslation } from 'react-i18next' const SettingsPage: FC = () => { const { pathname } = useLocation() diff --git a/src/renderer/src/pages/settings/components/EditModelsPopup.tsx b/src/renderer/src/pages/settings/components/EditModelsPopup.tsx index 6b82b491..47dac56b 100644 --- a/src/renderer/src/pages/settings/components/EditModelsPopup.tsx +++ b/src/renderer/src/pages/settings/components/EditModelsPopup.tsx @@ -1,17 +1,18 @@ import { LoadingOutlined, MinusOutlined, PlusOutlined, QuestionCircleOutlined } from '@ant-design/icons' import { SYSTEM_MODELS } from '@renderer/config/models' +import { getModelLogo } from '@renderer/config/provider' import { useProvider } from '@renderer/hooks/useProvider' import { fetchModels } from '@renderer/services/api' -import { getModelLogo } from '@renderer/config/provider' import { Model, Provider } from '@renderer/types' import { getDefaultGroupName, isFreeModel, runAsyncFunction } from '@renderer/utils' import { Avatar, Button, Empty, Flex, Modal, Tag } from 'antd' import Search from 'antd/es/input/Search' import { groupBy, isEmpty, uniqBy } from 'lodash' import { useEffect, useState } from 'react' -import styled from 'styled-components' -import { TopView } from '../../../components/TopView' import { useTranslation } from 'react-i18next' +import styled from 'styled-components' + +import { TopView } from '../../../components/TopView' interface ShowParams { provider: Provider diff --git a/src/renderer/src/pages/settings/components/ProviderSetting.tsx b/src/renderer/src/pages/settings/components/ProviderSetting.tsx index ff89730c..baa87d92 100644 --- a/src/renderer/src/pages/settings/components/ProviderSetting.tsx +++ b/src/renderer/src/pages/settings/components/ProviderSetting.tsx @@ -1,11 +1,3 @@ -import { Provider } from '@renderer/types' -import { FC, useEffect, useState } from 'react' -import styled from 'styled-components' -import { Avatar, Button, Card, Divider, Flex, Input, Space, Switch } from 'antd' -import { useProvider } from '@renderer/hooks/useProvider' -import { groupBy } from 'lodash' -import { SettingContainer, SettingSubtitle, SettingTitle } from '.' -import { getModelLogo } from '@renderer/config/provider' import { CheckOutlined, EditOutlined, @@ -14,13 +6,22 @@ import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons' +import { getModelLogo } from '@renderer/config/provider' +import { PROVIDER_CONFIG } from '@renderer/config/provider' +import { useProvider } from '@renderer/hooks/useProvider' +import { useTheme } from '@renderer/providers/ThemeProvider' +import { checkApi } from '@renderer/services/api' +import { Provider } from '@renderer/types' +import { Avatar, Button, Card, Divider, Flex, Input, Space, Switch } from 'antd' +import Link from 'antd/es/typography/Link' +import { groupBy } from 'lodash' +import { FC, useEffect, useState } from 'react' +import { useTranslation } from 'react-i18next' +import styled from 'styled-components' + +import { SettingContainer, SettingSubtitle, SettingTitle } from '.' import AddModelPopup from './AddModelPopup' import EditModelsPopup from './EditModelsPopup' -import Link from 'antd/es/typography/Link' -import { checkApi } from '@renderer/services/api' -import { useTranslation } from 'react-i18next' -import { PROVIDER_CONFIG } from '@renderer/config/provider' -import { useTheme } from '@renderer/providers/ThemeProvider' interface Props { provider: Provider diff --git a/src/renderer/src/pages/settings/components/index.tsx b/src/renderer/src/pages/settings/components/index.tsx index a57b83a1..ead68519 100644 --- a/src/renderer/src/pages/settings/components/index.tsx +++ b/src/renderer/src/pages/settings/components/index.tsx @@ -26,7 +26,7 @@ export const SettingTitle = styled.div` export const SettingSubtitle = styled.div` font-size: 14px; color: var(--color-text-2); - margin: 15px 0 10px 0; + margin: 15px 0 0 0; user-select: none; ` diff --git a/src/renderer/src/providers/AntdProvider.tsx b/src/renderer/src/providers/AntdProvider.tsx index a0afae03..b68699dd 100644 --- a/src/renderer/src/providers/AntdProvider.tsx +++ b/src/renderer/src/providers/AntdProvider.tsx @@ -2,6 +2,7 @@ import { useSettings } from '@renderer/hooks/useSettings' import { ConfigProvider, theme } from 'antd' import zhCN from 'antd/locale/zh_CN' import { FC, PropsWithChildren } from 'react' + import { useTheme } from './ThemeProvider' const AntdProvider: FC = ({ children }) => { diff --git a/src/renderer/src/services/ProviderSDK.ts b/src/renderer/src/services/ProviderSDK.ts index 3f1dce60..b12419da 100644 --- a/src/renderer/src/services/ProviderSDK.ts +++ b/src/renderer/src/services/ProviderSDK.ts @@ -1,12 +1,13 @@ -import { Assistant, Message, Provider, Suggestion } from '@renderer/types' -import OpenAI from 'openai' import Anthropic from '@anthropic-ai/sdk' -import { getDefaultModel, getTopNamingModel } from './assistant' -import { ChatCompletionCreateParamsNonStreaming, ChatCompletionMessageParam } from 'openai/resources' -import { sum, takeRight } from 'lodash' import { MessageCreateParamsNonStreaming, MessageParam } from '@anthropic-ai/sdk/resources' -import { EVENT_NAMES } from './event' +import { Assistant, Message, Provider, Suggestion } from '@renderer/types' import { getAssistantSettings, removeQuotes } from '@renderer/utils' +import { sum, takeRight } from 'lodash' +import OpenAI from 'openai' +import { ChatCompletionCreateParamsNonStreaming, ChatCompletionMessageParam } from 'openai/resources' + +import { getDefaultModel, getTopNamingModel } from './assistant' +import { EVENT_NAMES } from './event' export default class ProviderSDK { provider: Provider diff --git a/src/renderer/src/services/api.ts b/src/renderer/src/services/api.ts index eaa6a0fd..6f080058 100644 --- a/src/renderer/src/services/api.ts +++ b/src/renderer/src/services/api.ts @@ -4,6 +4,8 @@ import { setGenerating } from '@renderer/store/runtime' import { Assistant, Message, Provider, Suggestion, Topic } from '@renderer/types' import { uuid } from '@renderer/utils' import dayjs from 'dayjs' +import { isEmpty } from 'lodash' + import { getAssistantProvider, getDefaultModel, @@ -13,7 +15,6 @@ import { } from './assistant' import { EVENT_NAMES, EventEmitter } from './event' import ProviderSDK from './ProviderSDK' -import { isEmpty } from 'lodash' export async function fetchChatCompletion({ messages, diff --git a/src/renderer/src/services/assistant.ts b/src/renderer/src/services/assistant.ts index aa370c22..c106f014 100644 --- a/src/renderer/src/services/assistant.ts +++ b/src/renderer/src/services/assistant.ts @@ -1,7 +1,7 @@ -import { Assistant, Model, Provider, Topic } from '@renderer/types' -import store from '@renderer/store' -import { uuid } from '@renderer/utils' import i18n from '@renderer/i18n' +import store from '@renderer/store' +import { Assistant, Model, Provider, Topic } from '@renderer/types' +import { uuid } from '@renderer/utils' export function getDefaultAssistant(): Assistant { return { diff --git a/src/renderer/src/store/index.ts b/src/renderer/src/store/index.ts index a5643d35..7e5bbb5a 100644 --- a/src/renderer/src/store/index.ts +++ b/src/renderer/src/store/index.ts @@ -2,11 +2,12 @@ import { combineReducers, configureStore } from '@reduxjs/toolkit' import { useDispatch, useSelector, useStore } from 'react-redux' import { FLUSH, PAUSE, PERSIST, persistReducer, persistStore, PURGE, REGISTER, REHYDRATE } from 'redux-persist' import storage from 'redux-persist/lib/storage' + import assistants from './assistants' -import settings from './settings' import llm from './llm' -import runtime from './runtime' import migrate from './migrate' +import runtime from './runtime' +import settings from './settings' const rootReducer = combineReducers({ assistants, diff --git a/src/renderer/src/store/migrate.ts b/src/renderer/src/store/migrate.ts index 69bfc0e7..d35cdf6a 100644 --- a/src/renderer/src/store/migrate.ts +++ b/src/renderer/src/store/migrate.ts @@ -1,9 +1,10 @@ -import { createMigrate } from 'redux-persist' -import { RootState } from '.' import { SYSTEM_MODELS } from '@renderer/config/models' -import { isEmpty } from 'lodash' import i18n from '@renderer/i18n' import { Assistant } from '@renderer/types' +import { isEmpty } from 'lodash' +import { createMigrate } from 'redux-persist' + +import { RootState } from '.' const migrateConfig = { '2': (state: RootState) => { diff --git a/src/renderer/src/utils/index.ts b/src/renderer/src/utils/index.ts index 15e1d407..5106b364 100644 --- a/src/renderer/src/utils/index.ts +++ b/src/renderer/src/utils/index.ts @@ -1,9 +1,9 @@ -import { v4 as uuidv4 } from 'uuid' -import imageCompression from 'browser-image-compression' -import { Assistant, AssistantSettings, Message, Model } from '@renderer/types' -import { GPTTokens } from 'gpt-tokens' import { DEFAULT_CONEXTCOUNT, DEFAULT_TEMPERATURE } from '@renderer/config/constant' +import { Assistant, AssistantSettings, Message, Model } from '@renderer/types' +import imageCompression from 'browser-image-compression' +import { GPTTokens } from 'gpt-tokens' import { takeRight } from 'lodash' +import { v4 as uuidv4 } from 'uuid' export const runAsyncFunction = async (fn: () => void) => { await fn() diff --git a/yarn.lock b/yarn.lock index 70c90260..57b3de42 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3472,6 +3472,7 @@ __metadata: eslint: "npm:^8.56.0" eslint-plugin-react: "npm:^7.34.3" eslint-plugin-react-hooks: "npm:^4.6.2" + eslint-plugin-simple-import-sort: "npm:^12.1.1" eslint-plugin-unused-imports: "npm:^4.0.0" gpt-tokens: "npm:^1.3.6" i18next: "npm:^23.11.5" @@ -4698,6 +4699,15 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-simple-import-sort@npm:^12.1.1": + version: 12.1.1 + resolution: "eslint-plugin-simple-import-sort@npm:12.1.1" + peerDependencies: + eslint: ">=5.0.0" + checksum: 10c0/0ad1907ad9ddbadd1db655db0a9d0b77076e274b793a77b982c8525d808d868e6ecfce24f3a411e8a1fa551077387f9ebb38c00956073970ebd7ee6a029ce2b3 + languageName: node + linkType: hard + "eslint-plugin-unused-imports@npm:^4.0.0": version: 4.0.0 resolution: "eslint-plugin-unused-imports@npm:4.0.0"