import { useContext, useEffect, useState } from 'react' import PropTypes from 'prop-types' import { Flex } from 'antd' import { ElectronContext } from '../context/ElectronContext' import CloseColored from '../../../../assets/trafficlights/closecolored.svg?react' import CloseHoverColored from '../../../../assets/trafficlights/closehovercolored.svg?react' import CloseDownColored from '../../../../assets/trafficlights/closedowncolored.svg?react' import MinimizeColored from '../../../../assets/trafficlights/minimizecolored.svg?react' import MinimizeHoverColored from '../../../../assets/trafficlights/minimizehovercolored.svg?react' import MinimizeDownColored from '../../../../assets/trafficlights/minimizedowncolored.svg?react' import FullscreenColored from '../../../../assets/trafficlights/fullscreencolored.svg?react' import FullscreenHoverColored from '../../../../assets/trafficlights/fullscreenhovercolored.svg?react' import FullscreenDownColored from '../../../../assets/trafficlights/fullscreendowncolored.svg?react' import ExitFullscreenHoverColored from '../../../../assets/trafficlights/exitfullscreenhovercolored.svg?react' import ExitFullscreenDownColored from '../../../../assets/trafficlights/exitfullscreendowncolored.svg?react' import NoFocus from '../../../../assets/trafficlights/nofocus.svg?react' const TRAFFIC_LIGHT_SIZE = 12 const TRAFFIC_LIGHT_BUTTON_STYLE = { width: TRAFFIC_LIGHT_SIZE, height: TRAFFIC_LIGHT_SIZE, padding: 0, border: 'none', background: 'transparent', cursor: 'default', lineHeight: 0, display: 'flex', alignItems: 'center', justifyContent: 'center' } const TRAFFIC_LIGHT_ICON_STYLE = { width: TRAFFIC_LIGHT_SIZE, height: TRAFFIC_LIGHT_SIZE, display: 'block' } function getTrafficLightIcon({ isEnabled, isFocused, isActive, isHovered, icons }) { if (!isEnabled || !isFocused) { return icons.noFocus } if (isActive) { return icons.down } if (isHovered) { return icons.hover } return icons.colored } const TrafficLightButton = ({ action, icons, isGroupHovered, activeAction, isEnabled, isWindowFocused, onActive, onAction }) => { const Icon = getTrafficLightIcon({ isEnabled, isFocused: isWindowFocused, isActive: activeAction === action, isHovered: isGroupHovered, icons }) const handleMouseDown = (event) => { if (!isEnabled) return event.preventDefault() event.stopPropagation() onActive(action) onAction(action) } return ( ) } TrafficLightButton.propTypes = { action: PropTypes.string.isRequired, icons: PropTypes.shape({ colored: PropTypes.elementType.isRequired, hover: PropTypes.elementType.isRequired, down: PropTypes.elementType.isRequired, noFocus: PropTypes.elementType.isRequired }).isRequired, isGroupHovered: PropTypes.bool.isRequired, activeAction: PropTypes.string, isEnabled: PropTypes.bool.isRequired, isWindowFocused: PropTypes.bool.isRequired, onActive: PropTypes.func.isRequired, onAction: PropTypes.func.isRequired } const MacOSTrafficLights = () => { const { handleWindowControl, isFullScreen } = useContext(ElectronContext) const [isGroupHovered, setIsGroupHovered] = useState(false) const [activeAction, setActiveAction] = useState(null) const [isWindowFocused, setIsWindowFocused] = useState( () => document.hasFocus?.() ?? true ) useEffect(() => { const handleFocus = () => setIsWindowFocused(true) const handleBlur = () => setIsWindowFocused(false) window.addEventListener('focus', handleFocus) window.addEventListener('blur', handleBlur) return () => { window.removeEventListener('focus', handleFocus) window.removeEventListener('blur', handleBlur) } }, []) const fullscreenIcons = isFullScreen ? { colored: FullscreenColored, hover: ExitFullscreenHoverColored, down: ExitFullscreenDownColored, noFocus: NoFocus } : { colored: FullscreenColored, hover: FullscreenHoverColored, down: FullscreenDownColored, noFocus: NoFocus } const handleAction = (action) => { handleWindowControl(action) } return ( setIsGroupHovered(true)} onMouseLeave={() => { setIsGroupHovered(false) setActiveAction(null) }} > ) } export default MacOSTrafficLights