fix(tracker/player): minor fixes for recording behavior
This commit is contained in:
parent
e110659ee4
commit
1e2a5f2644
4 changed files with 43 additions and 40 deletions
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue