Compare commits

..

2 Commits

21 changed files with 112 additions and 156 deletions

View File

@@ -14,8 +14,13 @@ import StyleSheetManager from './context/StyleSheetManager'
import { ThemeProvider } from './context/ThemeProvider'
import NavigationHandler from './handler/NavigationHandler'
import DiscoverPage from './pages/discover'
import FilesPage from './pages/files/FilesPage'
import HomePage from './pages/home/HomePage'
import KnowledgePage from './pages/knowledge/KnowledgePage'
import McpServersPage from './pages/mcp-servers'
import PaintingsRoutePage from './pages/paintings/PaintingsRoutePage'
import SettingsPage from './pages/settings/SettingsPage'
import TranslatePage from './pages/translate/TranslatePage'
function App(): React.ReactElement {
return (
@@ -33,12 +38,12 @@ function App(): React.ReactElement {
<Routes>
<Route path="/" element={<HomePage />} />
{/* <Route path="/agents" element={<AgentsPage />} /> */}
{/* <Route path="/paintings/*" element={<PaintingsRoutePage />} /> */}
{/* <Route path="/translate" element={<TranslatePage />} /> */}
{/* <Route path="/files" element={<FilesPage />} /> */}
{/* <Route path="/knowledge" element={<KnowledgePage />} /> */}
<Route path="/paintings/*" element={<PaintingsRoutePage />} />
<Route path="/translate" element={<TranslatePage />} />
<Route path="/files" element={<FilesPage />} />
<Route path="/knowledge" element={<KnowledgePage />} />
{/* <Route path="/apps" element={<AppsPage />} /> */}
{/* <Route path="/mcp-servers/*" element={<McpServersPage />} /> */}
<Route path="/mcp-servers/*" element={<McpServersPage />} />
<Route path="/settings/*" element={<SettingsPage />} />
<Route path="/discover/*" element={<DiscoverPage />} />
</Routes>

View File

@@ -66,9 +66,9 @@
--settings-width: 250px;
--scrollbar-width: 5px;
--chat-background: #111111;
--chat-background-user: #28b561;
--chat-background-assistant: #2c2c2c;
--chat-background: transparent;
--chat-background-user: #232325;
--chat-background-assistant: transparent;
--chat-text-user: var(--color-black);
--list-item-border-radius: 8px;
@@ -133,9 +133,9 @@
--navbar-background-mac: rgba(255, 255, 255, 0.55);
--navbar-background: rgba(244, 244, 244);
--chat-background: #f3f3f3;
--chat-background-user: #95ec69;
--chat-background-assistant: #ffffff;
--chat-background: transparent;
--chat-background-user: #f3f3f3;
--chat-background-assistant: transparent;
--chat-text-user: var(--color-text);
--border-width: 0.5px;

View File

@@ -119,32 +119,21 @@ ul {
#messages {
background-color: var(--chat-background);
}
#inputbar {
margin: -5px 15px 15px 15px;
background: var(--color-background);
}
.system-prompt {
background-color: var(--chat-background-assistant);
}
.message-content-container {
margin: 5px 0;
border-radius: 8px;
padding: 10px 15px 0 15px;
}
.message-thought-container {
margin-top: 8px;
}
.message-user {
color: var(--chat-text-user);
.markdown,
.anticon,
.iconfont,
.lucide,
.message-tokens {
color: var(--chat-text-user) !important;
}
.message-action-button:hover {
background-color: var(--color-white-soft);
.message-content-container {
margin: 5px 0;
border-radius: 8px 0 8px 8px;
padding: 10px 15px 0 15px;
}
}
.group-grid-container.horizontal,

View File

@@ -1,6 +1,6 @@
import './assets/styles/tailwind.css'
import './assets/styles/index.scss'
import '@ant-design/v5-patch-for-react-19'
import './assets/styles/tailwind.css'
import { createRoot } from 'react-dom/client'

View File

@@ -1,9 +1,10 @@
import { Category } from '@renderer/types/cherryStore'
import React, { Suspense } from 'react'
import React from 'react'
import { Navigate, Route, Routes, useLocation } from 'react-router-dom'
// 实际的 AgentsPage 组件 - 请确保路径正确
import { discoverRouters } from '../routers'
import AgentsPage from '../../agents/AgentsPage'
import AppsPage from '../../apps/AppsPage'
// import AssistantDetailsPage from '../../agents/AssistantDetailsPage'; // 示例详情页
// 其他分类的页面组件 (如果需要)
@@ -31,16 +32,14 @@ const DiscoverContent: React.FC<DiscoverContentProps> = ({ activeTabId, currentC
}
return (
<Suspense fallback={<div>Loading...</div>}>
<Routes>
{discoverRouters.map((_Route) => {
if (!_Route.component) return null
return <Route key={_Route.path} path={`/${_Route.path}`} element={<_Route.component />} />
})}
<Routes>
{/* Path for Assistant category */}
<Route path="assistant" element={<AgentsPage />} />
{/* Path for Mini-App category */}
<Route path="mini-app" element={<AppsPage />} />
<Route path="*" element={<div>Discover Feature Not Found at {location.pathname}</div>} />
</Routes>
</Suspense>
<Route path="*" element={<div>Discover Feature Not Found at {location.pathname}</div>} />
</Routes>
)
}

View File

@@ -1,9 +1,7 @@
import { Category } from '@renderer/types/cherryStore'
import { Category, CherryStoreType } from '@renderer/types/cherryStore'
import { useEffect, useMemo, useState } from 'react'
import { useLocation, useNavigate } from 'react-router-dom'
import { discoverRouters } from '../routers'
// Extended Category type for internal use in hook, including path and sidebar flag
// Export this interface so other files can import it
export interface InternalCategory extends Category {
@@ -12,14 +10,23 @@ export interface InternalCategory extends Category {
}
// Initial category data with path and hasSidebar
const initialCategories: InternalCategory[] = discoverRouters.map((router) => ({
id: router.id,
title: router.title,
path: router.path,
hasSidebar: !router.component,
// 目前没有需要二级分类的分类
items: []
}))
const initialCategories: InternalCategory[] = [
{
id: CherryStoreType.ASSISTANT,
title: 'Assistants',
path: 'assistant',
hasSidebar: false,
items: []
},
{
id: CherryStoreType.MINI_APP,
title: 'Mini Apps',
path: 'mini-app',
hasSidebar: false,
items: []
}
// Add more categories as needed
]
// Helper to find category by path
const findCategoryByPath = (path: string | undefined): InternalCategory | undefined =>

View File

@@ -1,44 +0,0 @@
import i18n from '@renderer/i18n'
import { CherryStoreType } from '@renderer/types/cherryStore'
import { lazy } from 'react'
export const discoverRouters = [
{
id: CherryStoreType.ASSISTANT,
title: i18n.t('assistants.title'),
path: 'assistant',
component: lazy(() => import('../agents/AgentsPage'))
},
{
id: CherryStoreType.MINI_APP,
title: i18n.t('minapp.title'),
path: 'mini-app',
component: lazy(() => import('../apps/AppsPage'))
},
{
id: CherryStoreType.TRANSLATE,
title: i18n.t('translate.title'),
path: 'translate',
component: lazy(() => import('../translate/TranslatePage'))
},
{
id: CherryStoreType.FILES,
title: i18n.t('files.title'),
path: 'files',
component: lazy(() => import('../files/FilesPage'))
},
{
id: CherryStoreType.PAINTINGS,
title: i18n.t('paintings.title'),
path: 'paintings/*',
isPrefix: true,
component: lazy(() => import('../paintings/PaintingsRoutePage'))
},
{
id: CherryStoreType.MCP_SERVER,
title: i18n.t('common.mcp'),
path: 'mcp-servers/*',
isPrefix: true,
component: lazy(() => import('../mcp-servers'))
}
]

View File

@@ -5,6 +5,7 @@ import {
SortAscendingOutlined,
SortDescendingOutlined
} from '@ant-design/icons'
import { NavbarCenter, NavbarMain } from '@renderer/components/app/Navbar'
import ListItem from '@renderer/components/ListItem'
import TextEditPopup from '@renderer/components/Popups/TextEditPopup'
import Logger from '@renderer/config/logger'
@@ -206,9 +207,9 @@ const FilesPage: FC = () => {
return (
<Container>
{/* <NavbarMain>
<NavbarMain>
<NavbarCenter style={{ borderRight: 'none' }}>{t('files.title')}</NavbarCenter>
</NavbarMain> */}
</NavbarMain>
<ContentContainer id="content-container">
<SideNav>
{menuItems.map((item) => (

View File

@@ -132,10 +132,7 @@ const Chat: FC<Props> = (props) => {
}
const Container = styled.div`
display: flex;
flex-direction: row;
height: 100%;
flex: 1;
`
const Main = styled(Flex)`

View File

@@ -68,15 +68,13 @@ const HomePage: FC = () => {
}
const Container = styled.div`
min-width: 0;
display: flex;
flex: 1;
flex-direction: column;
`
const ContentContainer = styled.div`
display: flex;
flex: 1;
flex-direction: row;
overflow: hidden;
`

View File

@@ -912,7 +912,7 @@ const InputBarContainer = styled.div`
border: 0.5px solid var(--color-border);
transition: all 0.2s ease;
position: relative;
margin: 14px 20px;
margin: 16px 16px;
margin-top: 0;
border-radius: 15px;
padding-top: 6px; // 为拖动手柄留出空间

View File

@@ -217,7 +217,7 @@ const MessageContainer = styled.div`
flex-direction: column;
position: relative;
transition: background-color 0.3s ease;
padding: 0 20px;
padding: 0 24px;
transform: translateZ(0);
will-change: transform;
&.message-highlight {

View File

@@ -168,7 +168,9 @@ const MessageGroup = ({ messages, topic, registerMessageElement }: Props) => {
topic,
index: message.index,
style: {
paddingTop: isGrouped && ['horizontal', 'grid'].includes(multiModelMessageStyle) ? 0 : 15
...(isGrouped && ['horizontal', 'grid'].includes(multiModelMessageStyle)
? { padding: 0 }
: { paddingTop: 15 })
}
}
@@ -202,7 +204,10 @@ const MessageGroup = ({ messages, topic, registerMessageElement }: Props) => {
</MessageWrapper>
}
trigger={gridPopoverTrigger}
styles={{ root: { maxWidth: '60vw', minWidth: '550px', overflowY: 'auto', zIndex: 1000 } }}>
styles={{
root: { maxWidth: '60vw', minWidth: '550px', overflowY: 'auto', zIndex: 1000 },
body: { padding: 2 }
}}>
<div style={{ cursor: 'pointer' }}>{messageContent}</div>
</Popover>
)
@@ -259,7 +264,7 @@ const GroupContainer = styled.div<{ $isGrouped: boolean; $layout: MultiModelMess
padding-top: ${({ $isGrouped, $layout }) => ($isGrouped && 'horizontal' === $layout ? '15px' : '0')};
&.group-container.horizontal,
&.group-container.grid {
padding: 0 20px;
padding: 0 24px;
.message {
padding: 0;
}
@@ -317,10 +322,10 @@ const MessageWrapper = styled(Scrollbar)<MessageWrapperProps>`
width: 100%;
&.horizontal {
display: inline-block;
height: 100%;
}
&.grid {
display: inline-block;
height: 100%;
}
&.fold {
display: none;
@@ -333,10 +338,9 @@ const MessageWrapper = styled(Scrollbar)<MessageWrapperProps>`
if ($layout === 'horizontal' && $isGrouped) {
return css`
border: 0.5px solid var(--color-border);
padding: 10px;
padding: 10px 10px 0 10px;
border-radius: 6px;
max-height: 600px;
margin-bottom: 10px;
`
}
return ''

View File

@@ -104,7 +104,7 @@ const GroupMenuBar = styled.div<{ $layout: MultiModelMessageStyle }>`
margin: 0 20px;
padding: 6px 10px;
border-radius: 6px;
margin-top: 10px;
margin-top: 6px;
justify-content: space-between;
overflow: hidden;
border: 0.5px solid var(--color-border);

View File

@@ -81,7 +81,7 @@ const InstallNpxUv: FC<Props> = ({ mini = false }) => {
icon={installed ? <CheckCircleOutlined /> : <WarningOutlined />}
className="nodrag"
color={installed ? 'green' : 'danger'}
onClick={() => navigate('mcp-install')}
onClick={() => navigate('/mcp-servers/mcp-install')}
/>
)
}

View File

@@ -36,7 +36,7 @@ const McpServersList: FC = () => {
isActive: false
}
addMCPServer(newServer)
navigate(`settings`, { state: { server: newServer } })
navigate(`/mcp-servers/settings`, { state: { server: newServer } })
window.message.success({ content: t('settings.mcp.addSuccess'), key: 'mcp-list' })
}, [addMCPServer, navigate, t])
@@ -119,7 +119,7 @@ const McpServersList: FC = () => {
</ListHeader>
<DragableList style={{ width: '100%' }} list={mcpServers} onUpdate={updateMcpServers}>
{(server: MCPServer) => (
<ServerCard key={server.id} onClick={() => navigate(`settings`, { state: { server } })}>
<ServerCard key={server.id} onClick={() => navigate(`/mcp-servers/settings`, { state: { server } })}>
<ServerHeader>
<ServerName>
{server.logoUrl && <ServerLogo src={server.logoUrl} alt={`${server.name} logo`} />}
@@ -148,7 +148,7 @@ const McpServersList: FC = () => {
<Button
icon={<Settings2 size={16} />}
type="text"
onClick={() => navigate(`settings`, { state: { server } })}
onClick={() => navigate(`/mcp-servers/settings`, { state: { server } })}
/>
</StatusIndicator>
</ServerHeader>

View File

@@ -75,7 +75,7 @@ export const McpSettingsNavbar = () => {
<Button
size="small"
type="text"
onClick={() => navigate('npx-search')}
onClick={() => navigate('/mcp-servers/npx-search')}
icon={<Search size={14} />}
className="nodrag"
style={{ fontSize: 13, height: 28, borderRadius: 20 }}>

View File

@@ -1,10 +1,11 @@
import { ArrowLeftOutlined } from '@ant-design/icons'
import { NavbarCenter, NavbarMain } from '@renderer/components/app/Navbar'
import { HStack } from '@renderer/components/Layout'
import { useTheme } from '@renderer/context/ThemeProvider'
import { SettingContainer } from '@renderer/pages/settings'
import { Button } from 'antd'
import { FC } from 'react'
// import { useTranslation } from 'react-i18next'
import { useTranslation } from 'react-i18next'
import { Route, Routes, useLocation } from 'react-router'
import { Link } from 'react-router-dom'
import styled from 'styled-components'
@@ -17,32 +18,31 @@ import NpxSearch from './NpxSearch'
const McpServersPage: FC = () => {
const { theme } = useTheme()
// const { t } = useTranslation()
const { t } = useTranslation()
const location = useLocation()
const pathname = location.pathname
const isHome = pathname.includes('*')
const isHome = pathname === '/mcp-servers'
return (
<Container theme={theme} style={{ padding: 0, position: 'relative' }}>
{/* <NavbarMain> */}
{/* <NavbarCenter style={{ borderRight: 'none' }}> */}
<div className="flex">
<HStack alignItems="center" gap={10}>
{/* {t('common.mcp')} */}
{!isHome && (
<Link to="*">
<Button type="default" icon={<ArrowLeftOutlined />} shape="circle" size="small" className="nodrag" />
</Link>
)}
</HStack>
{/* </NavbarCenter> */}
<McpSettingsNavbar />
</div>
{/* </NavbarMain> */}
<NavbarMain>
<NavbarCenter style={{ borderRight: 'none' }}>
<HStack alignItems="center" gap={10}>
{t('common.mcp')}
{!isHome && (
<Link to="/mcp-servers">
<Button type="default" icon={<ArrowLeftOutlined />} shape="circle" size="small" className="nodrag" />
</Link>
)}
</HStack>
</NavbarCenter>
{pathname.includes('/mcp-servers') && <McpSettingsNavbar />}
</NavbarMain>
<MainContainer id="content-container">
<Routes>
<Route path="*" element={<McpServersList />} />
<Route path="/" element={<McpServersList />} />
<Route path="settings" element={<McpSettings />} />
<Route
path="npx-search"

View File

@@ -1,8 +1,10 @@
import { RedoOutlined } from '@ant-design/icons'
import { PlusOutlined, RedoOutlined } from '@ant-design/icons'
import IcImageUp from '@renderer/assets/images/paintings/ic_ImageUp.svg'
import { NavbarCenter, NavbarMain, NavbarRight } from '@renderer/components/app/Navbar'
import { HStack } from '@renderer/components/Layout'
import Scrollbar from '@renderer/components/Scrollbar'
import TranslateButton from '@renderer/components/TranslateButton'
import { isMac } from '@renderer/config/constant'
import { getProviderLogo } from '@renderer/config/providers'
import { useTheme } from '@renderer/context/ThemeProvider'
import { usePaintings } from '@renderer/hooks/usePaintings'
@@ -17,7 +19,7 @@ import { setGenerating } from '@renderer/store/runtime'
import type { FileType } from '@renderer/types'
import type { PaintingAction, PaintingsState } from '@renderer/types'
import { getErrorMessage, uuid } from '@renderer/utils'
import { Avatar, Input, InputNumber, Radio, Segmented, Select, Slider, Switch, Tooltip, Upload } from 'antd'
import { Avatar, Button, Input, InputNumber, Radio, Segmented, Select, Slider, Switch, Tooltip, Upload } from 'antd'
import TextArea from 'antd/es/input/TextArea'
import { Info } from 'lucide-react'
import type { FC } from 'react'
@@ -783,7 +785,7 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
return (
<Container>
{/* <NavbarMain>
<NavbarMain>
<NavbarCenter style={{ borderRight: 'none' }}>{t('paintings.title')}</NavbarCenter>
{isMac && (
<NavbarRight style={{ justifyContent: 'flex-end' }}>
@@ -792,7 +794,7 @@ const AihubmixPage: FC<{ Options: string[] }> = ({ Options }) => {
</Button>
</NavbarRight>
)}
</NavbarMain> */}
</NavbarMain>
<ContentContainer id="content-container">
<LeftContainer>
<ProviderTitleContainer>

View File

@@ -1,4 +1,5 @@
import { CheckOutlined, DeleteOutlined, HistoryOutlined, SendOutlined } from '@ant-design/icons'
import { NavbarCenter, NavbarMain } from '@renderer/components/app/Navbar'
import CopyIcon from '@renderer/components/Icons/CopyIcon'
import { HStack } from '@renderer/components/Layout'
import { isEmbeddingModel } from '@renderer/config/models'
@@ -430,19 +431,19 @@ const TranslatePage: FC = () => {
return (
<Container id="translate-page">
{/* <NavbarMain> */}
{/* <NavbarCenter> */}
{/* {t('translate.title')} */}
<Button
className="nodrag"
color="default"
variant={historyDrawerVisible ? 'filled' : 'text'}
type="text"
icon={<HistoryOutlined />}
onClick={() => setHistoryDrawerVisible(!historyDrawerVisible)}
/>
{/* </NavbarCenter> */}
{/* </NavbarMain> */}
<NavbarMain>
<NavbarCenter>
{t('translate.title')}
<Button
className="nodrag"
color="default"
variant={historyDrawerVisible ? 'filled' : 'text'}
type="text"
icon={<HistoryOutlined />}
onClick={() => setHistoryDrawerVisible(!historyDrawerVisible)}
/>
</NavbarCenter>
</NavbarMain>
<ContentContainer id="content-container" ref={contentContainerRef} $historyDrawerVisible={historyDrawerVisible}>
<HistoryContainner $historyDrawerVisible={historyDrawerVisible}>
<OperationBar>

View File

@@ -4,10 +4,7 @@ export enum CherryStoreType {
KNOWLEDGE = 'Knowledge',
MCP_SERVER = 'MCP-Server',
MODEL_PROVIDER = 'Model-Provider',
AGENT = 'Agent',
TRANSLATE = 'Translate',
PAINTINGS = 'Paintings',
FILES = 'Files'
AGENT = 'Agent'
}
export interface CherryStoreBaseItem {
id: string