fix(tracker/player): minor fixes for recording behavior

This commit is contained in:
nick-delirium 2023-02-14 17:24:05 +01:00 committed by Taha Yassine Kraiem
parent e110659ee4
commit 1e2a5f2644
4 changed files with 43 additions and 40 deletions

View file

@ -8,7 +8,7 @@ let stopRecorderCb: () => void;
import { recordingsService } from 'App/services';
import { toast } from 'react-toastify';
import { formatTimeOrDate } from 'App/date';
import { PlayerContext } from 'App/components/Session/playerContext';
import { PlayerContext, ILivePlayerContext } from 'App/components/Session/playerContext';
import { observer } from 'mobx-react-lite';
/**
@ -24,9 +24,7 @@ function isSupported() {
if (agent.includes('edge') || agent.includes('edg/')) return true;
// @ts-ignore
if (agent.includes('chrome') && !!window.chrome) return true;
return false;
return agent.includes('chrome') && !!window.chrome;
}
const supportedBrowsers = ['Chrome v91+', 'Edge v90+'];
@ -41,8 +39,8 @@ function ScreenRecorder({
sessionId: string;
isEnterprise: boolean;
}) {
const { player, store } = React.useContext(PlayerContext)
const recordingState = store.get().recordingState
const { player, store } = React.useContext(PlayerContext) as ILivePlayerContext;
const recordingState = store.get().recordingState;
const [isRecording, setRecording] = React.useState(false);
@ -54,7 +52,7 @@ function ScreenRecorder({
try {
toast.warn('Uploading the recording...');
const { URL, key } = await recordingsService.reserveUrl(siteId, { ...saveObj, sessionId });
const status = recordingsService.saveFile(URL, blob);
const status = await recordingsService.saveFile(URL, blob);
if (status) {
await recordingsService.confirmFile(siteId, { ...saveObj, sessionId }, key);
@ -68,38 +66,49 @@ function ScreenRecorder({
React.useEffect(() => {
if (!isRecording && recordingState === SessionRecordingStatus.Recording) {
startRecording();
void startRecording();
}
if (isRecording && recordingState !== SessionRecordingStatus.Recording) {
stopRecordingHandler();
}
}, [recordingState, isRecording]);
const onStop = () => {
setRecording(false);
player.assistManager.stopRecording();
};
const startRecording = async () => {
const stop = await screenRecorder(
`${formatTimeOrDate(new Date().getTime(), undefined, true)}_${sessionId}`,
sessionId,
onSave
);
stopRecorderCb = stop;
setRecording(true);
try {
// @ts-ignore
stopRecorderCb = await screenRecorder(
`${formatTimeOrDate(new Date().getTime(), undefined, true)}_${sessionId}`,
sessionId,
onSave,
onStop
);
setRecording(true);
} catch (e) {
console.error(e);
}
};
const stopRecordingHandler = () => {
player.assistManager.stopRecording();
stopRecorderCb?.();
setRecording(false);
onStop();
};
const recordingRequest = () => {
player.assistManager.requestRecording()
player.assistManager.requestRecording();
};
if (!isSupported() || !isEnterprise) {
return (
<div className="p-2">
{/* @ts-ignore */}
<Tooltip title={isEnterprise ? supportedMessage : 'This feature requires an enterprise license.'}>
<Tooltip
title={isEnterprise ? supportedMessage : 'This feature requires an enterprise license.'}
>
<Button icon="record-circle" disabled variant="text-primary">
Record Activity
</Button>
@ -121,7 +130,7 @@ function ScreenRecorder({
}
export default connect((state: any) => ({
isEnterprise: state.getIn(['user', 'account', 'edition']) === 'ee',
siteId: state.getIn(['site', 'siteId']),
sessionId: state.getIn(['sessions', 'current']).sessionId,
}))(observer(ScreenRecorder))
isEnterprise: state.getIn(['user', 'account', 'edition']) === 'ee',
siteId: state.getIn(['site', 'siteId']),
sessionId: state.getIn(['sessions', 'current']).sessionId,
}))(observer(ScreenRecorder));

