import React, { useCallback, useContext, useEffect, useRef } from 'react'; import { useMutation, useQueryClient } from 'react-query'; import { VStack } from '@chakra-ui/react'; import { downloadEvents, uploadEvents } from 'app/api/ontimeApi'; import { FiMaximize } from '@react-icons/all-files/fi/FiMaximize'; import { FiMinimize } from '@react-icons/all-files/fi/FiMinimize'; import { FiHelpCircle } from '@react-icons/all-files/fi/FiHelpCircle'; import { FiSettings } from '@react-icons/all-files/fi/FiSettings'; import { FiUpload } from '@react-icons/all-files/fi/FiUpload'; import { FiDownload } from '@react-icons/all-files/fi/FiDownload'; import { EVENTS_TABLE } from 'app/api/apiConstants'; import { LoggingContext } from '../../app/context/LoggingContext'; import TooltipActionBtn from '../../common/components/buttons/TooltipActionBtn'; import QuitIconBtn from '../../common/components/buttons/QuitIconBtn'; import PropTypes from 'prop-types'; import style from './MenuBar.module.scss'; export default function MenuBar(props) { const { isOpen, onOpen, onClose } = props; const { emitError } = useContext(LoggingContext); const hiddenFileInput = useRef(null); const queryClient = useQueryClient(); const uploaddb = useMutation(uploadEvents, { onSettled: () => { queryClient.invalidateQueries(EVENTS_TABLE); }, }); const handleClick = useCallback(() => { if (hiddenFileInput && hiddenFileInput.current) { hiddenFileInput.current.click(); } }, [hiddenFileInput]); const buttonStyle = { fontSize: '1.5em', size: 'lg', colorScheme: 'white', }; const handleUpload = useCallback( (event) => { const fileUploaded = event.target.files[0]; if (fileUploaded == null) return; // Limit file size to 1MB if (fileUploaded.size > 1000000) { emitError('Error: File size limit (1MB) exceeded'); return; } // Check file extension if (fileUploaded.name.endsWith('.xlsx') || fileUploaded.name.endsWith('.json')) { try { uploaddb.mutate(fileUploaded); } catch (error) { emitError(`Failed uploading file: ${error}`); } } else { emitError('Error: File type unknown'); } // reset input value hiddenFileInput.current.value = ''; }, [emitError, uploaddb] ); const handleIPC = useCallback((action) => { // Stop crashes when testing locally if (typeof window.process?.type === 'undefined') { if (action === 'help') { window.open('https://cpvalente.gitbook.io/ontime/'); } return; } if (window.process?.type === 'renderer') { switch (action) { case 'min': window.ipcRenderer.send('set-window', 'to-tray'); break; case 'max': window.ipcRenderer.send('set-window', 'to-max'); break; case 'shutdown': window.ipcRenderer.send('shutdown', 'now'); break; case 'help': window.ipcRenderer.send('send-to-link', 'help'); break; default: break; } } }, []); // Handle keyboard shortcuts const handleKeyPress = useCallback( (e) => { // handle held key if (e.repeat) return; // check if the alt key is pressed if (e.ctrlKey) { if (e.key === ',') { // if we are in electron if (window.process?.type === undefined) return; if (window.process.type === 'renderer') { // open if not open isOpen ? onClose() : onOpen(); } } } }, [isOpen, onClose, onOpen] ); useEffect(() => { // attach the event listener document.addEventListener('keydown', handleKeyPress); // remove the event listener return () => { document.removeEventListener('keydown', handleKeyPress); }; }, [handleKeyPress]); return ( handleIPC('shutdown')} /> } clickHandler={() => handleIPC('max')} tooltip='Show full window' /> } clickHandler={() => handleIPC('min')} tooltip='Close to tray' />
} clickHandler={() => handleIPC('help')} tooltip='Help' /> } className={isOpen ? style.open : ''} clickHandler={onOpen} tooltip='Settings' isRound />
} clickHandler={handleClick} tooltip='Import event list' /> } clickHandler={downloadEvents} tooltip='Export event list' /> ); } MenuBar.propTypes = { isOpen: PropTypes.bool, onOpen: PropTypes.func.isRequired, onClose: PropTypes.func.isRequired, };