mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-05 04:19:02 +08:00
refactor(Navbar): improve WindowControls visibility and clean up event listener management (#10066)
* refactor(Navbar): improve WindowControls visibility and clean up event listener management - Updated Navbar component to conditionally render WindowControls based on minappShow state. - Refactored IPC event listener management in preload script for better clarity and performance. * feat(WindowControls): replace custom restore icon with a new SVG component - Introduced a new `WindowRestoreIcon` component with enhanced SVG structure and styling. - Updated `WindowControls` to use the new `WindowRestoreIcon` for better visual consistency and scalability. * feat(WindowControls): update WindowRestoreIcon SVG for improved design - Enhanced the SVG structure of the `WindowRestoreIcon` component with updated dimensions and styling for better visual appeal. - Adjusted the path and rectangle properties to refine the icon's appearance and maintain consistency across the application. * lint error
This commit is contained in:
parent
87bdfbeeeb
commit
2962ef79dc
@ -455,9 +455,10 @@ const api = {
|
||||
isMaximized: (): Promise<boolean> => ipcRenderer.invoke(IpcChannel.Windows_IsMaximized),
|
||||
onMaximizedChange: (callback: (isMaximized: boolean) => void): (() => void) => {
|
||||
const channel = IpcChannel.Windows_MaximizedChanged
|
||||
ipcRenderer.on(channel, (_, isMaximized: boolean) => callback(isMaximized))
|
||||
const listener = (_: Electron.IpcRendererEvent, isMaximized: boolean) => callback(isMaximized)
|
||||
ipcRenderer.on(channel, listener)
|
||||
return () => {
|
||||
ipcRenderer.removeAllListeners(channel)
|
||||
ipcRenderer.removeListener(channel, listener)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,17 +2,45 @@ import { isLinux, isWin } from '@renderer/config/constant'
|
||||
import { Tooltip } from 'antd'
|
||||
import { Minus, Square, X } from 'lucide-react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { SVGProps } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { ControlButton, WindowControlsContainer } from './WindowControls.styled'
|
||||
|
||||
// Custom restore icon - two overlapping squares like Windows
|
||||
const RestoreIcon: React.FC<{ size?: number }> = ({ size = 14 }) => (
|
||||
<svg width={size} height={size} viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1">
|
||||
{/* Back square (top-right) */}
|
||||
<path d="M 4 2 H 11 V 9 H 9 V 4 H 4 V 2" />
|
||||
{/* Front square (bottom-left) */}
|
||||
<rect x="2" y="4" width="7" height="7" />
|
||||
interface WindowRestoreIconProps extends SVGProps<SVGSVGElement> {
|
||||
size?: string | number
|
||||
}
|
||||
|
||||
export const WindowRestoreIcon = ({ size = '1.1em', ...props }: WindowRestoreIconProps) => (
|
||||
<svg
|
||||
width={size}
|
||||
height={size}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="lucide lucide-square-icon lucide-square"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}>
|
||||
<defs id="defs1" />
|
||||
<rect
|
||||
width="14.165795"
|
||||
height="14.165795"
|
||||
x="2.7646871"
|
||||
y="7.0695167"
|
||||
rx="1.2377932"
|
||||
id="rect2"
|
||||
style={{ strokeWidth: '1.57397' }}
|
||||
/>
|
||||
<path
|
||||
d="m 8.8907777,2.8269172 c -0.5045461,0 -0.9490675,0.2424833 -1.2285866,0.6160739 H 18.993677 c 0.866756,0 1.563332,0.696576 1.563332,1.5633319 v 11.331486 c 0.37359,-0.279519 0.616074,-0.72404 0.616074,-1.228587 V 4.3635407 c 0,-0.8505156 -0.686108,-1.5366235 -1.536624,-1.5366235 z"
|
||||
style={{ strokeWidth: '0.911647', strokeDasharray: 'none' }}
|
||||
id="path5"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
|
||||
@ -67,7 +95,7 @@ const WindowControls: React.FC = () => {
|
||||
placement="bottom"
|
||||
mouseEnterDelay={DEFAULT_DELAY}>
|
||||
<ControlButton onClick={handleMaximize} aria-label={isMaximized ? 'Restore' : 'Maximize'}>
|
||||
{isMaximized ? <RestoreIcon size={14} /> : <Square size={14} />}
|
||||
{isMaximized ? <WindowRestoreIcon size={14} /> : <Square size={14} />}
|
||||
</ControlButton>
|
||||
</Tooltip>
|
||||
<Tooltip title={t('navbar.window.close')} placement="bottom" mouseEnterDelay={DEFAULT_DELAY}>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { isLinux, isMac, isWin } from '@renderer/config/constant'
|
||||
import { useFullscreen } from '@renderer/hooks/useFullscreen'
|
||||
import useNavBackgroundColor from '@renderer/hooks/useNavBackgroundColor'
|
||||
import { useRuntime } from '@renderer/hooks/useRuntime'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useSettings'
|
||||
import type { FC, PropsWithChildren } from 'react'
|
||||
import type { HTMLAttributes } from 'react'
|
||||
@ -13,6 +14,7 @@ type Props = PropsWithChildren & HTMLAttributes<HTMLDivElement>
|
||||
export const Navbar: FC<Props> = ({ children, ...props }) => {
|
||||
const backgroundColor = useNavBackgroundColor()
|
||||
const { isTopNavbar } = useNavbarPosition()
|
||||
const { minappShow } = useRuntime()
|
||||
|
||||
if (isTopNavbar) {
|
||||
return null
|
||||
@ -23,7 +25,7 @@ export const Navbar: FC<Props> = ({ children, ...props }) => {
|
||||
<NavbarContainer {...props} style={{ backgroundColor }}>
|
||||
{children}
|
||||
</NavbarContainer>
|
||||
{(isWin || isLinux) && <WindowControls />}
|
||||
{!isTopNavbar && !minappShow && <WindowControls />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Navbar, NavbarMain, NavbarRight } from '@renderer/components/app/Navbar'
|
||||
import { Navbar, NavbarMain } from '@renderer/components/app/Navbar'
|
||||
import App from '@renderer/components/MinApp/MinApp'
|
||||
import Scrollbar from '@renderer/components/Scrollbar'
|
||||
import { isLinux, isWin } from '@renderer/config/constant'
|
||||
import { useMinapps } from '@renderer/hooks/useMinapps'
|
||||
import { useNavbarPosition } from '@renderer/hooks/useSettings'
|
||||
import { Button, Input } from 'antd'
|
||||
@ -58,21 +57,13 @@ const AppsPage: FC = () => {
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
/>
|
||||
</NavbarMain>
|
||||
<NavbarRight
|
||||
style={{
|
||||
justifyContent: 'flex-end',
|
||||
flex: 1,
|
||||
position: 'relative',
|
||||
paddingRight: isWin || isLinux ? '144px' : '6px'
|
||||
}}>
|
||||
<Button
|
||||
type="text"
|
||||
className="nodrag"
|
||||
icon={<SettingsIcon size={18} color="var(--color-text-2)" />}
|
||||
onClick={MinappSettingsPopup.show}
|
||||
/>
|
||||
</NavbarRight>
|
||||
</NavbarMain>
|
||||
</Navbar>
|
||||
<ContentContainer id="content-container">
|
||||
<MainContainer>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user