mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-11 18:33:53 +00:00
f187d5edaf
* fix/122: register quit shortcut for macOS * fix/122: version bump
187 lines
5.3 KiB
React
187 lines
5.3 KiB
React
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 (
|
|
<VStack>
|
|
<QuitIconBtn clickHandler={() => handleIPC('shutdown')} />
|
|
<TooltipActionBtn
|
|
{...buttonStyle}
|
|
icon={<FiMaximize />}
|
|
clickHandler={() => handleIPC('max')}
|
|
tooltip='Show full window'
|
|
/>
|
|
<TooltipActionBtn
|
|
{...buttonStyle}
|
|
icon={<FiMinimize />}
|
|
clickHandler={() => handleIPC('min')}
|
|
tooltip='Close to tray'
|
|
/>
|
|
<div className={style.gap} />
|
|
<TooltipActionBtn
|
|
{...buttonStyle}
|
|
icon={<FiHelpCircle />}
|
|
clickHandler={() => handleIPC('help')}
|
|
tooltip='Help'
|
|
/>
|
|
<TooltipActionBtn
|
|
{...buttonStyle}
|
|
icon={<FiSettings />}
|
|
className={isOpen ? style.open : ''}
|
|
clickHandler={onOpen}
|
|
tooltip='Settings'
|
|
isRound
|
|
/>
|
|
<div className={style.gap} />
|
|
<input
|
|
type='file'
|
|
style={{ display: 'none' }}
|
|
ref={hiddenFileInput}
|
|
onChange={handleUpload}
|
|
accept='.json, .xlsx'
|
|
/>
|
|
<TooltipActionBtn
|
|
{...buttonStyle}
|
|
icon={<FiUpload />}
|
|
clickHandler={handleClick}
|
|
tooltip='Import event list'
|
|
/>
|
|
<TooltipActionBtn
|
|
{...buttonStyle}
|
|
icon={<FiDownload />}
|
|
clickHandler={downloadEvents}
|
|
tooltip='Export event list'
|
|
/>
|
|
</VStack>
|
|
);
|
|
}
|
|
|
|
MenuBar.propTypes = {
|
|
isOpen: PropTypes.bool,
|
|
onOpen: PropTypes.func.isRequired,
|
|
onClose: PropTypes.func.isRequired,
|
|
};
|