change(tracker): add confirmation state for recording, borders around screen etc
This commit is contained in:
parent
249e731569
commit
3ee4da6190
3 changed files with 105 additions and 1 deletions
|
|
@ -150,6 +150,7 @@ export default class AssistManager {
|
|||
const now = +new Date()
|
||||
this.store.update({ assistStart: now })
|
||||
|
||||
// @ts-ignore
|
||||
import('socket.io-client').then(({ default: io }) => {
|
||||
if (this.cleaned) { return }
|
||||
if (this.socket) { this.socket.close() } // TODO: single socket connection
|
||||
|
|
@ -395,6 +396,8 @@ export default class AssistManager {
|
|||
|
||||
// @ts-ignore
|
||||
const urlObject = new URL(window.env.API_EDP || window.location.origin)
|
||||
|
||||
// @ts-ignore TODO: set module in ts settings
|
||||
return import('peerjs').then(({ default: Peer }) => {
|
||||
if (this.cleaned) {return Promise.reject("Already cleaned")}
|
||||
const peerOpts: Peer.PeerJSOption = {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import AnnotationCanvas from './AnnotationCanvas.js'
|
|||
import ConfirmWindow from './ConfirmWindow/ConfirmWindow.js'
|
||||
import { callConfirmDefault, } from './ConfirmWindow/defaults.js'
|
||||
import type { Options as ConfirmOptions, } from './ConfirmWindow/defaults.js'
|
||||
import ScreenRecordingState, { RecordingState, } from './ScreenRecordingState'
|
||||
|
||||
// TODO: fully specified strict check with no-any (everywhere)
|
||||
|
||||
|
|
@ -21,6 +22,7 @@ export interface Options {
|
|||
onAgentConnect: StartEndCallback;
|
||||
onCallStart: StartEndCallback;
|
||||
onRemoteControlStart: StartEndCallback;
|
||||
onRecordingRequest?: (agentInfo: Record<string, any>) => any;
|
||||
session_calling_peer_key: string;
|
||||
session_control_peer_key: string;
|
||||
callConfirm: ConfirmOptions;
|
||||
|
|
@ -144,6 +146,7 @@ export default class Assist {
|
|||
private onStart() {
|
||||
const app = this.app
|
||||
const sessionId = app.getSessionID()
|
||||
|
||||
if (!sessionId) {
|
||||
return app.debug.error('No session ID')
|
||||
}
|
||||
|
|
@ -199,6 +202,14 @@ export default class Assist {
|
|||
},
|
||||
)
|
||||
|
||||
const onAcceptRecording = () => {
|
||||
socket.emit('recording_accepted')
|
||||
}
|
||||
const onDenyRecording = () => {
|
||||
socket.emit('recording_denied')
|
||||
}
|
||||
const recordingState = new ScreenRecordingState(onAcceptRecording, onDenyRecording)
|
||||
setTimeout(() => recordingState.requestRecording(), 5000)
|
||||
// TODO: check incoming args
|
||||
socket.on('request_control', this.remoteControl.requestControl)
|
||||
socket.on('release_control', this.remoteControl.releaseControl)
|
||||
|
|
@ -231,7 +242,7 @@ export default class Assist {
|
|||
ids.forEach(id =>{
|
||||
const agentInfo = this.agents[id]?.agentInfo
|
||||
this.agents[id] = {
|
||||
agentInfo,
|
||||
...this.agents[id],
|
||||
onDisconnect: this.options.onAgentConnect?.(agentInfo),
|
||||
}
|
||||
})
|
||||
|
|
@ -269,6 +280,12 @@ export default class Assist {
|
|||
socket.on('videofeed', (id, feedState) => {
|
||||
callUI?.toggleVideoStream(feedState)
|
||||
})
|
||||
socket.on('request_recording', (id, agentData) => {
|
||||
if (recordingState.status === RecordingState.Off) {
|
||||
console.log('requested screen recording', this.agents[id].agentInfo, agentData)
|
||||
this.options.onRecordingRequest?.(agentData)
|
||||
}
|
||||
})
|
||||
|
||||
const callingAgents: Map<string, string> = new Map() // !! uses socket.io ID
|
||||
// TODO: merge peerId & socket.io id (simplest way - send peerId with the name)
|
||||
|
|
|
|||
84
tracker/tracker-assist/src/ScreenRecordingState.ts
Normal file
84
tracker/tracker-assist/src/ScreenRecordingState.ts
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
export enum RecordingState {
|
||||
Off,
|
||||
Requested,
|
||||
Recording,
|
||||
}
|
||||
|
||||
const defaultStyles = '2px dashed red; position: fixed;'
|
||||
const leftTop = 'left: 0; top: 0'
|
||||
const bottomRight = 'right: 0; bottom: 0'
|
||||
|
||||
const borderEmulationStyles = {
|
||||
left: `${leftTop}; height: 100vh; width: 0; border-left: ${defaultStyles}`,
|
||||
top: `${leftTop}; height: 0; width: 100vw; border-top: ${defaultStyles}`,
|
||||
right: `${bottomRight}; height: 100vh; width: 0; border-right: ${defaultStyles}`,
|
||||
bottom: `${bottomRight}; height: 0; width: 100vw; border-bottom: ${defaultStyles}`,
|
||||
}
|
||||
|
||||
export default class ScreenRecordingState {
|
||||
public status = RecordingState.Off
|
||||
|
||||
constructor(
|
||||
private readonly onAccept: () => void,
|
||||
private readonly onDeny: () => void,
|
||||
) {}
|
||||
|
||||
public requestRecording = () => {
|
||||
// mount recording window
|
||||
if (this.status !== RecordingState.Off) return
|
||||
this.status = RecordingState.Requested
|
||||
|
||||
// todo: change timeout to deny after testing
|
||||
setTimeout(() => {
|
||||
console.log('starting recording')
|
||||
this.acceptRecording()
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
private readonly acceptRecording = () => {
|
||||
const borders = {
|
||||
left: window.document.createElement('div'),
|
||||
top: window.document.createElement('div'),
|
||||
right: window.document.createElement('div'),
|
||||
bottom: window.document.createElement('div'),
|
||||
}
|
||||
|
||||
const stopButton = window.document.createElement('div')
|
||||
stopButton.onclick = this.denyRecording
|
||||
const buttonStyle = 'position: fixed; bottom: 0; left: calc(50vw - 10px); padding: 4px; background: blue; border-radius: 6px; text-align: center;'
|
||||
buttonStyle.split(';').forEach(styleEntry => {
|
||||
console.log(styleEntry)
|
||||
const styleKeyVal = styleEntry.split(':')
|
||||
stopButton.style[styleKeyVal[0]] = styleKeyVal[1]
|
||||
})
|
||||
stopButton.textContent = 'Stop Recording'
|
||||
stopButton.id = 'or-recording-border'
|
||||
|
||||
Object.entries(borderEmulationStyles).forEach(([key, style,]) => {
|
||||
const styleEntries = style.split(';')
|
||||
styleEntries.forEach(styleEntry => {
|
||||
console.log(styleEntry)
|
||||
const styleKeyVal = styleEntry.split(':')
|
||||
borders[key].style[styleKeyVal[0]] = styleKeyVal[1]
|
||||
})
|
||||
borders[key].style = style
|
||||
borders[key].id = 'or-recording-border'
|
||||
|
||||
window.document.appendChild(borders[key])
|
||||
})
|
||||
window.document.appendChild(stopButton)
|
||||
|
||||
this.onAccept()
|
||||
this.status = RecordingState.Recording
|
||||
}
|
||||
|
||||
private readonly denyRecording = () => {
|
||||
this.onDeny()
|
||||
this.status = RecordingState.Off
|
||||
|
||||
const borders = window.document.querySelectorAll('#or-recording-border')
|
||||
if (borders.length > 0) {
|
||||
borders.forEach(border => border.parentElement?.removeChild(border))
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue