mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-04 20:00:00 +08:00
feat: implement ChatNavbar component and enhance MainNavbar with search functionality
This commit is contained in:
parent
684367bf7c
commit
06a60c4871
@ -1,16 +1,27 @@
|
|||||||
|
import { isMac } from '@renderer/config/constant'
|
||||||
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||||
import { Tooltip } from 'antd'
|
import { Tooltip } from 'antd'
|
||||||
import { t } from 'i18next'
|
import { t } from 'i18next'
|
||||||
import { MessageSquareDiff } from 'lucide-react'
|
import { MessageSquareDiff, Search } from 'lucide-react'
|
||||||
import { FC } from 'react'
|
import { FC } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
|
import SearchPopup from '../Popups/SearchPopup'
|
||||||
|
|
||||||
interface Props {}
|
interface Props {}
|
||||||
|
|
||||||
const HeaderNavbar: FC<Props> = () => {
|
const HeaderNavbar: FC<Props> = () => {
|
||||||
return (
|
return (
|
||||||
<Container>
|
<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}>
|
<Tooltip title={t('settings.shortcuts.new_topic')} mouseEnterDelay={0.8}>
|
||||||
<NavbarIcon onClick={() => EventEmitter.emit(EVENT_NAMES.ADD_NEW_TOPIC)} style={{ marginRight: 5 }}>
|
<NavbarIcon onClick={() => EventEmitter.emit(EVENT_NAMES.ADD_NEW_TOPIC)} style={{ marginRight: 5 }}>
|
||||||
<MessageSquareDiff size={18} />
|
<MessageSquareDiff size={18} />
|
||||||
@ -32,6 +43,7 @@ const Container = styled.div`
|
|||||||
min-height: var(--navbar-height);
|
min-height: var(--navbar-height);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
|
padding-left: ${isMac ? '75px' : '0'};
|
||||||
`
|
`
|
||||||
|
|
||||||
export const NavbarIcon = styled.div`
|
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
|
export default HeaderNavbar
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { Navbar } from '@renderer/components/app/Navbar'
|
import { Navbar } from '@renderer/components/app/Navbar'
|
||||||
import { HStack } from '@renderer/components/Layout'
|
import { HStack } from '@renderer/components/Layout'
|
||||||
import FloatingSidebar from '@renderer/components/Popups/FloatingSidebar'
|
|
||||||
import MinAppsPopover from '@renderer/components/Popups/MinAppsPopover'
|
import MinAppsPopover from '@renderer/components/Popups/MinAppsPopover'
|
||||||
import SearchPopup from '@renderer/components/Popups/SearchPopup'
|
import SearchPopup from '@renderer/components/Popups/SearchPopup'
|
||||||
import { isLinux, isMac, isWindows } from '@renderer/config/constant'
|
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 { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
|
||||||
import { useAppDispatch } from '@renderer/store'
|
import { useAppDispatch } from '@renderer/store'
|
||||||
import { setNarrowMode } from '@renderer/store/settings'
|
import { setNarrowMode } from '@renderer/store/settings'
|
||||||
import { Assistant, Topic } from '@renderer/types'
|
import { Assistant } from '@renderer/types'
|
||||||
import { Tooltip } from 'antd'
|
import { Tooltip } from 'antd'
|
||||||
import { t } from 'i18next'
|
import { t } from 'i18next'
|
||||||
import { LayoutGrid, PanelLeftClose, PanelRightClose, Search } from 'lucide-react'
|
import { LayoutGrid, PanelLeft, PanelRight, Search } from 'lucide-react'
|
||||||
import { FC, useCallback, useState } from 'react'
|
import { FC, useCallback } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import SelectModelButton from './components/SelectModelButton'
|
import SelectModelButton from './components/SelectModelButton'
|
||||||
@ -25,27 +24,22 @@ import UpdateAppButton from './components/UpdateAppButton'
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
activeAssistant: Assistant
|
activeAssistant: Assistant
|
||||||
activeTopic: Topic
|
|
||||||
setActiveTopic: (topic: Topic) => void
|
|
||||||
setActiveAssistant: (assistant: Assistant) => void
|
|
||||||
position: 'left' | 'right'
|
position: 'left' | 'right'
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTopic, setActiveTopic }) => {
|
const ChatNavbar: FC<Props> = ({ activeAssistant }) => {
|
||||||
const { assistant } = useAssistant(activeAssistant.id)
|
const { assistant } = useAssistant(activeAssistant.id)
|
||||||
const { showAssistants, toggleShowAssistants } = useShowAssistants()
|
const { showAssistants, toggleShowAssistants } = useShowAssistants()
|
||||||
const isFullscreen = useFullscreen()
|
const isFullscreen = useFullscreen()
|
||||||
const { topicPosition, sidebarIcons, narrowMode } = useSettings()
|
const { topicPosition, sidebarIcons, narrowMode } = useSettings()
|
||||||
const { showTopics, toggleShowTopics } = useShowTopics()
|
const { toggleShowTopics } = useShowTopics()
|
||||||
const dispatch = useAppDispatch()
|
const dispatch = useAppDispatch()
|
||||||
const [sidebarHideCooldown, setSidebarHideCooldown] = useState(false)
|
|
||||||
|
|
||||||
// Function to toggle assistants with cooldown
|
// Function to toggle assistants with cooldown
|
||||||
const handleToggleShowAssistants = useCallback(() => {
|
const handleToggleShowAssistants = useCallback(() => {
|
||||||
if (showAssistants) {
|
if (showAssistants) {
|
||||||
// When hiding sidebar, set cooldown
|
// When hiding sidebar, set cooldown
|
||||||
toggleShowAssistants()
|
toggleShowAssistants()
|
||||||
setSidebarHideCooldown(true)
|
|
||||||
// setTimeout(() => {
|
// setTimeout(() => {
|
||||||
// setSidebarHideCooldown(false)
|
// setSidebarHideCooldown(false)
|
||||||
// }, 10000) // 10 seconds cooldown
|
// }, 10000) // 10 seconds cooldown
|
||||||
@ -55,20 +49,6 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
|
|||||||
}
|
}
|
||||||
}, [showAssistants, toggleShowAssistants])
|
}, [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_assistants', handleToggleShowAssistants)
|
||||||
|
|
||||||
useShortcut('toggle_show_topics', () => {
|
useShortcut('toggle_show_topics', () => {
|
||||||
@ -95,17 +75,19 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
|
|||||||
<NavbarIcon
|
<NavbarIcon
|
||||||
onClick={() => toggleShowAssistants()}
|
onClick={() => toggleShowAssistants()}
|
||||||
style={{ marginRight: 8, marginLeft: isMac && !isFullscreen ? 4 : -12 }}>
|
style={{ marginRight: 8, marginLeft: isMac && !isFullscreen ? 4 : -12 }}>
|
||||||
{showAssistants ? <PanelLeftClose size={18} /> : <PanelRightClose size={18} />}
|
{showAssistants ? <PanelLeft size={18} /> : <PanelRight size={18} />}
|
||||||
</NavbarIcon>
|
</NavbarIcon>
|
||||||
<SelectModelButton assistant={assistant} />
|
<SelectModelButton assistant={assistant} />
|
||||||
</HStack>
|
</HStack>
|
||||||
<HStack alignItems="center" gap={8}>
|
<HStack alignItems="center" gap={8}>
|
||||||
<UpdateAppButton />
|
<UpdateAppButton />
|
||||||
<Tooltip title={t('chat.assistant.search.placeholder')} mouseEnterDelay={0.8}>
|
{isMac && (
|
||||||
<NarrowIcon onClick={() => SearchPopup.show()}>
|
<Tooltip title={t('chat.assistant.search.placeholder')} mouseEnterDelay={0.8}>
|
||||||
<Search size={18} />
|
<NarrowIcon onClick={() => SearchPopup.show()}>
|
||||||
</NarrowIcon>
|
<Search size={18} />
|
||||||
</Tooltip>
|
</NarrowIcon>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
<Tooltip title={t('navbar.expand')} mouseEnterDelay={0.8}>
|
<Tooltip title={t('navbar.expand')} mouseEnterDelay={0.8}>
|
||||||
<NarrowIcon onClick={handleNarrowModeToggle}>
|
<NarrowIcon onClick={handleNarrowModeToggle}>
|
||||||
<i className="iconfont icon-icon-adaptive-width"></i>
|
<i className="iconfont icon-icon-adaptive-width"></i>
|
||||||
@ -120,34 +102,6 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</MinAppsPopover>
|
</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>
|
</HStack>
|
||||||
</NavbarContainer>
|
</NavbarContainer>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
@ -163,7 +117,7 @@ const NavbarContainer = styled.div<{ $isFullscreen: boolean; $showSidebar: boole
|
|||||||
max-height: var(--navbar-height);
|
max-height: var(--navbar-height);
|
||||||
min-height: var(--navbar-height);
|
min-height: var(--navbar-height);
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding-left: ${({ $showSidebar }) => (isMac && !$showSidebar ? '70px' : '20px')};
|
padding-left: ${({ $showSidebar }) => (isMac ? ($showSidebar ? '10px' : '75px') : '15px')};
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: var(--color-text-1);
|
color: var(--color-text-1);
|
||||||
padding-right: ${({ $isFullscreen }) => ($isFullscreen ? '12px' : isWindows ? '140px' : isLinux ? '120px' : '12px')};
|
padding-right: ${({ $isFullscreen }) => ($isFullscreen ? '12px' : isWindows ? '140px' : isLinux ? '120px' : '12px')};
|
||||||
@ -210,4 +164,4 @@ const NarrowIcon = styled(NavbarIcon)`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export default HeaderNavbar
|
export default ChatNavbar
|
||||||
@ -8,7 +8,7 @@ import { useLocation, useNavigate } from 'react-router-dom'
|
|||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
import Chat from './Chat'
|
import Chat from './Chat'
|
||||||
import Navbar from './Navbar'
|
import ChatNavbar from './ChatNavbar'
|
||||||
|
|
||||||
const HomePage: FC = () => {
|
const HomePage: FC = () => {
|
||||||
const { assistants } = useAssistants()
|
const { assistants } = useAssistants()
|
||||||
@ -54,13 +54,7 @@ const HomePage: FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container id="home-page">
|
<Container id="home-page">
|
||||||
<Navbar
|
<ChatNavbar activeAssistant={activeAssistant} position="left" />
|
||||||
activeAssistant={activeAssistant}
|
|
||||||
activeTopic={activeTopic}
|
|
||||||
setActiveTopic={setActiveTopic}
|
|
||||||
setActiveAssistant={setActiveAssistant}
|
|
||||||
position="left"
|
|
||||||
/>
|
|
||||||
<ContentContainer id="content-container">
|
<ContentContainer id="content-container">
|
||||||
<Chat
|
<Chat
|
||||||
assistant={activeAssistant}
|
assistant={activeAssistant}
|
||||||
|
|||||||
@ -80,7 +80,7 @@ const Assistants: FC<AssistantsTabProps> = ({
|
|||||||
if (assistantsTabSortType === 'tags') {
|
if (assistantsTabSortType === 'tags') {
|
||||||
return (
|
return (
|
||||||
<Container className="assistants-tab" ref={containerRef}>
|
<Container className="assistants-tab" ref={containerRef}>
|
||||||
<div style={{ marginBottom: 4 }}>
|
<div style={{ display: 'flex', flexDirection: 'column', marginBottom: 4, gap: 10 }}>
|
||||||
{getGroupedAssistants.map((group) => (
|
{getGroupedAssistants.map((group) => (
|
||||||
<TagsContainer key={group.tag}>
|
<TagsContainer key={group.tag}>
|
||||||
{group.tag !== t('assistants.tags.untagged') && (
|
{group.tag !== t('assistants.tags.untagged') && (
|
||||||
@ -228,7 +228,7 @@ const GroupTitleName = styled.div`
|
|||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
margin-right: 2px;
|
margin-right: 5px;
|
||||||
display: flex;
|
display: flex;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user