mirror of
https://github.com/pavlobu/deskreen.git
synced 2025-05-18 08:20:10 -07:00
353 lines
11 KiB
TypeScript
353 lines
11 KiB
TypeScript
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
import React, { useState, useCallback, useContext, useEffect } from 'react';
|
|
import { remote } from 'electron';
|
|
import { makeStyles, createStyles } from '@material-ui/core/styles';
|
|
import Stepper from '@material-ui/core/Stepper';
|
|
import Step from '@material-ui/core/Step';
|
|
import StepLabel from '@material-ui/core/StepLabel';
|
|
import { Row, Col } from 'react-flexbox-grid';
|
|
import { Text } from '@blueprintjs/core';
|
|
|
|
import { useToasts } from 'react-toast-notifications';
|
|
|
|
import SuccessStep from '../components/StepsOfStepper/SuccessStep';
|
|
import IntermediateStep from '../components/StepsOfStepper/IntermediateStep';
|
|
import AllowConnectionForDeviceAlert from '../components/AllowConnectionForDeviceAlert';
|
|
import DeviceConnectedInfoButton from '../components/StepperPanel/DeviceConnectedInfoButton';
|
|
import ColorlibStepIcon, {
|
|
StepIconPropsDeskreen,
|
|
} from '../components/StepperPanel/ColorlibStepIcon';
|
|
import ColorlibConnector from '../components/StepperPanel/ColorlibConnector';
|
|
import { SettingsContext } from './SettingsProvider';
|
|
import isProduction from '../utils/isProduction';
|
|
import SharingSessionService from '../features/SharingSessionsService';
|
|
import ConnectedDevicesService from '../features/ConnectedDevicesService';
|
|
import SharingSessionStatusEnum from '../features/SharingSessionsService/SharingSessionStatusEnum';
|
|
import Logger from '../utils/logger';
|
|
|
|
const log = new Logger(__filename);
|
|
|
|
const sharingSessionService = remote.getGlobal(
|
|
'sharingSessionService'
|
|
) as SharingSessionService;
|
|
const connectedDevicesService = remote.getGlobal(
|
|
'connectedDevicesService'
|
|
) as ConnectedDevicesService;
|
|
|
|
const Fade = require('react-reveal/Fade');
|
|
const Zoom = require('react-reveal/Zoom');
|
|
const Pulse = require('react-reveal/Pulse');
|
|
|
|
const useStyles = makeStyles(() =>
|
|
createStyles({
|
|
stepContent: {
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
justifyContent: 'center',
|
|
alignItems: 'center',
|
|
},
|
|
stepLabelContent: {
|
|
marginTop: '10px !important',
|
|
height: '110px',
|
|
},
|
|
stepperComponent: {
|
|
paddingBottom: '0px',
|
|
},
|
|
})
|
|
);
|
|
|
|
function getSteps() {
|
|
return ['Connect', 'Select', 'Confirm'];
|
|
}
|
|
|
|
// eslint-disable-next-line react/display-name
|
|
const DeskreenStepper = React.forwardRef((_props, ref) => {
|
|
const classes = useStyles();
|
|
|
|
const [isInterShow, setIsInterShow] = useState(false);
|
|
|
|
const { isDarkTheme } = useContext(SettingsContext);
|
|
|
|
const { addToast } = useToasts();
|
|
|
|
const [isAlertOpen, setIsAlertOpen] = useState(false);
|
|
const [isUserAllowedConnection, setIsUserAllowedConnection] = useState(false);
|
|
|
|
const [
|
|
pendingConnectionDevice,
|
|
setPendingConnectionDevice,
|
|
] = useState<Device | null>(null);
|
|
|
|
useEffect(() => {
|
|
sharingSessionService
|
|
.createWaitingForConnectionSharingSession()
|
|
// eslint-disable-next-line promise/always-return
|
|
.then((waitingForConnectionSharingSession) => {
|
|
waitingForConnectionSharingSession.setOnDeviceConnectedCallback(
|
|
(device: Device) => {
|
|
connectedDevicesService.setPendingConnectionDevice(device);
|
|
}
|
|
);
|
|
})
|
|
.catch((e) => log.error(e));
|
|
|
|
connectedDevicesService.addPendingConnectedDeviceListener(
|
|
(device: Device) => {
|
|
setPendingConnectionDevice(device);
|
|
setIsAlertOpen(true);
|
|
}
|
|
);
|
|
|
|
setTimeout(
|
|
() => {
|
|
setIsInterShow(true);
|
|
},
|
|
isProduction() ? 500 : 0
|
|
);
|
|
}, []);
|
|
|
|
const [activeStep, setActiveStep] = useState(0);
|
|
const [isEntireScreenSelected, setIsEntireScreenSelected] = useState(false);
|
|
const [
|
|
isApplicationWindowSelected,
|
|
setIsApplicationWindowSelected,
|
|
] = useState(false);
|
|
const steps = getSteps();
|
|
|
|
const makeSmoothIntermediateStepTransition = () => {
|
|
if (!isProduction()) return;
|
|
setIsInterShow(false);
|
|
setTimeout(() => {
|
|
setIsInterShow(true);
|
|
}, 500);
|
|
};
|
|
|
|
const handleNext = useCallback(() => {
|
|
makeSmoothIntermediateStepTransition();
|
|
if (activeStep === steps.length - 1) {
|
|
setIsEntireScreenSelected(false);
|
|
setIsApplicationWindowSelected(false);
|
|
}
|
|
setActiveStep((prevActiveStep) => prevActiveStep + 1);
|
|
}, [activeStep, steps]);
|
|
|
|
const handleNextEntireScreen = useCallback(() => {
|
|
makeSmoothIntermediateStepTransition();
|
|
setActiveStep((prevActiveStep) => prevActiveStep + 1);
|
|
setIsEntireScreenSelected(true);
|
|
}, []);
|
|
|
|
const handleNextApplicationWindow = useCallback(() => {
|
|
makeSmoothIntermediateStepTransition();
|
|
setActiveStep((prevActiveStep) => prevActiveStep + 1);
|
|
setIsApplicationWindowSelected(true);
|
|
}, []);
|
|
|
|
const handleBack = useCallback(() => {
|
|
makeSmoothIntermediateStepTransition();
|
|
setActiveStep((prevActiveStep) => prevActiveStep - 1);
|
|
}, []);
|
|
|
|
const handleReset = useCallback(() => {
|
|
makeSmoothIntermediateStepTransition();
|
|
setActiveStep(0);
|
|
setPendingConnectionDevice(null);
|
|
setIsUserAllowedConnection(false);
|
|
sharingSessionService.waitingForConnectionSharingSession = null;
|
|
sharingSessionService
|
|
.createWaitingForConnectionSharingSession()
|
|
// eslint-disable-next-line promise/always-return
|
|
.then((waitingForConnectionSharingSession) => {
|
|
waitingForConnectionSharingSession.setOnDeviceConnectedCallback(
|
|
(device: Device) => {
|
|
connectedDevicesService.setPendingConnectionDevice(device);
|
|
}
|
|
);
|
|
})
|
|
.catch((e) => log.error(e));
|
|
}, []);
|
|
|
|
React.useImperativeHandle(ref, () => ({
|
|
handleReset() {
|
|
handleReset();
|
|
},
|
|
}));
|
|
|
|
const handleCancelAlert = async () => {
|
|
setIsAlertOpen(false);
|
|
|
|
if (sharingSessionService.waitingForConnectionSharingSession !== null) {
|
|
const sharingSession =
|
|
sharingSessionService.waitingForConnectionSharingSession;
|
|
sharingSession.denyConnectionForPartner();
|
|
sharingSession.destory();
|
|
sharingSession.setStatus(SharingSessionStatusEnum.NOT_CONNECTED);
|
|
sharingSessionService.sharingSessions.delete(sharingSession.id);
|
|
|
|
const prevRoomID =
|
|
sharingSessionService.waitingForConnectionSharingSession.roomID;
|
|
|
|
sharingSessionService.waitingForConnectionSharingSession = null;
|
|
sharingSessionService
|
|
.createWaitingForConnectionSharingSession(prevRoomID)
|
|
// eslint-disable-next-line promise/always-return
|
|
.then((waitingForConnectionSharingSession) => {
|
|
waitingForConnectionSharingSession.setOnDeviceConnectedCallback(
|
|
(device: Device) => {
|
|
connectedDevicesService.setPendingConnectionDevice(device);
|
|
}
|
|
);
|
|
})
|
|
.catch((e) => log.error(e));
|
|
}
|
|
};
|
|
|
|
const handleConfirmAlert = useCallback(async () => {
|
|
setIsAlertOpen(false);
|
|
setIsUserAllowedConnection(true);
|
|
handleNext();
|
|
|
|
if (sharingSessionService.waitingForConnectionSharingSession !== null) {
|
|
const sharingSession =
|
|
sharingSessionService.waitingForConnectionSharingSession;
|
|
sharingSession.setStatus(SharingSessionStatusEnum.CONNECTED);
|
|
}
|
|
}, [handleNext]);
|
|
|
|
const handleUserClickedDeviceDisconnectButton = useCallback(async () => {
|
|
handleReset();
|
|
|
|
addToast(
|
|
<Text>
|
|
Device is successfully disconnected by you. You can connect new device
|
|
</Text>,
|
|
{
|
|
appearance: 'info',
|
|
autoDismiss: true,
|
|
// @ts-ignore: works fine here, ignore
|
|
isdarktheme: `${isDarkTheme}`,
|
|
}
|
|
);
|
|
|
|
if (sharingSessionService.waitingForConnectionSharingSession !== null) {
|
|
const sharingSession =
|
|
sharingSessionService.waitingForConnectionSharingSession;
|
|
sharingSession.disconnectByHostMachineUser();
|
|
sharingSession.destory();
|
|
sharingSession.setStatus(SharingSessionStatusEnum.NOT_CONNECTED);
|
|
sharingSessionService.sharingSessions.delete(sharingSession.id);
|
|
}
|
|
}, [addToast, handleReset, isDarkTheme]);
|
|
|
|
const renderIntermediateOrSuccessStepContent = useCallback(() => {
|
|
return activeStep === steps.length ? (
|
|
<div style={{ width: '100%' }}>
|
|
<Zoom duration={300} when={isInterShow} style={{ width: '100%' }}>
|
|
<Row middle="xs" center="xs">
|
|
<SuccessStep handleReset={handleReset} />
|
|
</Row>
|
|
</Zoom>
|
|
</div>
|
|
) : (
|
|
<div id="intermediate-step-container" style={{ width: '100%' }}>
|
|
<Fade
|
|
duration={isProduction() ? 300 : 0}
|
|
when={isInterShow}
|
|
style={{ width: '100%' }}
|
|
>
|
|
<IntermediateStep
|
|
activeStep={activeStep}
|
|
steps={steps}
|
|
handleNext={handleNext}
|
|
handleBack={handleBack}
|
|
handleNextEntireScreen={handleNextEntireScreen}
|
|
handleNextApplicationWindow={handleNextApplicationWindow}
|
|
resetPendingConnectionDevice={
|
|
() => setPendingConnectionDevice(null)
|
|
// eslint-disable-next-line react/jsx-curly-newline
|
|
}
|
|
resetUserAllowedConnection={() => setIsUserAllowedConnection(false)}
|
|
/>
|
|
</Fade>
|
|
</div>
|
|
);
|
|
}, [
|
|
activeStep,
|
|
steps,
|
|
isInterShow,
|
|
handleReset,
|
|
handleNext,
|
|
handleBack,
|
|
handleNextEntireScreen,
|
|
handleNextApplicationWindow,
|
|
]);
|
|
|
|
const renderStepLabelContent = useCallback(
|
|
(label, idx) => {
|
|
return (
|
|
<StepLabel
|
|
id="step-label-deskreen"
|
|
className={classes.stepLabelContent}
|
|
StepIconComponent={ColorlibStepIcon}
|
|
StepIconProps={
|
|
{
|
|
isEntireScreenSelected,
|
|
isApplicationWindowSelected,
|
|
} as StepIconPropsDeskreen
|
|
}
|
|
>
|
|
{pendingConnectionDevice && idx === 0 && isUserAllowedConnection ? (
|
|
<DeviceConnectedInfoButton
|
|
device={pendingConnectionDevice}
|
|
onDisconnect={handleUserClickedDeviceDisconnectButton}
|
|
/>
|
|
) : (
|
|
<Text className="bp3-text-muted">{label}</Text>
|
|
)}
|
|
</StepLabel>
|
|
);
|
|
},
|
|
[
|
|
classes.stepLabelContent,
|
|
handleUserClickedDeviceDisconnectButton,
|
|
isApplicationWindowSelected,
|
|
isEntireScreenSelected,
|
|
isUserAllowedConnection,
|
|
pendingConnectionDevice,
|
|
]
|
|
);
|
|
|
|
return (
|
|
<>
|
|
<Row style={{ width: '100%' }}>
|
|
<Col xs={12}>
|
|
<Pulse top duration={isProduction() ? 1500 : 0}>
|
|
<Stepper
|
|
className={classes.stepperComponent}
|
|
activeStep={activeStep}
|
|
alternativeLabel
|
|
style={{ background: 'transparent' }}
|
|
connector={<ColorlibConnector />}
|
|
>
|
|
{steps.map((label, idx) => (
|
|
<Step key={label}>{renderStepLabelContent(label, idx)}</Step>
|
|
))}
|
|
</Stepper>
|
|
</Pulse>
|
|
</Col>
|
|
<Col className={classes.stepContent} xs={12}>
|
|
{renderIntermediateOrSuccessStepContent()}
|
|
</Col>
|
|
</Row>
|
|
<AllowConnectionForDeviceAlert
|
|
device={pendingConnectionDevice}
|
|
isOpen={isAlertOpen}
|
|
onCancel={handleCancelAlert}
|
|
onConfirm={handleConfirmAlert}
|
|
/>
|
|
</>
|
|
);
|
|
});
|
|
|
|
export default DeskreenStepper;
|