feat: add show or hide assistant sidebar
This commit is contained in:
parent
a0c147ae3f
commit
f434fe1231
@ -12,7 +12,7 @@
|
|||||||
--color-white-mute: #f2f2f2;
|
--color-white-mute: #f2f2f2;
|
||||||
|
|
||||||
--color-black: #1b1b1f;
|
--color-black: #1b1b1f;
|
||||||
--color-black-soft: #303030;
|
--color-black-soft: #262626;
|
||||||
--color-black-mute: #363636;
|
--color-black-mute: #363636;
|
||||||
|
|
||||||
--color-gray-1: #515c67;
|
--color-gray-1: #515c67;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||||
import { toggleRightSidebar } from '@renderer/store/settings'
|
import { toggleRightSidebar, toggleShowAssistants } from '@renderer/store/settings'
|
||||||
|
|
||||||
export function useShowRightSidebar() {
|
export function useShowRightSidebar() {
|
||||||
const showRightSidebar = useAppSelector((state) => state.settings.showRightSidebar)
|
const showRightSidebar = useAppSelector((state) => state.settings.showRightSidebar)
|
||||||
@ -7,6 +7,16 @@ export function useShowRightSidebar() {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
showRightSidebar,
|
showRightSidebar,
|
||||||
setShowRightSidebar: () => dispatch(toggleRightSidebar())
|
toggleRightSidebar: () => dispatch(toggleRightSidebar())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useShowAssistants() {
|
||||||
|
const showAssistants = useAppSelector((state) => state.settings.showAssistants)
|
||||||
|
const dispatch = useAppDispatch()
|
||||||
|
|
||||||
|
return {
|
||||||
|
showAssistants,
|
||||||
|
toggleShowAssistants: () => dispatch(toggleShowAssistants())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,15 +5,17 @@ import styled from 'styled-components'
|
|||||||
import Chat from './components/Chat'
|
import Chat from './components/Chat'
|
||||||
import Assistants from './components/Assistants'
|
import Assistants from './components/Assistants'
|
||||||
import { uuid } from '@renderer/utils'
|
import { uuid } from '@renderer/utils'
|
||||||
import { useShowRightSidebar } from '@renderer/hooks/useStore'
|
import { useShowAssistants, useShowRightSidebar } from '@renderer/hooks/useStore'
|
||||||
import { Tooltip } from 'antd'
|
import { Tooltip } from 'antd'
|
||||||
import Navigation from './components/Navigation'
|
import Navigation from './components/Navigation'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { PlusSquareOutlined } from '@ant-design/icons'
|
||||||
|
|
||||||
const HomePage: FC = () => {
|
const HomePage: FC = () => {
|
||||||
const { assistants, addAssistant } = useAssistants()
|
const { assistants, addAssistant } = useAssistants()
|
||||||
const [activeAssistant, setActiveAssistant] = useState(assistants[0])
|
const [activeAssistant, setActiveAssistant] = useState(assistants[0])
|
||||||
const { showRightSidebar, setShowRightSidebar } = useShowRightSidebar()
|
const { showRightSidebar, toggleRightSidebar } = useShowRightSidebar()
|
||||||
|
const { showAssistants, toggleShowAssistants } = useShowAssistants()
|
||||||
const { defaultAssistant } = useDefaultAssistant()
|
const { defaultAssistant } = useDefaultAssistant()
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
@ -26,29 +28,36 @@ const HomePage: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Navbar>
|
<Navbar>
|
||||||
<NavbarLeft style={{ justifyContent: 'flex-end', borderRight: 'none' }}>
|
{showAssistants && (
|
||||||
<NewButton onClick={onCreateAssistant}>
|
<NavbarLeft style={{ justifyContent: 'space-between', borderRight: 'none', padding: '0 8px' }}>
|
||||||
<i className="iconfont icon-a-addchat"></i>
|
<NewButton onClick={toggleShowAssistants} style={{ marginLeft: 8 }}>
|
||||||
</NewButton>
|
<i className="iconfont icon-hidesidebarhoriz" />
|
||||||
</NavbarLeft>
|
</NewButton>
|
||||||
|
<NewButton onClick={onCreateAssistant}>
|
||||||
|
<PlusSquareOutlined />
|
||||||
|
</NewButton>
|
||||||
|
</NavbarLeft>
|
||||||
|
)}
|
||||||
<Navigation activeAssistant={activeAssistant} />
|
<Navigation activeAssistant={activeAssistant} />
|
||||||
<NavbarRight style={{ justifyContent: 'flex-end', padding: 5 }}>
|
<NavbarRight style={{ justifyContent: 'flex-end', padding: 5 }}>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
placement="left"
|
placement="left"
|
||||||
title={showRightSidebar ? t('assistant.topics.hide_topics') : t('assistant.topics.show_topics')}
|
title={showRightSidebar ? t('assistant.topics.hide_topics') : t('assistant.topics.show_topics')}
|
||||||
arrow>
|
arrow>
|
||||||
<NewButton onClick={setShowRightSidebar}>
|
<NewButton onClick={toggleRightSidebar}>
|
||||||
<i className={`iconfont ${showRightSidebar ? 'icon-showsidebarhoriz' : 'icon-hidesidebarhoriz'}`} />
|
<i className={`iconfont ${showRightSidebar ? 'icon-showsidebarhoriz' : 'icon-hidesidebarhoriz'}`} />
|
||||||
</NewButton>
|
</NewButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</NavbarRight>
|
</NavbarRight>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
<ContentContainer>
|
<ContentContainer>
|
||||||
<Assistants
|
{showAssistants && (
|
||||||
activeAssistant={activeAssistant}
|
<Assistants
|
||||||
setActiveAssistant={setActiveAssistant}
|
activeAssistant={activeAssistant}
|
||||||
onCreateAssistant={onCreateAssistant}
|
setActiveAssistant={setActiveAssistant}
|
||||||
/>
|
onCreateAssistant={onCreateAssistant}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Chat assistant={activeAssistant} />
|
<Chat assistant={activeAssistant} />
|
||||||
</ContentContainer>
|
</ContentContainer>
|
||||||
</Container>
|
</Container>
|
||||||
@ -59,33 +68,31 @@ const Container = styled.div`
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: calc(100vh - var(--navbar-height));
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const ContentContainer = styled.div`
|
const ContentContainer = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
height: 100%;
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const NewButton = styled.div`
|
export const NewButton = styled.div`
|
||||||
-webkit-app-region: none;
|
-webkit-app-region: none;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
width: 34px;
|
width: 28px;
|
||||||
height: 34px;
|
height: 28px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
transition: all 0.2s ease-in-out;
|
transition: all 0.2s ease-in-out;
|
||||||
color: var(--color-icon);
|
color: var(--color-icon);
|
||||||
.iconfont {
|
.anticon {
|
||||||
font-size: 22px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
.icon-showsidebarhoriz,
|
.icon-showsidebarhoriz,
|
||||||
.icon-hidesidebarhoriz {
|
.icon-hidesidebarhoriz {
|
||||||
font-size: 18px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--color-background-soft);
|
background-color: var(--color-background-soft);
|
||||||
|
|||||||
@ -7,6 +7,9 @@ import { Button, Dropdown, MenuProps } from 'antd'
|
|||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
import { NewButton } from '../HomePage'
|
||||||
|
import { useShowAssistants } from '@renderer/hooks/useStore'
|
||||||
|
import { capitalizeFirstLetter } from '@renderer/utils'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
activeAssistant: Assistant
|
activeAssistant: Assistant
|
||||||
@ -17,6 +20,7 @@ const Navigation: FC<Props> = ({ activeAssistant }) => {
|
|||||||
const { model, setModel } = useAssistant(activeAssistant.id)
|
const { model, setModel } = useAssistant(activeAssistant.id)
|
||||||
const { providers } = useProviders()
|
const { providers } = useProviders()
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const { showAssistants, toggleShowAssistants } = useShowAssistants()
|
||||||
|
|
||||||
const items: MenuProps['items'] = providers
|
const items: MenuProps['items'] = providers
|
||||||
.filter((p) => p.models.length > 0)
|
.filter((p) => p.models.length > 0)
|
||||||
@ -33,12 +37,17 @@ const Navigation: FC<Props> = ({ activeAssistant }) => {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavbarCenter style={{ border: 'none', padding: '0 15px' }}>
|
<NavbarCenter style={{ border: 'none', paddingLeft: showAssistants ? 8 : 16 }}>
|
||||||
{assistant?.name}
|
{!showAssistants && (
|
||||||
|
<NewButton onClick={toggleShowAssistants} style={{ marginRight: 8 }}>
|
||||||
|
<i className="iconfont icon-showsidebarhoriz" />
|
||||||
|
</NewButton>
|
||||||
|
)}
|
||||||
|
<AssistantName>{assistant?.name}</AssistantName>
|
||||||
<DropdownMenu menu={{ items, style: { maxHeight: '80vh', overflow: 'auto' } }} trigger={['click']}>
|
<DropdownMenu menu={{ items, style: { maxHeight: '80vh', overflow: 'auto' } }} trigger={['click']}>
|
||||||
<Button size="small" type="primary" ghost style={{ fontSize: '11px' }}>
|
<DropdownButton size="small" type="primary" ghost>
|
||||||
{model ? model.name : t('button.select_model')}
|
{model ? capitalizeFirstLetter(model.name) : t('button.select_model')}
|
||||||
</Button>
|
</DropdownButton>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</NavbarCenter>
|
</NavbarCenter>
|
||||||
)
|
)
|
||||||
@ -49,4 +58,15 @@ const DropdownMenu = styled(Dropdown)`
|
|||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const AssistantName = styled.span`
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 5px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const DropdownButton = styled(Button)`
|
||||||
|
font-size: 10px;
|
||||||
|
border-radius: 15px;
|
||||||
|
padding: 0 8px;
|
||||||
|
`
|
||||||
|
|
||||||
export default Navigation
|
export default Navigation
|
||||||
|
|||||||
@ -19,7 +19,7 @@ const persistedReducer = persistReducer(
|
|||||||
{
|
{
|
||||||
key: 'cherry-studio',
|
key: 'cherry-studio',
|
||||||
storage,
|
storage,
|
||||||
version: 13,
|
version: 14,
|
||||||
blacklist: ['runtime'],
|
blacklist: ['runtime'],
|
||||||
migrate
|
migrate
|
||||||
},
|
},
|
||||||
|
|||||||
@ -243,6 +243,16 @@ const migrate = createMigrate({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
// @ts-ignore store type is unknown
|
||||||
|
'14': (state: RootState) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
settings: {
|
||||||
|
...state.settings,
|
||||||
|
showAssistants: true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -4,12 +4,14 @@ export type SendMessageShortcut = 'Enter' | 'Shift+Enter'
|
|||||||
|
|
||||||
export interface SettingsState {
|
export interface SettingsState {
|
||||||
showRightSidebar: boolean
|
showRightSidebar: boolean
|
||||||
|
showAssistants: boolean
|
||||||
sendMessageShortcut: SendMessageShortcut
|
sendMessageShortcut: SendMessageShortcut
|
||||||
language: string
|
language: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: SettingsState = {
|
const initialState: SettingsState = {
|
||||||
showRightSidebar: true,
|
showRightSidebar: true,
|
||||||
|
showAssistants: true,
|
||||||
sendMessageShortcut: 'Enter',
|
sendMessageShortcut: 'Enter',
|
||||||
language: navigator.language
|
language: navigator.language
|
||||||
}
|
}
|
||||||
@ -21,6 +23,9 @@ const settingsSlice = createSlice({
|
|||||||
toggleRightSidebar: (state) => {
|
toggleRightSidebar: (state) => {
|
||||||
state.showRightSidebar = !state.showRightSidebar
|
state.showRightSidebar = !state.showRightSidebar
|
||||||
},
|
},
|
||||||
|
toggleShowAssistants: (state) => {
|
||||||
|
state.showAssistants = !state.showAssistants
|
||||||
|
},
|
||||||
setSendMessageShortcut: (state, action: PayloadAction<SendMessageShortcut>) => {
|
setSendMessageShortcut: (state, action: PayloadAction<SendMessageShortcut>) => {
|
||||||
state.sendMessageShortcut = action.payload
|
state.sendMessageShortcut = action.payload
|
||||||
},
|
},
|
||||||
@ -30,6 +35,6 @@ const settingsSlice = createSlice({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export const { toggleRightSidebar, setSendMessageShortcut, setLanguage } = settingsSlice.actions
|
export const { toggleRightSidebar, toggleShowAssistants, setSendMessageShortcut, setLanguage } = settingsSlice.actions
|
||||||
|
|
||||||
export default settingsSlice.reducer
|
export default settingsSlice.reducer
|
||||||
|
|||||||
@ -198,3 +198,8 @@ export function estimateHistoryTokenCount(assistant: Assistant, msgs: Message[])
|
|||||||
|
|
||||||
return all.usedTokens - 7
|
return all.usedTokens - 7
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 首字母大写
|
||||||
|
export const capitalizeFirstLetter = (str: string) => {
|
||||||
|
return str.charAt(0).toUpperCase() + str.slice(1)
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user