mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-03 02:59:07 +08:00
refactor(App): replace TabsContainer with AppLayout for improved layout structure; integrate ChatProvider for chat context management; update routing logic in NavigationHandler to utilize SettingsPopup; adjust main height variable in styles for consistency; enhance FilesPage layout by repositioning SideNav; implement new SettingsPopup component for settings management.
This commit is contained in:
parent
bedea8aaaa
commit
db1c03f9fa
@ -5,7 +5,7 @@ import { Provider } from 'react-redux'
|
|||||||
import { HashRouter } from 'react-router-dom'
|
import { HashRouter } from 'react-router-dom'
|
||||||
import { PersistGate } from 'redux-persist/integration/react'
|
import { PersistGate } from 'redux-persist/integration/react'
|
||||||
|
|
||||||
import TabsContainer from './components/Tabs/TabsContainer'
|
import AppLayout from './components/Layout/AppLayout'
|
||||||
import TopViewContainer from './components/TopView'
|
import TopViewContainer from './components/TopView'
|
||||||
import AntdProvider from './context/AntdProvider'
|
import AntdProvider from './context/AntdProvider'
|
||||||
import { CodeStyleProvider } from './context/CodeStyleProvider'
|
import { CodeStyleProvider } from './context/CodeStyleProvider'
|
||||||
@ -13,6 +13,7 @@ import { NotificationProvider } from './context/NotificationProvider'
|
|||||||
import StyleSheetManager from './context/StyleSheetManager'
|
import StyleSheetManager from './context/StyleSheetManager'
|
||||||
import { ThemeProvider } from './context/ThemeProvider'
|
import { ThemeProvider } from './context/ThemeProvider'
|
||||||
import NavigationHandler from './handler/NavigationHandler'
|
import NavigationHandler from './handler/NavigationHandler'
|
||||||
|
import { ChatProvider } from './hooks/useChat'
|
||||||
import Routes from './Routes'
|
import Routes from './Routes'
|
||||||
|
|
||||||
function App(): React.ReactElement {
|
function App(): React.ReactElement {
|
||||||
@ -24,14 +25,16 @@ function App(): React.ReactElement {
|
|||||||
<NotificationProvider>
|
<NotificationProvider>
|
||||||
<CodeStyleProvider>
|
<CodeStyleProvider>
|
||||||
<PersistGate loading={null} persistor={persistor}>
|
<PersistGate loading={null} persistor={persistor}>
|
||||||
<TopViewContainer>
|
<HashRouter>
|
||||||
<HashRouter>
|
<TopViewContainer>
|
||||||
<NavigationHandler />
|
<NavigationHandler />
|
||||||
<TabsContainer>
|
<ChatProvider>
|
||||||
<Routes />
|
<AppLayout>
|
||||||
</TabsContainer>
|
<Routes />
|
||||||
</HashRouter>
|
</AppLayout>
|
||||||
</TopViewContainer>
|
</ChatProvider>
|
||||||
|
</TopViewContainer>
|
||||||
|
</HashRouter>
|
||||||
</PersistGate>
|
</PersistGate>
|
||||||
</CodeStyleProvider>
|
</CodeStyleProvider>
|
||||||
</NotificationProvider>
|
</NotificationProvider>
|
||||||
|
|||||||
@ -5,10 +5,8 @@ import AppsPage from './pages/apps/AppsPage'
|
|||||||
import FilesPage from './pages/files/FilesPage'
|
import FilesPage from './pages/files/FilesPage'
|
||||||
import HomePage from './pages/home/HomePage'
|
import HomePage from './pages/home/HomePage'
|
||||||
import KnowledgePage from './pages/knowledge/KnowledgePage'
|
import KnowledgePage from './pages/knowledge/KnowledgePage'
|
||||||
import LaunchpadPage from './pages/launchpad/LaunchpadPage'
|
|
||||||
import McpServersPage from './pages/mcp-servers'
|
import McpServersPage from './pages/mcp-servers'
|
||||||
import PaintingsRoutePage from './pages/paintings/PaintingsRoutePage'
|
import PaintingsRoutePage from './pages/paintings/PaintingsRoutePage'
|
||||||
import SettingsPage from './pages/settings/SettingsPage'
|
|
||||||
import TranslatePage from './pages/translate/TranslatePage'
|
import TranslatePage from './pages/translate/TranslatePage'
|
||||||
|
|
||||||
const RouteContainer = () => {
|
const RouteContainer = () => {
|
||||||
@ -22,8 +20,8 @@ const RouteContainer = () => {
|
|||||||
<Route path="/knowledge" element={<KnowledgePage />} />
|
<Route path="/knowledge" element={<KnowledgePage />} />
|
||||||
<Route path="/apps" element={<AppsPage />} />
|
<Route path="/apps" element={<AppsPage />} />
|
||||||
<Route path="/mcp-servers/*" element={<McpServersPage />} />
|
<Route path="/mcp-servers/*" element={<McpServersPage />} />
|
||||||
<Route path="/settings/*" element={<SettingsPage />} />
|
{/* <Route path="/settings/*" element={<SettingsPage />} />
|
||||||
<Route path="/launchpad" element={<LaunchpadPage />} />
|
<Route path="/launchpad" element={<LaunchpadPage />} /> */}
|
||||||
</Routes>
|
</Routes>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
--list-item-border-radius: 15px;
|
--list-item-border-radius: 15px;
|
||||||
--border-width: 0.5px;
|
--border-width: 0.5px;
|
||||||
|
|
||||||
--main-height: calc(100vh - var(--navbar-height) - 6px);
|
--main-height: 100vh;
|
||||||
|
|
||||||
--border-width: 0.5px;
|
--border-width: 0.5px;
|
||||||
}
|
}
|
||||||
|
|||||||
27
src/renderer/src/components/Layout/AppLayout.tsx
Normal file
27
src/renderer/src/components/Layout/AppLayout.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { HStack } from '@renderer/components/Layout'
|
||||||
|
import MainSidebar from '@renderer/pages/home/MainSidebar/MainSidebar'
|
||||||
|
import { FC } from 'react'
|
||||||
|
import styled from 'styled-components'
|
||||||
|
|
||||||
|
interface AppLayoutProps {
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
const AppLayout: FC<AppLayoutProps> = ({ children }) => {
|
||||||
|
return (
|
||||||
|
<HStack style={{ display: 'flex', flex: 1 }} id="app-layout">
|
||||||
|
<MainSidebar />
|
||||||
|
<ContentArea>{children}</ContentArea>
|
||||||
|
</HStack>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const ContentArea = styled.div`
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
`
|
||||||
|
|
||||||
|
export default AppLayout
|
||||||
230
src/renderer/src/components/Popups/SettingsPopup.tsx
Normal file
230
src/renderer/src/components/Popups/SettingsPopup.tsx
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
import AboutSettings from '@renderer/pages/settings/AboutSettings'
|
||||||
|
import DataSettings from '@renderer/pages/settings/DataSettings/DataSettings'
|
||||||
|
import DisplaySettings from '@renderer/pages/settings/DisplaySettings/DisplaySettings'
|
||||||
|
import GeneralSettings from '@renderer/pages/settings/GeneralSettings'
|
||||||
|
import ModelSettings from '@renderer/pages/settings/ModelSettings/ModelSettings'
|
||||||
|
import ProvidersList from '@renderer/pages/settings/ProviderSettings'
|
||||||
|
import QuickAssistantSettings from '@renderer/pages/settings/QuickAssistantSettings'
|
||||||
|
import QuickPhraseSettings from '@renderer/pages/settings/QuickPhraseSettings'
|
||||||
|
import SelectionAssistantSettings from '@renderer/pages/settings/SelectionAssistantSettings/SelectionAssistantSettings'
|
||||||
|
import ShortcutSettings from '@renderer/pages/settings/ShortcutSettings'
|
||||||
|
import WebSearchSettings from '@renderer/pages/settings/WebSearchSettings'
|
||||||
|
import { Modal, Spin } from 'antd'
|
||||||
|
import {
|
||||||
|
Cloud,
|
||||||
|
Command,
|
||||||
|
Globe,
|
||||||
|
HardDrive,
|
||||||
|
Info,
|
||||||
|
MonitorCog,
|
||||||
|
Package,
|
||||||
|
Rocket,
|
||||||
|
Settings2,
|
||||||
|
TextCursorInput,
|
||||||
|
Zap
|
||||||
|
} from 'lucide-react'
|
||||||
|
import React, { Suspense, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import styled from 'styled-components'
|
||||||
|
|
||||||
|
import { TopView } from '../TopView'
|
||||||
|
|
||||||
|
type SettingsTab =
|
||||||
|
| 'provider'
|
||||||
|
| 'model'
|
||||||
|
| 'web-search'
|
||||||
|
| 'general'
|
||||||
|
| 'display'
|
||||||
|
| 'shortcut'
|
||||||
|
| 'quickAssistant'
|
||||||
|
| 'selectionAssistant'
|
||||||
|
| 'data'
|
||||||
|
| 'about'
|
||||||
|
| 'quickPhrase'
|
||||||
|
|
||||||
|
interface SettingsPopupShowParams {
|
||||||
|
defaultTab?: SettingsTab
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props extends SettingsPopupShowParams {
|
||||||
|
resolve?: (value: any) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const SettingsPopupContainer: React.FC<Props> = ({ defaultTab = 'provider', resolve }) => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const [activeTab, setActiveTab] = useState<SettingsTab>(defaultTab)
|
||||||
|
const [open, setOpen] = useState(true)
|
||||||
|
|
||||||
|
const menuItems = [
|
||||||
|
{ key: 'provider', icon: <Cloud size={18} />, label: t('settings.provider.title') },
|
||||||
|
{ key: 'model', icon: <Package size={18} />, label: t('settings.model') },
|
||||||
|
{ key: 'web-search', icon: <Globe size={18} />, label: t('settings.websearch.title') },
|
||||||
|
{ key: 'general', icon: <Settings2 size={18} />, label: t('settings.general') },
|
||||||
|
{ key: 'display', icon: <MonitorCog size={18} />, label: t('settings.display.title') },
|
||||||
|
{ key: 'shortcut', icon: <Command size={18} />, label: t('settings.shortcuts.title') },
|
||||||
|
{ key: 'quickAssistant', icon: <Rocket size={18} />, label: t('settings.quickAssistant.title') },
|
||||||
|
{ key: 'selectionAssistant', icon: <TextCursorInput size={18} />, label: t('selection.name') },
|
||||||
|
{ key: 'quickPhrase', icon: <Zap size={18} />, label: t('settings.quickPhrase.title') },
|
||||||
|
{ key: 'data', icon: <HardDrive size={18} />, label: t('settings.data.title') },
|
||||||
|
{ key: 'about', icon: <Info size={18} />, label: t('settings.about') }
|
||||||
|
] as const
|
||||||
|
|
||||||
|
const renderContent = () => {
|
||||||
|
switch (activeTab) {
|
||||||
|
case 'provider':
|
||||||
|
return (
|
||||||
|
<Suspense fallback={<Spin />}>
|
||||||
|
<ProvidersList />
|
||||||
|
</Suspense>
|
||||||
|
)
|
||||||
|
case 'model':
|
||||||
|
return <ModelSettings />
|
||||||
|
case 'web-search':
|
||||||
|
return <WebSearchSettings />
|
||||||
|
case 'general':
|
||||||
|
return <GeneralSettings />
|
||||||
|
case 'display':
|
||||||
|
return <DisplaySettings />
|
||||||
|
case 'shortcut':
|
||||||
|
return <ShortcutSettings />
|
||||||
|
case 'quickAssistant':
|
||||||
|
return <QuickAssistantSettings />
|
||||||
|
case 'selectionAssistant':
|
||||||
|
return <SelectionAssistantSettings />
|
||||||
|
case 'data':
|
||||||
|
return <DataSettings />
|
||||||
|
case 'about':
|
||||||
|
return <AboutSettings />
|
||||||
|
case 'quickPhrase':
|
||||||
|
return <QuickPhraseSettings />
|
||||||
|
default:
|
||||||
|
return <ProvidersList />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
setOpen(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const onAfterClose = () => {
|
||||||
|
resolve && resolve(null)
|
||||||
|
TopView.hide(TopViewKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置全局隐藏方法
|
||||||
|
SettingsPopup.hide = onCancel
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledModal
|
||||||
|
title={t('settings.title')}
|
||||||
|
open={open}
|
||||||
|
onCancel={onCancel}
|
||||||
|
afterClose={onAfterClose}
|
||||||
|
footer={null}
|
||||||
|
width={1000}
|
||||||
|
centered
|
||||||
|
destroyOnClose>
|
||||||
|
<ContentContainer>
|
||||||
|
<SettingMenus>
|
||||||
|
{menuItems.map((item) => (
|
||||||
|
<MenuItem
|
||||||
|
key={item.key}
|
||||||
|
className={activeTab === item.key ? 'active' : ''}
|
||||||
|
onClick={() => setActiveTab(item.key as SettingsTab)}>
|
||||||
|
{item.icon}
|
||||||
|
{item.label}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</SettingMenus>
|
||||||
|
<SettingContent>{renderContent()}</SettingContent>
|
||||||
|
</ContentContainer>
|
||||||
|
</StyledModal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const TopViewKey = 'SettingsPopup'
|
||||||
|
|
||||||
|
export default class SettingsPopup {
|
||||||
|
static hide() {
|
||||||
|
TopView.hide(TopViewKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
static show(props: SettingsPopupShowParams = {}) {
|
||||||
|
return new Promise<any>((resolve) => {
|
||||||
|
TopView.show(<SettingsPopupContainer {...props} resolve={resolve} />, TopViewKey)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const StyledModal = styled(Modal)`
|
||||||
|
.ant-modal-content {
|
||||||
|
height: 80vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-modal-body {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const ContentContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
`
|
||||||
|
|
||||||
|
const SettingMenus = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: var(--settings-width);
|
||||||
|
border-right: 0.5px solid var(--color-border);
|
||||||
|
padding: 10px;
|
||||||
|
user-select: none;
|
||||||
|
background: var(--color-background);
|
||||||
|
`
|
||||||
|
|
||||||
|
const MenuItem = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: var(--list-item-border-radius);
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
border: 0.5px solid transparent;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
|
||||||
|
.anticon {
|
||||||
|
font-size: 16px;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 18px;
|
||||||
|
opacity: 0.7;
|
||||||
|
margin-left: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--color-background-soft);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: var(--color-background-soft);
|
||||||
|
border: 0.5px solid var(--color-border);
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const SettingContent = styled.div`
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
flex: 1;
|
||||||
|
overflow: auto;
|
||||||
|
`
|
||||||
@ -1,15 +1,12 @@
|
|||||||
|
import SettingsPopup from '@renderer/components/Popups/SettingsPopup'
|
||||||
import NavigationService from '@renderer/services/NavigationService'
|
import NavigationService from '@renderer/services/NavigationService'
|
||||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
import { useAppSelector } from '@renderer/store'
|
||||||
import { addTab, Tab } from '@renderer/store/tabs'
|
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { useHotkeys } from 'react-hotkeys-hook'
|
import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
|
||||||
const NavigationHandler: React.FC = () => {
|
const NavigationHandler: React.FC = () => {
|
||||||
const dispatch = useAppDispatch()
|
|
||||||
const location = useLocation()
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const tabs = useAppSelector((state) => state.tabs.tabs)
|
|
||||||
|
|
||||||
const showSettingsShortcutEnabled = useAppSelector(
|
const showSettingsShortcutEnabled = useAppSelector(
|
||||||
(state) => state.shortcuts.shortcuts.find((s) => s.key === 'show_settings')?.enabled
|
(state) => state.shortcuts.shortcuts.find((s) => s.key === 'show_settings')?.enabled
|
||||||
@ -22,10 +19,7 @@ const NavigationHandler: React.FC = () => {
|
|||||||
useHotkeys(
|
useHotkeys(
|
||||||
'meta+, ! ctrl+,',
|
'meta+, ! ctrl+,',
|
||||||
function () {
|
function () {
|
||||||
if (location.pathname.startsWith('/settings')) {
|
SettingsPopup.show({ defaultTab: 'provider' })
|
||||||
return
|
|
||||||
}
|
|
||||||
navigate('/settings/provider')
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
splitKey: '!',
|
splitKey: '!',
|
||||||
@ -35,20 +29,6 @@ const NavigationHandler: React.FC = () => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// 初始化 home tab
|
|
||||||
useEffect(() => {
|
|
||||||
if (tabs.length === 0) {
|
|
||||||
const homeTab: Tab = {
|
|
||||||
id: 'home',
|
|
||||||
titleKey: 'title.home',
|
|
||||||
title: '',
|
|
||||||
path: '/',
|
|
||||||
iconType: 'home'
|
|
||||||
}
|
|
||||||
dispatch(addTab(homeTab))
|
|
||||||
}
|
|
||||||
}, [dispatch, tabs.length])
|
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||||
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||||
import { loadTopicMessagesThunk } from '@renderer/store/thunk/messageThunk'
|
import { loadTopicMessagesThunk } from '@renderer/store/thunk/messageThunk'
|
||||||
import { Assistant } from '@renderer/types'
|
import { Assistant, Topic } from '@renderer/types'
|
||||||
import { Topic } from '@renderer/types'
|
import { createContext, use, useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import { use, useEffect, useMemo, useState } from 'react'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
import { createContext } from 'react'
|
|
||||||
|
|
||||||
import { useTopicsForAssistant } from './useAssistant'
|
import { useTopicsForAssistant } from './useAssistant'
|
||||||
import { useSettings } from './useSettings'
|
import { useSettings } from './useSettings'
|
||||||
@ -20,14 +19,25 @@ const ChatContext = createContext<ChatContextType | null>(null)
|
|||||||
|
|
||||||
export const ChatProvider = ({ children }) => {
|
export const ChatProvider = ({ children }) => {
|
||||||
const assistants = useAppSelector((state) => state.assistants.assistants)
|
const assistants = useAppSelector((state) => state.assistants.assistants)
|
||||||
const [activeAssistant, setActiveAssistant] = useState<Assistant>(assistants[0])
|
const [activeAssistant, setActiveAssistantBase] = useState<Assistant>(assistants[0])
|
||||||
const topics = useTopicsForAssistant(activeAssistant.id)
|
const topics = useTopicsForAssistant(activeAssistant.id)
|
||||||
const [activeTopic, setActiveTopic] = useState<Topic>(topics[0])
|
const [activeTopic, setActiveTopic] = useState<Topic>(topics[0])
|
||||||
const { clickAssistantToShowTopic } = useSettings()
|
const { clickAssistantToShowTopic } = useSettings()
|
||||||
const dispatch = useAppDispatch()
|
const dispatch = useAppDispatch()
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const location = useLocation()
|
||||||
|
|
||||||
console.log('activeAssistant', activeAssistant)
|
// 包装setActiveAssistant以添加导航逻辑
|
||||||
console.log('activeTopic', activeTopic)
|
const setActiveAssistant = useCallback(
|
||||||
|
(assistant: Assistant) => {
|
||||||
|
setActiveAssistantBase(assistant)
|
||||||
|
// 如果当前不在聊天页面,导航到聊天页面
|
||||||
|
if (location.pathname !== '/') {
|
||||||
|
navigate('/')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[setActiveAssistantBase, location.pathname, navigate]
|
||||||
|
)
|
||||||
|
|
||||||
// 当 topics 变化时,如果当前 activeTopic 不在 topics 中,设置第一个 topic
|
// 当 topics 变化时,如果当前 activeTopic 不在 topics 中,设置第一个 topic
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -58,7 +68,7 @@ export const ChatProvider = ({ children }) => {
|
|||||||
EventEmitter.on(EVENT_NAMES.SET_TOPIC, setActiveTopic)
|
EventEmitter.on(EVENT_NAMES.SET_TOPIC, setActiveTopic)
|
||||||
]
|
]
|
||||||
return () => subscriptions.forEach((subscription) => subscription())
|
return () => subscriptions.forEach((subscription) => subscription())
|
||||||
}, [])
|
}, [setActiveAssistant])
|
||||||
|
|
||||||
const value = useMemo(
|
const value = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
@ -67,7 +77,7 @@ export const ChatProvider = ({ children }) => {
|
|||||||
setActiveAssistant,
|
setActiveAssistant,
|
||||||
setActiveTopic
|
setActiveTopic
|
||||||
}),
|
}),
|
||||||
[activeAssistant, activeTopic]
|
[activeAssistant, activeTopic, setActiveAssistant]
|
||||||
)
|
)
|
||||||
|
|
||||||
return <ChatContext value={value}>{children}</ChatContext>
|
return <ChatContext value={value}>{children}</ChatContext>
|
||||||
|
|||||||
@ -134,17 +134,6 @@ const FilesPage: FC = () => {
|
|||||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('files.title')}</NavbarCenter>
|
<NavbarCenter style={{ borderRight: 'none' }}>{t('files.title')}</NavbarCenter>
|
||||||
</NavbarMain>
|
</NavbarMain>
|
||||||
<ContentContainer id="content-container">
|
<ContentContainer id="content-container">
|
||||||
<SideNav>
|
|
||||||
{menuItems.map((item) => (
|
|
||||||
<ListItem
|
|
||||||
key={item.key}
|
|
||||||
icon={item.icon}
|
|
||||||
title={item.label}
|
|
||||||
active={fileType === item.key}
|
|
||||||
onClick={() => setFileType(item.key as FileTypes)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</SideNav>
|
|
||||||
<MainContent>
|
<MainContent>
|
||||||
<SortContainer>
|
<SortContainer>
|
||||||
<Flex gap={8} align="center">
|
<Flex gap={8} align="center">
|
||||||
@ -207,6 +196,17 @@ const FilesPage: FC = () => {
|
|||||||
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
||||||
)}
|
)}
|
||||||
</MainContent>
|
</MainContent>
|
||||||
|
<SideNav>
|
||||||
|
{menuItems.map((item) => (
|
||||||
|
<ListItem
|
||||||
|
key={item.key}
|
||||||
|
icon={item.icon}
|
||||||
|
title={item.label}
|
||||||
|
active={fileType === item.key}
|
||||||
|
onClick={() => setFileType(item.key as FileTypes)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</SideNav>
|
||||||
</ContentContainer>
|
</ContentContainer>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -122,7 +122,7 @@ const Chat: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Main = styled(Flex)`
|
const Main = styled(Flex)`
|
||||||
height: calc(100vh - var(--navbar-height) - 50px);
|
height: calc(100vh - var(--navbar-height));
|
||||||
transform: translateZ(0);
|
transform: translateZ(0);
|
||||||
position: relative;
|
position: relative;
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,12 +1,9 @@
|
|||||||
import { HStack } from '@renderer/components/Layout'
|
|
||||||
import { ChatProvider } from '@renderer/hooks/useChat'
|
|
||||||
import { useSettings } from '@renderer/hooks/useSettings'
|
import { useSettings } from '@renderer/hooks/useSettings'
|
||||||
import { FC, useEffect } from 'react'
|
import { FC, useEffect } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import Chat from './Chat'
|
import Chat from './Chat'
|
||||||
import ChatNavbar from './ChatNavbar'
|
import ChatNavbar from './ChatNavbar'
|
||||||
import MainSidebar from './MainSidebar/MainSidebar'
|
|
||||||
|
|
||||||
const HomePage: FC<{ style?: React.CSSProperties }> = ({ style }) => {
|
const HomePage: FC<{ style?: React.CSSProperties }> = ({ style }) => {
|
||||||
const { showAssistants, showTopics, topicPosition } = useSettings()
|
const { showAssistants, showTopics, topicPosition } = useSettings()
|
||||||
@ -20,17 +17,12 @@ const HomePage: FC<{ style?: React.CSSProperties }> = ({ style }) => {
|
|||||||
}, [showAssistants, showTopics, topicPosition])
|
}, [showAssistants, showTopics, topicPosition])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChatProvider>
|
<Container style={style}>
|
||||||
<HStack style={{ display: 'flex', flex: 1 }} id="home-page">
|
<ChatNavbar />
|
||||||
<MainSidebar />
|
<ContentContainer id="content-container">
|
||||||
<Container style={style}>
|
<Chat />
|
||||||
<ChatNavbar />
|
</ContentContainer>
|
||||||
<ContentContainer id="content-container">
|
</Container>
|
||||||
<Chat />
|
|
||||||
</ContentContainer>
|
|
||||||
</Container>
|
|
||||||
</HStack>
|
|
||||||
</ChatProvider>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -56,6 +56,7 @@ export const Container = styled.div<{ transparent?: boolean }>`
|
|||||||
min-height: var(--main-height);
|
min-height: var(--main-height);
|
||||||
background: var(--color-background);
|
background: var(--color-background);
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
|
margin-top: 50px;
|
||||||
`
|
`
|
||||||
|
|
||||||
export const MainMenu = styled.div`
|
export const MainMenu = styled.div`
|
||||||
|
|||||||
@ -96,6 +96,13 @@ const KnowledgePage: FC = () => {
|
|||||||
<NavbarCenter style={{ borderRight: 'none' }}>{t('knowledge.title')}</NavbarCenter>
|
<NavbarCenter style={{ borderRight: 'none' }}>{t('knowledge.title')}</NavbarCenter>
|
||||||
</NavbarMain>
|
</NavbarMain>
|
||||||
<ContentContainer id="content-container">
|
<ContentContainer id="content-container">
|
||||||
|
{bases.length === 0 ? (
|
||||||
|
<MainContent>
|
||||||
|
<Empty description={t('knowledge.empty')} image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
||||||
|
</MainContent>
|
||||||
|
) : selectedBase ? (
|
||||||
|
<KnowledgeContent selectedBase={selectedBase} />
|
||||||
|
) : null}
|
||||||
<SideNav>
|
<SideNav>
|
||||||
<ScrollContainer>
|
<ScrollContainer>
|
||||||
<DragableList
|
<DragableList
|
||||||
@ -128,13 +135,6 @@ const KnowledgePage: FC = () => {
|
|||||||
<div style={{ minHeight: '10px' }}></div>
|
<div style={{ minHeight: '10px' }}></div>
|
||||||
</ScrollContainer>
|
</ScrollContainer>
|
||||||
</SideNav>
|
</SideNav>
|
||||||
{bases.length === 0 ? (
|
|
||||||
<MainContent>
|
|
||||||
<Empty description={t('knowledge.empty')} image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
|
||||||
</MainContent>
|
|
||||||
) : selectedBase ? (
|
|
||||||
<KnowledgeContent selectedBase={selectedBase} />
|
|
||||||
) : null}
|
|
||||||
</ContentContainer>
|
</ContentContainer>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user