Set device features on device initialization
Summary: 1. Identify if device supports screenshots/screen recording when it is created. 2. Disable screen recording/screenshot buttons when they are not supported Reviewed By: passy Differential Revision: D34611133 fbshipit-source-id: 82ad2d67e4af482d9becf7995187667b5d99bc36
This commit is contained in:
committed by
Facebook GitHub Bot
parent
04e7c7282b
commit
6c74f2dd18
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
import {Button as AntButton, message} from 'antd';
|
||||
import React, {useState, useEffect, useCallback} from 'react';
|
||||
import React, {useState, useCallback} from 'react';
|
||||
import {capture, getCaptureLocation, getFileName} from '../utils/screenshot';
|
||||
import {CameraOutlined, VideoCameraOutlined} from '@ant-design/icons';
|
||||
import {useStore} from '../utils/useStore';
|
||||
@@ -22,21 +22,8 @@ async function openFile(path: string) {
|
||||
export default function ScreenCaptureButtons() {
|
||||
const selectedDevice = useStore((state) => state.connections.selectedDevice);
|
||||
const [isTakingScreenshot, setIsTakingScreenshot] = useState(false);
|
||||
const [isRecordingAvailable, setIsRecordingAvailable] = useState(false);
|
||||
const [isRecording, setIsRecording] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let canceled = false;
|
||||
selectedDevice?.screenCaptureAvailable().then((result) => {
|
||||
if (!canceled) {
|
||||
setIsRecordingAvailable(result);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
canceled = true;
|
||||
};
|
||||
}, [selectedDevice]);
|
||||
|
||||
const handleScreenshot = useCallback(() => {
|
||||
setIsTakingScreenshot(true);
|
||||
return capture(selectedDevice!)
|
||||
@@ -87,7 +74,10 @@ export default function ScreenCaptureButtons() {
|
||||
title="Take Screenshot"
|
||||
type="ghost"
|
||||
onClick={handleScreenshot}
|
||||
disabled={!selectedDevice}
|
||||
disabled={
|
||||
!selectedDevice ||
|
||||
!selectedDevice.description.features.screenshotAvailable
|
||||
}
|
||||
loading={isTakingScreenshot}
|
||||
/>
|
||||
<AntButton
|
||||
@@ -95,7 +85,10 @@ export default function ScreenCaptureButtons() {
|
||||
title="Make Screen Recording"
|
||||
type={isRecording ? 'primary' : 'ghost'}
|
||||
onClick={handleRecording}
|
||||
disabled={!selectedDevice || !isRecordingAvailable}
|
||||
disabled={
|
||||
!selectedDevice ||
|
||||
!selectedDevice.description.features.screenCaptureAvailable
|
||||
}
|
||||
danger={isRecording}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -25,14 +25,12 @@ type DispatchFromProps = {};
|
||||
|
||||
type State = {
|
||||
recording: boolean;
|
||||
recordingEnabled: boolean;
|
||||
};
|
||||
type Props = OwnProps & StateFromProps & DispatchFromProps;
|
||||
|
||||
export default class VideoRecordingButton extends Component<Props, State> {
|
||||
state: State = {
|
||||
recording: false,
|
||||
recordingEnabled: true,
|
||||
};
|
||||
|
||||
startRecording = async () => {
|
||||
@@ -80,7 +78,6 @@ export default class VideoRecordingButton extends Component<Props, State> {
|
||||
}
|
||||
};
|
||||
render() {
|
||||
const {recordingEnabled} = this.state;
|
||||
const {selectedDevice} = this.props;
|
||||
return (
|
||||
<Button
|
||||
@@ -89,7 +86,10 @@ export default class VideoRecordingButton extends Component<Props, State> {
|
||||
pulse={this.state.recording}
|
||||
selected={this.state.recording}
|
||||
title="Make Screen Recording"
|
||||
disabled={!selectedDevice || !recordingEnabled}
|
||||
disabled={
|
||||
!selectedDevice ||
|
||||
!selectedDevice.description.features.screenCaptureAvailable
|
||||
}
|
||||
type={this.state.recording ? 'danger' : 'primary'}>
|
||||
<Glyph
|
||||
name={this.state.recording ? 'stop-playback' : 'camcorder'}
|
||||
|
||||
@@ -45,6 +45,10 @@ export default class ArchivedDevice extends BaseDevice {
|
||||
os: options.os,
|
||||
serial: options.serial,
|
||||
icon: 'box',
|
||||
features: {
|
||||
screenCaptureAvailable: false,
|
||||
screenshotAvailable: false,
|
||||
},
|
||||
},
|
||||
);
|
||||
this.connected.set(false);
|
||||
|
||||
@@ -235,32 +235,15 @@ export default class BaseDevice implements Device {
|
||||
return this.flipperServer.exec('device-navigate', this.serial, location);
|
||||
}
|
||||
|
||||
async screenshotAvailable(): Promise<boolean> {
|
||||
if (this.isArchived) {
|
||||
return false;
|
||||
}
|
||||
return this.flipperServer.exec('device-supports-screenshot', this.serial);
|
||||
}
|
||||
|
||||
async screenshot(): Promise<Uint8Array> {
|
||||
if (this.isArchived) {
|
||||
return new Uint8Array();
|
||||
async screenshot(): Promise<Uint8Array | undefined> {
|
||||
if (!this.description.features.screenshotAvailable || this.isArchived) {
|
||||
return;
|
||||
}
|
||||
return Base64.toUint8Array(
|
||||
await this.flipperServer.exec('device-take-screenshot', this.serial),
|
||||
);
|
||||
}
|
||||
|
||||
async screenCaptureAvailable(): Promise<boolean> {
|
||||
if (this.isArchived) {
|
||||
return false;
|
||||
}
|
||||
return this.flipperServer.exec(
|
||||
'device-supports-screencapture',
|
||||
this.serial,
|
||||
);
|
||||
}
|
||||
|
||||
async startScreenCapture(destination: string): Promise<void> {
|
||||
return this.flipperServer.exec(
|
||||
'device-start-screencapture',
|
||||
|
||||
@@ -26,6 +26,10 @@ export class TestDevice extends BaseDevice {
|
||||
title,
|
||||
os,
|
||||
specs,
|
||||
features: {
|
||||
screenCaptureAvailable: false,
|
||||
screenshotAvailable: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import BaseDevice from '../devices/BaseDevice';
|
||||
import {reportPlatformFailures} from 'flipper-common';
|
||||
import {getRenderHostInstance} from '../RenderHost';
|
||||
import {getFlipperLib, path} from 'flipper-plugin';
|
||||
import {assertNotNull} from './assertNotNull';
|
||||
|
||||
export function getCaptureLocation() {
|
||||
return (
|
||||
@@ -27,7 +28,7 @@ export function getFileName(extension: 'png' | 'mp4'): string {
|
||||
|
||||
export async function capture(device: BaseDevice): Promise<string> {
|
||||
if (!device.connected.get()) {
|
||||
console.log('Skipping screenshot for disconnected device');
|
||||
console.info('Skipping screenshot for disconnected device');
|
||||
return '';
|
||||
}
|
||||
const pngPath = path.join(getCaptureLocation(), getFileName('png'));
|
||||
@@ -36,9 +37,16 @@ export async function capture(device: BaseDevice): Promise<string> {
|
||||
// again to write in a file, probably easier to change screenshot api to `device.screenshot(): path`
|
||||
device
|
||||
.screenshot()
|
||||
.then((buffer) =>
|
||||
getFlipperLib().remoteServerContext.fs.writeFileBinary(pngPath, buffer),
|
||||
)
|
||||
.then((buffer) => {
|
||||
assertNotNull(
|
||||
buffer,
|
||||
`Device ${device.description.deviceType}:${device.description.os} does not support taking screenshots`,
|
||||
);
|
||||
return getFlipperLib().remoteServerContext.fs.writeFileBinary(
|
||||
pngPath,
|
||||
buffer,
|
||||
);
|
||||
})
|
||||
.then(() => pngPath),
|
||||
'captureScreenshot',
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user