Merge remote-tracking branch 'origin/feat/sidebar' into feat/cherry-store-render

This commit is contained in:
MyPrototypeWhat 2025-06-09 17:49:42 +08:00
commit f2c52dfe89
17 changed files with 181 additions and 261 deletions

View File

@ -11,13 +11,13 @@ if (isDev) {
export const DATA_PATH = getDataPath()
export const titleBarOverlayDark = {
height: 40,
height: 42,
color: 'rgba(255,255,255,0)',
symbolColor: '#fff'
}
export const titleBarOverlayLight = {
height: 40,
height: 42,
color: 'rgba(255,255,255,0)',
symbolColor: '#000'
}

View File

@ -56,14 +56,14 @@ export class WindowService {
minHeight: 600,
show: false,
autoHideMenuBar: true,
transparent: isMac,
transparent: false,
vibrancy: 'sidebar',
visualEffectState: 'active',
titleBarStyle: 'hidden',
titleBarOverlay: nativeTheme.shouldUseDarkColors ? titleBarOverlayDark : titleBarOverlayLight,
backgroundColor: isMac ? undefined : nativeTheme.shouldUseDarkColors ? '#181818' : '#FFFFFF',
darkTheme: nativeTheme.shouldUseDarkColors,
trafficLightPosition: { x: 15, y: 12 },
trafficLightPosition: { x: 12, y: 12 },
...(isLinux ? { icon } : {}),
webPreferences: {
preload: join(__dirname, '../preload/index.js'),

View File

@ -29,7 +29,7 @@
--color-text-secondary: rgba(235, 235, 245, 0.7);
--color-icon: #ffffff99;
--color-icon-white: #ffffff;
--color-border: #000;
--color-border: #383838;
--color-border-soft: #ffffff10;
--color-border-mute: #ffffff05;
--color-error: #f44336;
@ -56,7 +56,7 @@
--navbar-background-mac: rgba(20, 20, 20, 0.55);
--navbar-background: #1f1f1f;
--navbar-height: 45px;
--navbar-height: 42px;
--sidebar-width: 50px;
--status-bar-height: 40px;
--input-bar-height: 100px;

View File

@ -1,16 +1,27 @@
import { isMac } from '@renderer/config/constant'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import { Tooltip } from 'antd'
import { t } from 'i18next'
import { MessageSquareDiff } from 'lucide-react'
import { MessageSquareDiff, Search } from 'lucide-react'
import { FC } from 'react'
import styled from 'styled-components'
import SearchPopup from '../Popups/SearchPopup'
interface Props {}
const HeaderNavbar: FC<Props> = () => {
return (
<Container>
<div></div>
<div>
{!isMac && (
<Tooltip title={t('chat.assistant.search.placeholder')} mouseEnterDelay={0.8}>
<NarrowIcon onClick={() => SearchPopup.show()}>
<Search size={18} />
</NarrowIcon>
</Tooltip>
)}
</div>
<Tooltip title={t('settings.shortcuts.new_topic')} mouseEnterDelay={0.8}>
<NavbarIcon onClick={() => EventEmitter.emit(EVENT_NAMES.ADD_NEW_TOPIC)} style={{ marginRight: 5 }}>
<MessageSquareDiff size={18} />
@ -32,6 +43,7 @@ const Container = styled.div`
min-height: var(--navbar-height);
background-color: transparent;
-webkit-app-region: drag;
padding-left: ${isMac ? '75px' : '0'};
`
export const NavbarIcon = styled.div`
@ -69,4 +81,10 @@ export const NavbarIcon = styled.div`
}
`
const NarrowIcon = styled(NavbarIcon)`
@media (max-width: 1000px) {
display: none;
}
`
export default HeaderNavbar

View File

@ -15,14 +15,13 @@ import {
Bot,
ChevronDown,
ChevronRight,
Compass,
FileSearch,
Folder,
Languages,
LayoutGrid,
MessageSquare,
Moon,
Palette,
Sparkle,
SquareTerminal,
Sun,
SunMoon
@ -48,7 +47,6 @@ const MainSidebar: FC = () => {
const [isAppMenuExpanded, setIsAppMenuExpanded] = useState(false)
const location = useLocation()
const state = location.state
const { pathname } = location
const { activeAssistant, activeTopic, setActiveAssistant, setActiveTopic } = useChat()
@ -59,10 +57,9 @@ const MainSidebar: FC = () => {
}, [navigate])
useEffect(() => {
state?.assistant && setActiveAssistant(state?.assistant)
state?.topic && setActiveTopic(state?.topic)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [state])
const unsubscribe = EventEmitter.on(EVENT_NAMES.SHOW_TOPIC_SIDEBAR, () => setTab('topic'))
return () => unsubscribe()
}, [])
useEffect(() => {
const unsubscribe = EventEmitter.on(EVENT_NAMES.SWITCH_ASSISTANT, (assistantId: string) => {
@ -78,7 +75,7 @@ const MainSidebar: FC = () => {
}, [assistants, setActiveAssistant])
useEffect(() => {
const canMinimize = topicPosition == 'left' ? !showAssistants : !showAssistants && !showTopics
const canMinimize = !showAssistants && !showTopics
window.api.window.setMinimumSize(canMinimize ? 520 : 1080, 600)
return () => {
@ -86,6 +83,10 @@ const MainSidebar: FC = () => {
}
}, [showAssistants, showTopics, topicPosition])
useEffect(() => {
setIsAppMenuExpanded(false)
}, [activeAssistant.id, activeTopic.id])
const onAvatarClick = () => {
navigate('/settings/provider')
}
@ -96,14 +97,15 @@ const MainSidebar: FC = () => {
}
const appMenuItems = [
{ icon: <Sparkle size={18} className="icon" />, text: t('agents.title'), path: '/agents' },
// { icon: <Sparkle size={18} className="icon" />, text: t('agents.title'), path: '/agents' },
{ icon: <Compass size={18} className="icon" />, text: t('discover.title'), path: '/discover' },
{ icon: <Languages size={18} className="icon" />, text: t('translate.title'), path: '/translate' },
{
icon: <Palette size={18} className="icon" />,
text: t('paintings.title'),
path: `/paintings/${defaultPaintingProvider}`
},
{ icon: <LayoutGrid size={18} className="icon" />, text: t('minapp.title'), path: '/apps' },
// { icon: <LayoutGrid size={18} className="icon" />, text: t('minapp.title'), path: '/apps' },
{ icon: <FileSearch size={18} className="icon" />, text: t('knowledge.title'), path: '/knowledge' },
{ icon: <SquareTerminal size={18} className="icon" />, text: t('common.mcp'), path: '/mcp-servers' },
{ icon: <Folder size={18} className="icon" />, text: t('files.title'), path: '/files' }
@ -111,10 +113,6 @@ const MainSidebar: FC = () => {
const isRoutes = (path: string): boolean => pathname.startsWith(path)
if (location.pathname !== '/') {
return null
}
const onChageTab = (tab: Tab) => {
setTab(tab)
setIsAppMenuExpanded(false)
@ -124,6 +122,10 @@ const MainSidebar: FC = () => {
return null
}
if (location.pathname !== '/') {
return null
}
return (
<Container id="main-sidebar">
<MainNavbar />
@ -187,7 +189,6 @@ const MainSidebar: FC = () => {
activeTopic={activeTopic}
setActiveAssistant={setActiveAssistant}
setActiveTopic={setActiveTopic}
position="left"
/>
<UserMenu onClick={onAvatarClick}>
<UserMenuLeft>

View File

@ -1,7 +1,7 @@
import { isLinux, isMac, isWindows } from '@renderer/config/constant'
import { useFullscreen } from '@renderer/hooks/useFullscreen'
import { Button } from 'antd'
import { X } from 'lucide-react'
import { ChevronDown, X } from 'lucide-react'
import type { FC, PropsWithChildren } from 'react'
import type { HTMLAttributes } from 'react'
import { useNavigate } from 'react-router-dom'
@ -28,16 +28,46 @@ export const NavbarRight: FC<Props> = ({ children, ...props }) => {
export const NavbarMain: FC<Props> = ({ children, ...props }) => {
const isFullscreen = useFullscreen()
const navigate = useNavigate()
return (
<NavbarMainContainer {...props} $isFullscreen={isFullscreen}>
<CloseIconWindows />
{children}
<Button type="text" icon={<X size={18} />} onClick={() => navigate('/')} className="nodrag"></Button>
<CloseIconMac />
</NavbarMainContainer>
)
}
const CloseIconMac = () => {
const navigate = useNavigate()
if (!isMac) {
return null
}
return <Button type="text" icon={<X size={18} />} onClick={() => navigate('/')} className="nodrag" />
}
const CloseIconWindows = () => {
const navigate = useNavigate()
if (isMac) {
return null
}
return (
<Button
size="small"
type="default"
shape="circle"
icon={<ChevronDown size={16} />}
onClick={() => navigate('/')}
className="nodrag"
style={{ marginRight: 5 }}
/>
)
}
const NavbarContainer = styled.div`
min-width: 100%;
display: flex;

View File

@ -47,7 +47,7 @@ As [role name], with [list skills], strictly adhering to [list constraints], usi
`
export const SUMMARIZE_PROMPT =
"You are an assistant skilled in conversation. You need to summarize the user's conversation into a title within 10 words. The language of the title should be consistent with the user's primary language. Do not use punctuation marks or other special symbols"
"You are an assistant skilled in conversation. You need to summarize the user's conversation into a title within 10 words. The language of the title should be consistent with the user's primary language. Do not use punctuation marks, markdown language markers, or other special symbols"
// https://github.com/ItzCrazyKns/Perplexica/blob/master/src/lib/prompts/webSearch.ts
export const SEARCH_SUMMARY_PROMPT = `

View File

@ -4,15 +4,16 @@ import { setActiveAssistant, setActiveTopic } from '@renderer/store/runtime'
import { loadTopicMessagesThunk } from '@renderer/store/thunk/messageThunk'
import { Assistant } from '@renderer/types'
import { Topic } from '@renderer/types'
import { find } from 'lodash'
import { useEffect } from 'react'
import { useAssistants } from './useAssistant'
import { useSettings } from './useSettings'
export const useChat = () => {
const { assistants } = useAssistants()
const activeAssistant = useAppSelector((state) => state.runtime.chat.activeAssistant) || assistants[0]
const activeTopic = useAppSelector((state) => state.runtime.chat.activeTopic) || activeAssistant?.topics[0]!
const { clickAssistantToShowTopic } = useSettings()
const dispatch = useAppDispatch()
useEffect(() => {
@ -23,11 +24,15 @@ export const useChat = () => {
}, [activeTopic, dispatch])
useEffect(() => {
// activeTopic not in assistant.topics
if (activeAssistant && !find(activeAssistant.topics, { id: activeTopic?.id })) {
dispatch(setActiveTopic(activeAssistant.topics[0]))
const firstTopic = activeAssistant.topics[0]
firstTopic && dispatch(setActiveTopic(firstTopic))
}, [activeAssistant, dispatch])
useEffect(() => {
if (clickAssistantToShowTopic) {
EventEmitter.emit(EVENT_NAMES.SHOW_TOPIC_SIDEBAR)
}
}, [activeTopic?.id, activeAssistant, dispatch])
}, [clickAssistantToShowTopic, activeAssistant])
return {
activeAssistant,

View File

@ -1,4 +1,4 @@
import { Navbar, NavbarCenter } from '@renderer/components/app/Navbar'
import { NavbarCenter, NavbarMain } from '@renderer/components/app/Navbar'
// import { useRuntime } from '@renderer/hooks/useRuntime' // No longer needed if resourcesPath is not used
import { Tabs as VercelTabs } from '@renderer/ui/vercel-tabs'
import { useEffect } from 'react'
@ -45,9 +45,9 @@ export default function DiscoverPage() {
return (
<div className="h-full w-full">
<div className="flex h-full w-full flex-col overflow-hidden">
<Navbar className="h-auto flex-shrink-0">
<NavbarMain className="h-auto flex-shrink-0">
<NavbarCenter>{t('discover.title')}</NavbarCenter>
</Navbar>
</NavbarMain>
{categories.length > 0 && (
<div className="px-4 py-2">

View File

@ -1,6 +1,5 @@
import { Navbar } from '@renderer/components/app/Navbar'
import { HStack } from '@renderer/components/Layout'
import FloatingSidebar from '@renderer/components/Popups/FloatingSidebar'
import MinAppsPopover from '@renderer/components/Popups/MinAppsPopover'
import SearchPopup from '@renderer/components/Popups/SearchPopup'
import { isLinux, isMac, isWindows } from '@renderer/config/constant'
@ -13,11 +12,11 @@ import { useShowAssistants, useShowTopics } from '@renderer/hooks/useStore'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import { useAppDispatch } from '@renderer/store'
import { setNarrowMode } from '@renderer/store/settings'
import { Assistant, Topic } from '@renderer/types'
import { Assistant } from '@renderer/types'
import { Tooltip } from 'antd'
import { t } from 'i18next'
import { LayoutGrid, PanelLeftClose, PanelRightClose, Search } from 'lucide-react'
import { FC, useCallback, useState } from 'react'
import { LayoutGrid, PanelLeft, PanelRight, Search } from 'lucide-react'
import { FC, useCallback } from 'react'
import styled from 'styled-components'
import SelectModelButton from './components/SelectModelButton'
@ -25,27 +24,22 @@ import UpdateAppButton from './components/UpdateAppButton'
interface Props {
activeAssistant: Assistant
activeTopic: Topic
setActiveTopic: (topic: Topic) => void
setActiveAssistant: (assistant: Assistant) => void
position: 'left' | 'right'
}
const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTopic, setActiveTopic }) => {
const ChatNavbar: FC<Props> = ({ activeAssistant }) => {
const { assistant } = useAssistant(activeAssistant.id)
const { showAssistants, toggleShowAssistants } = useShowAssistants()
const isFullscreen = useFullscreen()
const { topicPosition, sidebarIcons, narrowMode } = useSettings()
const { showTopics, toggleShowTopics } = useShowTopics()
const { toggleShowTopics } = useShowTopics()
const dispatch = useAppDispatch()
const [sidebarHideCooldown, setSidebarHideCooldown] = useState(false)
// Function to toggle assistants with cooldown
const handleToggleShowAssistants = useCallback(() => {
if (showAssistants) {
// When hiding sidebar, set cooldown
toggleShowAssistants()
setSidebarHideCooldown(true)
// setTimeout(() => {
// setSidebarHideCooldown(false)
// }, 10000) // 10 seconds cooldown
@ -55,20 +49,6 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
}
}, [showAssistants, toggleShowAssistants])
const handleToggleShowTopics = useCallback(() => {
if (showTopics) {
// When hiding sidebar, set cooldown
toggleShowTopics()
setSidebarHideCooldown(true)
// setTimeout(() => {
// setSidebarHideCooldown(false)
// }, 10000) // 10 seconds cooldown
} else {
// When showing sidebar, no cooldown needed
toggleShowTopics()
}
}, [showTopics, toggleShowTopics])
useShortcut('toggle_show_assistants', handleToggleShowAssistants)
useShortcut('toggle_show_topics', () => {
@ -95,17 +75,19 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
<NavbarIcon
onClick={() => toggleShowAssistants()}
style={{ marginRight: 8, marginLeft: isMac && !isFullscreen ? 4 : -12 }}>
{showAssistants ? <PanelLeftClose size={18} /> : <PanelRightClose size={18} />}
{showAssistants ? <PanelLeft size={18} /> : <PanelRight size={18} />}
</NavbarIcon>
<SelectModelButton assistant={assistant} />
</HStack>
<HStack alignItems="center" gap={8}>
<UpdateAppButton />
<Tooltip title={t('chat.assistant.search.placeholder')} mouseEnterDelay={0.8}>
<NarrowIcon onClick={() => SearchPopup.show()}>
<Search size={18} />
</NarrowIcon>
</Tooltip>
{isMac && (
<Tooltip title={t('chat.assistant.search.placeholder')} mouseEnterDelay={0.8}>
<NarrowIcon onClick={() => SearchPopup.show()}>
<Search size={18} />
</NarrowIcon>
</Tooltip>
)}
<Tooltip title={t('navbar.expand')} mouseEnterDelay={0.8}>
<NarrowIcon onClick={handleNarrowModeToggle}>
<i className="iconfont icon-icon-adaptive-width"></i>
@ -120,34 +102,6 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
</Tooltip>
</MinAppsPopover>
)}
{topicPosition === 'right' && !showTopics && !sidebarHideCooldown && (
<FloatingSidebar
activeAssistant={assistant}
setActiveAssistant={setActiveAssistant}
activeTopic={activeTopic}
setActiveTopic={setActiveTopic}
position={'right'}>
<Tooltip title={t('navbar.show_sidebar')} mouseEnterDelay={2}>
<NavbarIcon onClick={() => toggleShowTopics()}>
<PanelLeftClose size={18} />
</NavbarIcon>
</Tooltip>
</FloatingSidebar>
)}
{topicPosition === 'right' && !showTopics && sidebarHideCooldown && (
<Tooltip title={t('navbar.show_sidebar')} mouseEnterDelay={2}>
<NavbarIcon onClick={() => toggleShowTopics()} onMouseOut={() => setSidebarHideCooldown(false)}>
<PanelLeftClose size={18} />
</NavbarIcon>
</Tooltip>
)}
{topicPosition === 'right' && showTopics && (
<Tooltip title={t('navbar.hide_sidebar')} mouseEnterDelay={2}>
<NavbarIcon onClick={() => handleToggleShowTopics()}>
<PanelRightClose size={18} />
</NavbarIcon>
</Tooltip>
)}
</HStack>
</NavbarContainer>
</Navbar>
@ -163,7 +117,7 @@ const NavbarContainer = styled.div<{ $isFullscreen: boolean; $showSidebar: boole
max-height: var(--navbar-height);
min-height: var(--navbar-height);
justify-content: space-between;
padding-left: ${({ $showSidebar }) => (isMac && !$showSidebar ? '70px' : '10px')};
padding-left: ${({ $showSidebar }) => (isMac ? ($showSidebar ? '10px' : '75px') : '15px')};
font-weight: bold;
color: var(--color-text-1);
padding-right: ${({ $isFullscreen }) => ($isFullscreen ? '12px' : isWindows ? '140px' : isLinux ? '120px' : '12px')};
@ -210,4 +164,4 @@ const NarrowIcon = styled(NavbarIcon)`
}
`
export default HeaderNavbar
export default ChatNavbar

View File

@ -8,7 +8,7 @@ import { useLocation, useNavigate } from 'react-router-dom'
import styled from 'styled-components'
import Chat from './Chat'
import Navbar from './Navbar'
import ChatNavbar from './ChatNavbar'
const HomePage: FC = () => {
const { assistants } = useAssistants()
@ -54,13 +54,7 @@ const HomePage: FC = () => {
return (
<Container id="home-page">
<Navbar
activeAssistant={activeAssistant}
activeTopic={activeTopic}
setActiveTopic={setActiveTopic}
setActiveAssistant={setActiveAssistant}
position="left"
/>
<ChatNavbar activeAssistant={activeAssistant} position="left" />
<ContentContainer id="content-container">
<Chat
assistant={activeAssistant}

View File

@ -14,7 +14,7 @@ import { useAssistant } from '@renderer/hooks/useAssistant'
import { useKnowledgeBases } from '@renderer/hooks/useKnowledge'
import { useMCPServers } from '@renderer/hooks/useMCPServers'
import { useMessageOperations, useTopicLoading } from '@renderer/hooks/useMessageOperations'
import { modelGenerating, useRuntime } from '@renderer/hooks/useRuntime'
import { useRuntime } from '@renderer/hooks/useRuntime'
import { useMessageStyle, useSettings } from '@renderer/hooks/useSettings'
import { useShortcut, useShortcutDisplay } from '@renderer/hooks/useShortcuts'
import { useSidebarIconShow } from '@renderer/hooks/useSidebarIcon'
@ -52,6 +52,7 @@ import InputbarTools, { InputbarToolsRef } from './InputbarTools'
import KnowledgeBaseInput from './KnowledgeBaseInput'
import MentionModelsInput from './MentionModelsInput'
import SendMessageButton from './SendMessageButton'
import SettingButton from './SettingButton'
import TokenCount from './TokenCount'
interface Props {
@ -405,8 +406,6 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
}
const addNewTopic = useCallback(async () => {
await modelGenerating()
const topic = getDefaultTopic(assistant.id)
await db.topics.add({ id: topic.id, messages: [] })
@ -858,6 +857,7 @@ const Inputbar: FC<Props> = ({ assistant: _assistant, setActiveTopic, topic }) =
ToolbarButton={ToolbarButton}
onClick={onNewContext}
/>
<SettingButton assistant={assistant} ToolbarButton={ToolbarButton} />
<TranslateButton text={text} onTranslated={onTranslated} isLoading={isTranslating} />
{loading && (
<Tooltip placement="top" title={t('chat.input.pause')} arrow>

View File

@ -0,0 +1,43 @@
import { Assistant } from '@renderer/types'
import { Popover } from 'antd'
import { Settings } from 'lucide-react'
import { FC, useState } from 'react'
import SettingsTab from '../Tabs/SettingsTab'
interface Props {
assistant: Assistant
ToolbarButton: any
}
const SettingButton: FC<Props> = ({ assistant, ToolbarButton }) => {
const [open, setOpen] = useState(false)
const handleOpenChange = (newOpen: boolean) => {
setOpen(newOpen)
}
const handleClose = () => {
setOpen(false)
}
return (
<Popover
placement="topLeft"
content={<SettingsTab assistant={assistant} onClose={handleClose} />}
trigger="click"
open={open}
onOpenChange={handleOpenChange}
styles={{
body: {
padding: '4px 2px 4px 2px'
}
}}>
<ToolbarButton type="text">
<Settings size={18} />
</ToolbarButton>
</Popover>
)
}
export default SettingButton

View File

@ -80,7 +80,7 @@ const Assistants: FC<AssistantsTabProps> = ({
if (assistantsTabSortType === 'tags') {
return (
<Container className="assistants-tab" ref={containerRef}>
<div style={{ marginBottom: 4 }}>
<div style={{ display: 'flex', flexDirection: 'column', marginBottom: 4, gap: 10 }}>
{getGroupedAssistants.map((group) => (
<TagsContainer key={group.tag}>
{group.tag !== t('assistants.tags.untagged') && (
@ -197,12 +197,7 @@ const AssistantAddItem = styled.div`
cursor: pointer;
&:hover {
background-color: var(--color-background-soft);
}
&.active {
background-color: var(--color-background-soft);
border: 0.5px solid var(--color-border);
background-color: var(--color-list-item-hover);
}
`
@ -228,7 +223,7 @@ const GroupTitleName = styled.div`
color: var(--color-text);
font-size: 13px;
line-height: 24px;
margin-right: 2px;
margin-right: 5px;
display: flex;
`

View File

@ -69,6 +69,7 @@ import OpenAISettingsGroup from './components/OpenAISettingsGroup'
interface Props {
assistant: Assistant
onClose: () => void
}
const SettingsTab: FC<Props> = (props) => {
@ -197,7 +198,10 @@ const SettingsTab: FC<Props> = (props) => {
type="text"
size="small"
icon={<Settings2 size={16} />}
onClick={() => AssistantSettingsPopup.show({ assistant, tab: 'model' })}
onClick={() => {
AssistantSettingsPopup.show({ assistant, tab: 'model' })
props.onClose()
}}
/>
</HStack>
}>
@ -681,8 +685,10 @@ const SettingsTab: FC<Props> = (props) => {
}
const Container = styled(Scrollbar)`
min-width: 300px;
max-width: 40vw;
max-height: 70vh;
display: flex;
flex: 1;
flex-direction: column;
padding: 0 8px;
padding-right: 0;

View File

@ -1,12 +1,8 @@
import AddAssistantPopup from '@renderer/components/Popups/AddAssistantPopup'
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
import { useSettings } from '@renderer/hooks/useSettings'
import { useShowTopics } from '@renderer/hooks/useStore'
import { Assistant, Topic } from '@renderer/types'
import { uuid } from '@renderer/utils'
import { Segmented as AntSegmented } from 'antd'
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import Assistants from './AssistantsTab'
@ -19,37 +15,14 @@ interface Props {
activeTopic: Topic
setActiveAssistant: (assistant: Assistant) => void
setActiveTopic: (topic: Topic) => void
position: 'left' | 'right'
forceToSeeAllTab?: boolean
style?: React.CSSProperties
}
type Tab = 'assistants' | 'topic' | 'settings'
const HomeTabs: FC<Props> = ({
tab,
activeAssistant,
activeTopic,
setActiveAssistant,
setActiveTopic,
position,
forceToSeeAllTab,
style
}) => {
const HomeTabs: FC<Props> = ({ tab, activeAssistant, activeTopic, setActiveAssistant, setActiveTopic, style }) => {
const { addAssistant } = useAssistants()
const { topicPosition } = useSettings()
const { defaultAssistant } = useDefaultAssistant()
const { showTopics, toggleShowTopics } = useShowTopics()
const { t } = useTranslation()
const showTab = !(position === 'left' && topicPosition === 'right')
const assistantTab = {
label: t('assistants.abbr'),
value: 'assistants'
// icon: <BotIcon size={16} />
}
const onCreateAssistant = async () => {
const assistant = await AddAssistantPopup.show()
@ -62,36 +35,6 @@ const HomeTabs: FC<Props> = ({
setActiveAssistant(assistant)
}
// useEffect(() => {
// const unsubscribes = [
// EventEmitter.on(EVENT_NAMES.SHOW_ASSISTANTS, (): any => {
// showTab && setTab('assistants')
// }),
// EventEmitter.on(EVENT_NAMES.SHOW_TOPIC_SIDEBAR, (): any => {
// showTab && setTab('topic')
// }),
// EventEmitter.on(EVENT_NAMES.SHOW_CHAT_SETTINGS, (): any => {
// showTab && setTab('settings')
// }),
// EventEmitter.on(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR, () => {
// showTab && setTab('topic')
// if (position === 'left' && topicPosition === 'right') {
// toggleShowTopics()
// }
// })
// ]
// return () => unsubscribes.forEach((unsub) => unsub())
// }, [position, showTab, tab, toggleShowTopics, topicPosition])
// useEffect(() => {
// if (position === 'right' && topicPosition === 'right' && tab === 'assistants') {
// setTab('topic')
// }
// if (position === 'left' && topicPosition === 'right' && forceToSeeAllTab != true && tab !== 'assistants') {
// setTab('assistants')
// }
// }, [position, tab, topicPosition, forceToSeeAllTab])
return (
<Container style={{ ...style }} className="home-tabs">
<TabContent className="home-tabs-content">
@ -134,68 +77,4 @@ const TabContent = styled.div`
overflow-x: hidden;
`
const Divider = styled.div`
border-top: 0.5px solid var(--color-border);
margin-top: 10px;
margin-left: 10px;
margin-right: 10px;
`
const Segmented = styled(AntSegmented)`
font-family: var(--font-family);
&.ant-segmented {
background-color: transparent;
margin: 0 10px;
margin-top: 10px;
padding: 0;
}
.ant-segmented-item {
overflow: hidden;
transition: none !important;
height: 34px;
line-height: 34px;
background-color: transparent;
user-select: none;
border-radius: var(--list-item-border-radius);
box-shadow: none;
}
.ant-segmented-item-selected,
.ant-segmented-item-selected:active {
transition: none !important;
background-color: var(--color-list-item);
}
.ant-segmented-item-label {
align-items: center;
display: flex;
flex-direction: row;
justify-content: center;
font-size: 13px;
height: 100%;
}
.ant-segmented-item-label[aria-selected='true'] {
color: var(--color-text);
}
.icon-business-smart-assistant {
margin-right: -2px;
}
.ant-segmented-thumb {
transition: none !important;
background-color: var(--color-list-item);
border-radius: var(--list-item-border-radius);
box-shadow: none;
&:hover {
background-color: transparent;
}
}
.ant-segmented-item-label,
.ant-segmented-item-icon {
display: flex;
align-items: center;
}
/* These styles ensure the same appearance as before */
border-radius: 0;
box-shadow: none;
`
export default HomeTabs

View File

@ -1,7 +1,4 @@
import { NavbarRight } from '@renderer/components/app/Navbar'
import { HStack } from '@renderer/components/Layout'
import { isLinux, isWindows } from '@renderer/config/constant'
import { useFullscreen } from '@renderer/hooks/useFullscreen'
import { Button, Dropdown, Menu, type MenuProps } from 'antd'
import { ChevronDown, Search } from 'lucide-react'
import { useTranslation } from 'react-i18next'
@ -74,29 +71,27 @@ export const McpSettingsNavbar = () => {
}))
return (
<NavbarRight style={{ paddingRight: useFullscreen() ? '12px' : isWindows ? 150 : isLinux ? 120 : 12 }}>
<HStack alignItems="center" gap={5}>
<HStack alignItems="center" gap={5}>
<Button
size="small"
type="text"
onClick={() => navigate('/mcp-servers/npx-search')}
icon={<Search size={14} />}
className="nodrag"
style={{ fontSize: 13, height: 28, borderRadius: 20 }}>
{t('settings.mcp.searchNpx')}
</Button>
<Dropdown menu={{ items: resourceMenuItems }} trigger={['click']}>
<Button
size="small"
type="text"
onClick={() => navigate('/mcp-servers/npx-search')}
icon={<Search size={14} />}
className="nodrag"
style={{ fontSize: 13, height: 28, borderRadius: 20 }}>
{t('settings.mcp.searchNpx')}
style={{ fontSize: 13, height: 28, borderRadius: 20, display: 'flex', alignItems: 'center' }}>
{t('settings.mcp.findMore')}
<ChevronDown size={16} />
</Button>
<Dropdown menu={{ items: resourceMenuItems }} trigger={['click']}>
<Button
size="small"
type="text"
className="nodrag"
style={{ fontSize: 13, height: 28, borderRadius: 20, display: 'flex', alignItems: 'center' }}>
{t('settings.mcp.findMore')}
<ChevronDown size={16} />
</Button>
</Dropdown>
<InstallNpxUv mini />
</HStack>
</NavbarRight>
</Dropdown>
<InstallNpxUv mini />
</HStack>
)
}