diff --git a/src/renderer/src/assets/styles/index.scss b/src/renderer/src/assets/styles/index.scss index ce8b99e7..08c94e5d 100644 --- a/src/renderer/src/assets/styles/index.scss +++ b/src/renderer/src/assets/styles/index.scss @@ -48,8 +48,8 @@ --status-bar-height: 40px; --input-bar-height: 85px; - --assistants-width: 300px; - --topic-list-width: 300px; + --assistants-width: 280px; + --topic-list-width: 280px; --settings-width: var(--assistants-width); } diff --git a/src/renderer/src/components/Popups/AddAssistantPopup.tsx b/src/renderer/src/components/Popups/AddAssistantPopup.tsx index 78ec54bb..0a2e64a7 100644 --- a/src/renderer/src/components/Popups/AddAssistantPopup.tsx +++ b/src/renderer/src/components/Popups/AddAssistantPopup.tsx @@ -70,8 +70,8 @@ const PopupContainer: React.FC = ({ resolve }) => { open={open} onCancel={onCancel} afterClose={onClose} - transitionName="" - maskTransitionName="" + transitionName="ant-move-down" + maskTransitionName="ant-fade" footer={null}> = ({ children, ...props }) => { const { minappShow } = useRuntime() - const backgroundColor = minappShow ? 'var(--navbar-background)' : navbarBackgroundColor + const { windowStyle } = useSettings() + + const macTransparentWindow = isMac && windowStyle === 'transparent' + const navbarBgColor = macTransparentWindow ? 'var(--navbar-background-mac)' : 'var(--navbar-background)' + const backgroundColor = minappShow ? 'var(--navbar-background)' : navbarBgColor return ( @@ -39,7 +42,6 @@ const NavbarContainer = styled.div` margin-left: ${isMac ? 'calc(var(--sidebar-width) * -1)' : 0}; padding-left: ${isMac ? 'var(--sidebar-width)' : 0}; border-bottom: 0.5px solid var(--color-border); - background-color: ${navbarBackgroundColor}; transition: background-color 0.3s ease; -webkit-app-region: drag; ` diff --git a/src/renderer/src/components/app/Sidebar.tsx b/src/renderer/src/components/app/Sidebar.tsx index 0f8e5ac0..ffdc1c20 100644 --- a/src/renderer/src/components/app/Sidebar.tsx +++ b/src/renderer/src/components/app/Sidebar.tsx @@ -2,6 +2,7 @@ import { TranslationOutlined } from '@ant-design/icons' import { isMac } from '@renderer/config/constant' import { isLocalAi, UserAvatar } from '@renderer/config/env' import useAvatar from '@renderer/hooks/useAvatar' +import { useSettings } from '@renderer/hooks/useSettings' import { useRuntime, useShowAssistants } from '@renderer/hooks/useStore' import { Avatar } from 'antd' import { FC } from 'react' @@ -11,8 +12,6 @@ import styled from 'styled-components' import UserPopup from '../Popups/UserPopup' -const sidebarBackgroundColor = isMac ? 'var(--navbar-background-mac)' : 'var(--navbar-background)' - const Sidebar: FC = () => { const { pathname } = useLocation() const avatar = useAvatar() @@ -21,11 +20,15 @@ const Sidebar: FC = () => { const { generating } = useRuntime() const { t } = useTranslation() const navigate = useNavigate() + const { windowStyle } = useSettings() const isRoute = (path: string): string => (pathname === path ? 'active' : '') const onEditUser = () => UserPopup.show() + const macTransparentWindow = isMac && windowStyle === 'transparent' + const sidebarBgColor = macTransparentWindow ? 'var(--navbar-background-mac)' : 'var(--navbar-background)' + const to = (path: string) => { if (generating) { window.message.warning({ content: t('message.switch.disabled'), key: 'switch-assistant' }) @@ -39,7 +42,7 @@ const Sidebar: FC = () => { } return ( - + @@ -87,7 +90,6 @@ const Container = styled.div` -webkit-app-region: drag !important; border-right: 0.5px solid var(--color-border); margin-top: ${isMac ? 'var(--navbar-height)' : 0}; - background-color: ${sidebarBackgroundColor}; transition: background-color 0.3s ease; ` diff --git a/src/renderer/src/hooks/useSettings.ts b/src/renderer/src/hooks/useSettings.ts index d6e6d665..700ed6b0 100644 --- a/src/renderer/src/hooks/useSettings.ts +++ b/src/renderer/src/hooks/useSettings.ts @@ -3,6 +3,7 @@ import { SendMessageShortcut, setSendMessageShortcut as _setSendMessageShortcut, setTheme, + setWindowStyle, ThemeMode } from '@renderer/store/settings' @@ -17,6 +18,9 @@ export function useSettings() { }, setTheme(theme: ThemeMode) { dispatch(setTheme(theme)) + }, + setWindowStyle(windowStyle: 'transparent' | 'opaque') { + dispatch(setWindowStyle(windowStyle)) } } } diff --git a/src/renderer/src/i18n/index.ts b/src/renderer/src/i18n/index.ts index 444a3ed6..ed1d1b7d 100644 --- a/src/renderer/src/i18n/index.ts +++ b/src/renderer/src/i18n/index.ts @@ -202,6 +202,9 @@ const resources = { 'theme.dark': 'Dark', 'theme.light': 'Light', 'theme.auto': 'Auto', + 'theme.window.style.title': 'Window Style', + 'theme.window.style.transparent': 'Transparent Window', + 'theme.window.style.opaque': 'Opaque Window', 'font_size.title': 'Message Font Size' }, translate: { @@ -444,6 +447,9 @@ const resources = { 'theme.dark': '深色主题', 'theme.light': '浅色主题', 'theme.auto': '跟随系统', + 'theme.window.style.title': '窗口样式', + 'theme.window.style.transparent': '透明窗口', + 'theme.window.style.opaque': '不透明窗口', 'font_size.title': '消息字体大小' }, translate: { diff --git a/src/renderer/src/pages/home/Assistants.tsx b/src/renderer/src/pages/home/Assistants.tsx index 22ae869c..6798c728 100644 --- a/src/renderer/src/pages/home/Assistants.tsx +++ b/src/renderer/src/pages/home/Assistants.tsx @@ -106,7 +106,7 @@ const Assistants: FC = ({ if (showTopics) { return ( - + ) @@ -155,6 +155,7 @@ const AssistantItem = styled.div` position: relative; border-radius: 4px; margin: 0 10px; + padding-right: 35px; cursor: pointer; font-family: Ubuntu; .anticon { diff --git a/src/renderer/src/pages/home/HomePage.tsx b/src/renderer/src/pages/home/HomePage.tsx index c05d0ba2..c392aacb 100644 --- a/src/renderer/src/pages/home/HomePage.tsx +++ b/src/renderer/src/pages/home/HomePage.tsx @@ -64,7 +64,7 @@ const HomePage: FC = () => { {showAssistants && ( - setShowTopics(false)}> + setShowTopics(false)}> {showTopics && } {showTopics ? t('common.back') : t('common.chat')} @@ -124,16 +124,18 @@ const NavigtaionBack = styled.div` align-items: center; justify-content: flex-start; gap: 10px; - cursor: pointer; - margin-left: ${isMac ? '14px' : '2px'}; + margin-left: ${isMac ? '10px' : 0}; -webkit-app-region: none; transition: all 0.2s ease-in-out; transition: opacity 0.2s ease-in-out; - padding: 2px 8px; + padding: 3px 8px; border-radius: 6px; - &:hover { - background-color: var(--color-background-mute); - color: var(--color-text-1); + &.back { + cursor: pointer; + &:hover { + background-color: var(--color-background-mute); + color: var(--color-text-1); + } } ` @@ -172,7 +174,7 @@ export const NewButton = styled.div` font-size: 17px; } &:hover { - background-color: var(--color-background-soft); + background-color: var(--color-background-mute); cursor: pointer; color: var(--color-icon-white); } diff --git a/src/renderer/src/pages/home/Topics.tsx b/src/renderer/src/pages/home/Topics.tsx index c74d3dec..b48b850e 100644 --- a/src/renderer/src/pages/home/Topics.tsx +++ b/src/renderer/src/pages/home/Topics.tsx @@ -1,13 +1,12 @@ import { DeleteOutlined, EditOutlined, OpenAIOutlined } from '@ant-design/icons' -import { DragDropContext, Draggable, Droppable, DropResult } from '@hello-pangea/dnd' +import DragableList from '@renderer/components/DragableList' import PromptPopup from '@renderer/components/Popups/PromptPopup' import { useAssistant } from '@renderer/hooks/useAssistant' 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 { Button, Dropdown, MenuProps } from 'antd' import { FC, useCallback } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' @@ -19,7 +18,7 @@ interface Props { } const Topics: FC = ({ assistant: _assistant, activeTopic, setActiveTopic }) => { - const { assistant, removeTopic, updateTopic, updateTopics } = useAssistant(_assistant.id) + const { assistant, removeTopic, updateTopic, updateTopics, removeAllTopics } = useAssistant(_assistant.id) const { t } = useTranslation() const generating = useAppSelector((state) => state.runtime.generating) @@ -77,17 +76,6 @@ const Topics: FC = ({ assistant: _assistant, activeTopic, setActiveTopic [assistant, removeTopic, setActiveTopic, t, updateTopic] ) - const onDragEnd = useCallback( - (result: DropResult) => { - if (result.destination) { - const sourceIndex = result.source.index - const destIndex = result.destination.index - updateTopics(droppableReorder(assistant.topics, sourceIndex, destIndex)) - } - }, - [assistant.topics, updateTopics] - ) - const onSwitchTopic = useCallback( (topic: Topic) => { if (generating) { @@ -99,35 +87,35 @@ const Topics: FC = ({ assistant: _assistant, activeTopic, setActiveTopic [generating, setActiveTopic, t] ) + const onDeleteAll = () => { + window.modal.confirm({ + title: t('chat.topics.delete.all.title'), + content: t('chat.topics.delete.all.content'), + okButtonProps: { danger: true }, + onOk: removeAllTopics + }) + } + return ( - - - {(provided) => ( -
- {assistant.topics.map((topic, index) => ( - - {(provided) => ( -
- - onSwitchTopic(topic)}> - {topic.name} - - -
- )} -
- ))} -
- )} -
-
+ + {(topic) => ( + + onSwitchTopic(topic)}> + {topic.name} + + + )} + + {assistant.topics.length > 20 && ( +
+ +
+ )}
) } @@ -136,14 +124,11 @@ const Container = styled.div` display: flex; flex: 1; flex-direction: column; - overflow-y: scroll; padding-top: 10px; - padding-bottom: 10px; - margin-top: -10px; ` const TopicListItem = styled.div` - padding: 7px 10px; + padding: 6px 10px; margin: 0 10px; cursor: pointer; border-radius: 4px; @@ -151,6 +136,7 @@ const TopicListItem = styled.div` overflow: hidden; text-overflow: ellipsis; font-family: Ubuntu; + font-size: 13px; &:hover { background-color: var(--color-background-soft); } @@ -160,4 +146,10 @@ const TopicListItem = styled.div` } ` +const Footer = styled.div` + padding: 0 10px; + padding-bottom: 10px; + width: 100%; +` + export default Topics diff --git a/src/renderer/src/pages/settings/GeneralSettings.tsx b/src/renderer/src/pages/settings/GeneralSettings.tsx index ea83b61b..21e5a29d 100644 --- a/src/renderer/src/pages/settings/GeneralSettings.tsx +++ b/src/renderer/src/pages/settings/GeneralSettings.tsx @@ -1,16 +1,13 @@ import { FolderOpenOutlined, SaveOutlined } from '@ant-design/icons' import { HStack } from '@renderer/components/Layout' -import useAvatar from '@renderer/hooks/useAvatar' import { useSettings } from '@renderer/hooks/useSettings' import i18n from '@renderer/i18n' import { backup, reset, restore } from '@renderer/services/backup' -import LocalStorage from '@renderer/services/storage' import { useAppDispatch } from '@renderer/store' -import { setAvatar } from '@renderer/store/runtime' import { setLanguage, setUserName, ThemeMode } from '@renderer/store/settings' import { setProxyUrl as _setProxyUrl } from '@renderer/store/settings' -import { compressImage, isValidProxyUrl } from '@renderer/utils' -import { Avatar, Button, Input, Select, Upload } from 'antd' +import { isValidProxyUrl } from '@renderer/utils' +import { Avatar, Button, Input, Select } from 'antd' import { FC, useState } from 'react' import { useTranslation } from 'react-i18next' import styled from 'styled-components' @@ -18,8 +15,7 @@ import styled from 'styled-components' import { SettingContainer, SettingDivider, SettingRow, SettingRowTitle, SettingTitle } from '.' const GeneralSettings: FC = () => { - const avatar = useAvatar() - const { language, proxyUrl: storeProxyUrl, userName, theme, setTheme } = useSettings() + const { language, proxyUrl: storeProxyUrl, userName, theme, windowStyle, setTheme, setWindowStyle } = useSettings() const [proxyUrl, setProxyUrl] = useState(storeProxyUrl) const dispatch = useAppDispatch() const { t } = useTranslation() @@ -72,24 +68,16 @@ const GeneralSettings: FC = () => { - {t('common.avatar')} - {}} - accept="image/png, image/jpeg" - itemRender={() => null} - maxCount={1} - onChange={async ({ file }) => { - try { - const _file = file.originFileObj as File - const compressedFile = await compressImage(_file) - await LocalStorage.storeImage('avatar', compressedFile) - dispatch(setAvatar(await LocalStorage.getImage('avatar'))) - } catch (error: any) { - window.message.error(error.message) - } - }}> - - + {t('settings.theme.window.style.title')} +