Screen capture unique file names and location

Summary: Screen captures now have unique names, so they don't get overwritten. By default they are saved to the desktop, but the path can be overwritten by setting `screenCapturePath` in `~/.sonar/config.js`

Reviewed By: jknoxville

Differential Revision: D9120822

fbshipit-source-id: ab6880eac475da3839f08c6e644c16bdc8693647
This commit is contained in:
Daniel Büchele
2018-08-01 11:11:48 -07:00
committed by Facebook Github Bot
parent d2708d4982
commit 06e70a1555
2 changed files with 46 additions and 33 deletions

View File

@@ -12,17 +12,18 @@ import IOSDevice from '../devices/IOSDevice';
import os from 'os';
import fs from 'fs';
import adb from 'adbkit-fb';
import path from 'path';
import {exec} from 'child_process';
import {remote} from 'electron';
import path from 'path';
const SCREENSHOT_FILE_NAME = 'screen.png';
const VIDEO_FILE_NAME = 'video.mp4';
const SCREENSHOT_PATH = path.join(
os.homedir(),
'/.sonar/',
SCREENSHOT_FILE_NAME,
);
const VIDEO_PATH = path.join(os.homedir(), '.sonar', VIDEO_FILE_NAME);
let CAPTURE_LOCATION = remote.app.getPath('desktop');
try {
CAPTURE_LOCATION =
JSON.parse(window.process.env.CONFIG).screenCapturePath.replace(
/^~/,
os.homedir(),
) || CAPTURE_LOCATION;
} catch (e) {}
import type BaseDevice from '../devices/BaseDevice';
@@ -39,9 +40,9 @@ type State = {|
capturingScreenshot: boolean,
|};
function openFile(path: string): Promise<*> {
function openFile(path: string): Promise<string> {
return new Promise((resolve, reject) => {
exec(`${getOpenCommand()} ${path}`, (error, stdout, stderr) => {
exec(`${getOpenCommand()} "${path}"`, (error, stdout, stderr) => {
if (error) {
reject(error);
} else {
@@ -63,18 +64,24 @@ function getOpenCommand(): string {
}
}
function getFileName(extension: 'png' | 'mp4'): string {
return `Screen Capture ${new Date().toISOString()}.${extension}`;
}
function writePngStreamToFile(stream: PullTransfer): Promise<string> {
return new Promise((resolve, reject) => {
const pngPath = path.join(CAPTURE_LOCATION, getFileName('png'));
stream.on('end', () => {
resolve(SCREENSHOT_PATH);
resolve(pngPath);
});
stream.on('error', reject);
stream.pipe(fs.createWriteStream(SCREENSHOT_PATH));
stream.pipe(fs.createWriteStream(pngPath));
});
}
class ScreenCaptureButtons extends Component<Props, State> {
iOSRecorder: ?any;
videoPath: ?string;
state = {
pullingData: false,
@@ -117,7 +124,7 @@ class ScreenCaptureButtons extends Component<Props, State> {
}
};
captureScreenshot = () => {
captureScreenshot = (): ?Promise<string> => {
const {selectedDevice} = this.props;
if (selectedDevice instanceof AndroidDevice) {
@@ -127,29 +134,33 @@ class ScreenCaptureButtons extends Component<Props, State> {
.then(openFile)
.catch(console.error);
} else if (selectedDevice instanceof IOSDevice) {
exec(
`xcrun simctl io booted screenshot ${SCREENSHOT_PATH}`,
(err, data) => {
if (err) {
console.error(err);
} else {
openFile(SCREENSHOT_PATH);
}
},
);
const screenshotPath = path.join(CAPTURE_LOCATION, getFileName('png'));
return new Promise((resolve, reject) => {
exec(
`xcrun simctl io booted screenshot "${screenshotPath}"`,
async (err, data) => {
if (err) {
reject(err);
} else {
resolve(await openFile(screenshotPath));
}
},
);
});
}
};
startRecording = () => {
const {selectedDevice} = this.props;
const videoPath = path.join(CAPTURE_LOCATION, getFileName('mp4'));
this.videoPath = videoPath;
if (selectedDevice instanceof AndroidDevice) {
this.setState({
recording: true,
});
this.executeShell(
selectedDevice,
`screenrecord --bugreport /sdcard/${VIDEO_FILE_NAME}`,
`screenrecord --bugreport /sdcard/video.mp4`,
)
.then(output => {
if (output) {
@@ -166,14 +177,14 @@ class ScreenCaptureButtons extends Component<Props, State> {
(): Promise<string> => {
return this.pullFromDevice(
selectedDevice,
`/sdcard/${VIDEO_FILE_NAME}`,
VIDEO_PATH,
`/sdcard/video.mp4`,
videoPath,
);
},
)
.then(openFile)
.then(() => {
this.executeShell(selectedDevice, `rm /sdcard/${VIDEO_FILE_NAME}`);
this.executeShell(selectedDevice, `rm /sdcard/video.mp4`);
})
.then(() => {
this.setState({
@@ -192,7 +203,7 @@ class ScreenCaptureButtons extends Component<Props, State> {
recording: true,
});
this.iOSRecorder = exec(
`xcrun simctl io booted recordVideo ${VIDEO_PATH}`,
`xcrun simctl io booted recordVideo "${videoPath}"`,
);
}
};
@@ -214,16 +225,18 @@ class ScreenCaptureButtons extends Component<Props, State> {
};
stopRecording = () => {
const {videoPath} = this;
const {selectedDevice} = this.props;
this.videoPath = null;
if (selectedDevice instanceof AndroidDevice) {
this.executeShell(selectedDevice, `pgrep 'screenrecord' -L 2`);
} else if (this.iOSRecorder) {
} else if (this.iOSRecorder && videoPath) {
this.iOSRecorder.kill();
this.setState({
recording: false,
});
openFile(VIDEO_PATH);
openFile(videoPath);
}
};

View File

@@ -163,7 +163,7 @@ type Props = {
/**
* onClick handler.
*/
onClick?: (event: SyntheticMouseEvent<>) => void,
onClick?: (event: SyntheticMouseEvent<>) => any,
/**
* Whether this button is disabled.
*/