View file

@ -82,7 +82,7 @@ export function formatDateTimeDefault(timestamp: number): string {
* @param {Object} timezone fixed offset like UTC+6
* @returns {String} formatted date (or time if its today)
*/
export function formatTimeOrDate(timestamp: number, timezone: Timezone, isFull = false): string {
export function formatTimeOrDate(timestamp: number, timezone?: Timezone, isFull = false): string {
var date = DateTime.fromMillis(timestamp)
if (timezone) {
if (timezone.value === 'UTC') date = date.toUTC();

View file

@ -6,7 +6,8 @@ function createFileRecorder(
mimeType: string,
recName: string,
sessionId: string,
saveCb: Function
saveCb: (saveObj: { name: string; duration: number }, blob: Blob) => void,
onStop: () => void
) {
let ended = false;
const start = new Date().getTime();
@ -26,6 +27,7 @@ function createFileRecorder(
ended = true;
saveFile(recordedChunks, mimeType, start, recName, sessionId, saveCb);
onStop()
recordedChunks = [];
}
@ -48,7 +50,7 @@ function saveFile(
startDate: number,
recName: string,
sessionId: string,
saveCb: Function
saveCb: (saveObj: { name: string; duration: number }, blob: Blob) => void
) {
const saveObject = { name: recName, duration: new Date().getTime() - startDate, sessionId };
@ -90,14 +92,15 @@ async function recordScreen() {
*
* @returns a promise that resolves to a function that stops the recording
*/
export async function screenRecorder(recName: string, sessionId: string, saveCb: Function) {
export async function screenRecorder(recName: string, sessionId: string, saveCb: (saveObj: { name: string; duration: number }, blob: Blob) => void, onStop: () => void) {
try {
const stream = await recordScreen();
const mediaRecorder = createFileRecorder(stream, FILE_TYPE, recName, sessionId, saveCb);
const mediaRecorder = createFileRecorder(stream, FILE_TYPE, recName, sessionId, saveCb, onStop);
return () => {
if (mediaRecorder.state !== 'inactive') {
mediaRecorder.stop();
onStop()
}
}
} catch (e) {

View file

@ -36,7 +36,7 @@ export default class ScreenRecordingState {
private status = RecordingState.Off
private recordingAgent: string
private overlayAdded = false
private uiComponents: [HTMLDivElement, HTMLDivElement]
private uiComponents: [HTMLDivElement]
constructor(private readonly confirmOptions: ConfirmOptions) { }
@ -79,16 +79,6 @@ export default class ScreenRecordingState {
private readonly acceptRecording = () => {
if (!this.overlayAdded) {
const stopButton = window.document.createElement('div')
stopButton.onclick = () => this.rejectRecording()
Object.assign(stopButton.style, buttonStyles)
stopButton.textContent = 'Stop Recording'
stopButton.className = 'or-recording-button'
stopButton.setAttribute('data-openreplay-obscured', '')
stopButton.setAttribute('data-openreplay-hidden', '')
stopButton.setAttribute('data-openreplay-ignore', '')
window.document.body.appendChild(stopButton)
const borderWindow = window.document.createElement('div')
Object.assign(borderWindow.style, borderStyles)
borderWindow.className = 'or-recording-border'
@ -99,7 +89,7 @@ export default class ScreenRecordingState {
this.overlayAdded = true
this.uiComponents = [stopButton, borderWindow,]
this.uiComponents = [borderWindow,]
}
this.status = RecordingState.Recording
}
@ -118,6 +108,7 @@ export default class ScreenRecordingState {
this.confirm?.remove()
this.status = RecordingState.Off
this.overlayAdded = false
this.uiComponents.forEach((el) => el.parentElement?.removeChild(el))
}
}