From 44e6b90d1a93998817b46663079698aaa7477c14 Mon Sep 17 00:00:00 2001 From: nick-delirium Date: Tue, 14 Feb 2023 17:24:05 +0100 Subject: [PATCH] fix(tracker/player): minor fixes for recording behavior --- .../ScreenRecorder/ScreenRecorder.tsx | 55 +++++++++++-------- frontend/app/date.ts | 2 +- frontend/app/utils/screenRecorder.ts | 11 ++-- .../src/ScreenRecordingState.ts | 15 +---- 4 files changed, 43 insertions(+), 40 deletions(-) diff --git a/frontend/app/components/Session_/ScreenRecorder/ScreenRecorder.tsx b/frontend/app/components/Session_/ScreenRecorder/ScreenRecorder.tsx index 9e9aa0ed3..b690669c8 100644 --- a/frontend/app/components/Session_/ScreenRecorder/ScreenRecorder.tsx +++ b/frontend/app/components/Session_/ScreenRecorder/ScreenRecorder.tsx @@ -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 (
{/* @ts-ignore */} - + @@ -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)); diff --git a/frontend/app/date.ts b/frontend/app/date.ts index a6162d671..eff9898b4 100644 --- a/frontend/app/date.ts +++ b/frontend/app/date.ts @@ -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(); diff --git a/frontend/app/utils/screenRecorder.ts b/frontend/app/utils/screenRecorder.ts index 705b72af5..a434f5d39 100644 --- a/frontend/app/utils/screenRecorder.ts +++ b/frontend/app/utils/screenRecorder.ts @@ -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) { diff --git a/tracker/tracker-assist/src/ScreenRecordingState.ts b/tracker/tracker-assist/src/ScreenRecordingState.ts index 4667590a8..a962e85ac 100644 --- a/tracker/tracker-assist/src/ScreenRecordingState.ts +++ b/tracker/tracker-assist/src/ScreenRecordingState.ts @@ -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)) } }