From 82604020ab57f08afb33d9b1df7e8e02e6b7fd5c Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Tue, 27 Oct 2020 05:16:10 -0700 Subject: [PATCH] Support screenshot buttons Summary: Added Sandy styling to `CaptureButtons`, and converted to hooks while at it Reviewed By: cekkaewnumchai Differential Revision: D24538953 fbshipit-source-id: cfb9a9b856ada40eb96b77d2e5e6ea780971d0ce --- .../app/src/chrome/ScreenCaptureButtons.tsx | 210 ++++++++---------- .../sandy-chrome/appinspect/AppInspect.tsx | 21 +- 2 files changed, 108 insertions(+), 123 deletions(-) diff --git a/desktop/app/src/chrome/ScreenCaptureButtons.tsx b/desktop/app/src/chrome/ScreenCaptureButtons.tsx index 9f1f67753..7bdb2aef4 100644 --- a/desktop/app/src/chrome/ScreenCaptureButtons.tsx +++ b/desktop/app/src/chrome/ScreenCaptureButtons.tsx @@ -7,28 +7,14 @@ * @format */ +import {Button as AntButton, message} from 'antd'; import {Button, ButtonGroup} from '../ui'; -import React, {Component} from 'react'; -import {connect} from 'react-redux'; +import React, {useState, useEffect, useCallback} from 'react'; import path from 'path'; -import BaseDevice from '../devices/BaseDevice'; -import {State as Store} from '../reducers'; import open from 'open'; import {capture, CAPTURE_LOCATION, getFileName} from '../utils/screenshot'; - -type OwnProps = {}; - -type StateFromProps = { - selectedDevice: BaseDevice | null | undefined; -}; - -type DispatchFromProps = {}; - -type State = { - recording: boolean; - recordingEnabled: boolean; - capturingScreenshot: boolean; -}; +import {CameraOutlined, VideoCameraOutlined} from '@ant-design/icons'; +import {useStore} from '../utils/useStore'; export async function openFile(path: string | null) { if (!path) { @@ -42,111 +28,101 @@ export async function openFile(path: string | null) { } } -type Props = OwnProps & StateFromProps & DispatchFromProps; -class ScreenCaptureButtons extends Component { - videoPath: string | null | undefined; +export default function ScreenCaptureButtons({useSandy}: {useSandy?: boolean}) { + const selectedDevice = useStore((state) => state.connections.selectedDevice); + const [isTakingScreenshot, setIsTakingScreenshot] = useState(false); + const [isRecordingAvailable, setIsRecordingAvailable] = useState(false); + const [isRecording, setIsRecording] = useState(false); - state = { - recording: false, - recordingEnabled: false, - capturingScreenshot: false, - }; - - componentDidMount() { - this.checkIfRecordingIsAvailable(); - } - - UNSAFE_componentWillReceiveProps(nextProps: Props) { - if (nextProps.selectedDevice !== this.props.selectedDevice) { - this.checkIfRecordingIsAvailable(nextProps); - } - } - - checkIfRecordingIsAvailable = async (props: Props = this.props) => { - const {selectedDevice} = props; - const recordingEnabled = selectedDevice - ? await selectedDevice.screenCaptureAvailable() - : false; - this.setState({recordingEnabled}); - }; - - captureScreenshot: Promise | any = async () => { - const {selectedDevice} = this.props; - if (selectedDevice != null) { - await capture(selectedDevice) - .then(openFile) - .catch((e) => console.error('Taking screenshot failed:', e)); - } - }; - - startRecording = async () => { - const {selectedDevice} = this.props; - if (!selectedDevice) { - return; - } - const videoPath = path.join(CAPTURE_LOCATION, getFileName('mp4')); - return selectedDevice.startScreenCapture(videoPath); - }; - - stopRecording = async () => { - const {selectedDevice} = this.props; - if (!selectedDevice) { - return; - } - const path = await selectedDevice.stopScreenCapture().catch((e) => { - console.error(e); + useEffect(() => { + let cancelled = false; + selectedDevice?.screenCaptureAvailable().then((result) => { + if (!cancelled) { + setIsRecordingAvailable(result); + } }); - path ? openFile(path) : 0; - }; + return () => { + cancelled = true; + }; + }, [selectedDevice]); - onRecordingClicked = () => { - if (this.state.recording) { - this.stopRecording(); - this.setState({ - recording: false, + const handleScreenshot = useCallback(() => { + setIsTakingScreenshot(true); + capture(selectedDevice!) + .then(openFile) + .catch((e) => { + console.error('Taking screenshot failed:', e); + message.error('Taking screenshot failed:' + e); + }) + .finally(() => { + setIsTakingScreenshot(false); + }); + }, [selectedDevice]); + const handleRecording = useCallback(() => { + if (!selectedDevice) { + return; + } + if (!isRecording) { + setIsRecording(true); + const videoPath = path.join(CAPTURE_LOCATION, getFileName('mp4')); + selectedDevice.startScreenCapture(videoPath).catch((e) => { + console.error('Failed to start recording', e); + message.error('Failed to start recording' + e); + setIsRecording(false); }); } else { - this.setState({ - recording: true, - }); - this.startRecording().catch((e) => { - this.setState({ - recording: false, + selectedDevice + .stopScreenCapture() + .then((path) => { + path && openFile(path); + }) + .catch((e) => { + console.error('Failed to start recording', e); + message.error('Failed to start recording' + e); + }) + .finally(() => { + setIsRecording(false); }); - console.error(e); - }); } - }; + }, [selectedDevice, isRecording]); - render() { - const {recordingEnabled} = this.state; - const {selectedDevice} = this.props; - - return ( - -