aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Foiani <sotech117@michaels-mbp-5.devices.brown.edu>2022-06-13 14:57:34 -0400
committerMichael Foiani <sotech117@michaels-mbp-5.devices.brown.edu>2022-06-13 14:57:34 -0400
commitc7e4bf8c4e19669666cce610020969cf0d865e49 (patch)
tree5bce1f51bc61df39337ee5e4c1e3b830d2e034e9 /src
parentf8bfda0b0139db5f8bf1de602ce211a091d5d9ef (diff)
Revert "debug w bob"
This reverts commit 1dfb694ffa8f34a834387eb073ffb9bd3a678039. return to stable version without printing the logs.
Diffstat (limited to 'src')
-rw-r--r--src/client/util/RecordingApi.ts385
-rw-r--r--src/client/views/nodes/RecordingBox/RecordingBox.tsx2
-rw-r--r--src/client/views/nodes/RecordingBox/RecordingView.tsx29
3 files changed, 186 insertions, 230 deletions
diff --git a/src/client/util/RecordingApi.ts b/src/client/util/RecordingApi.ts
index 4c8f55ce5..d56093cee 100644
--- a/src/client/util/RecordingApi.ts
+++ b/src/client/util/RecordingApi.ts
@@ -5,10 +5,10 @@ import { Doc } from "../../fields/Doc";
import { VideoBox } from "../views/nodes/VideoBox";
type Movement = {
- time: number,
- panX: number,
- panY: number,
- scale: number,
+ time: number,
+ panX: number,
+ panY: number,
+ scale: number,
}
export type Presentation = {
@@ -20,10 +20,9 @@ export type Presentation = {
export class RecordingApi {
private static get NULL_PRESENTATION(): Presentation {
- return { movements: null, meta: {}, totalTime: -1,}
+ return { movements: null, meta: {}, totalTime: -1, }
}
-<<<<<<< HEAD
// instance variables
private currentPresentation: Presentation;
private tracking: boolean;
@@ -49,78 +48,54 @@ export class RecordingApi {
// for now, set playFFView
this.playFFView = null;
this.timers = null;
+
+ // put a pointerdown event on the doucment to see what the target
}
-=======
- // instance variables
- private currentPresentation: Presentation;
- private tracking: boolean;
- private absoluteStart: number;
-
-
- // create static instance and getter for global use
- @observable static _instance: RecordingApi;
- public static get Instance(): RecordingApi { return RecordingApi._instance }
- public constructor() {
- // init the global instance
- RecordingApi._instance = this;
-
- // init the instance variables
- this.currentPresentation = RecordingApi.NULL_PRESENTATION
- this.tracking = false;
- this.absoluteStart = -1;
-
- // used for tracking movements in the view frame
- this.disposeFunc = null;
- this.recordingFFView = null;
-
- // for now, set playFFView
- this.playFFView = null;
- this.timers = null;
-
- // put a pointerdown event on the doucment to see what the target
- }
->>>>>>> parent of d91ff1f93 (fix bugs with selecting tracking. very stable now.)
- // little helper :)
- private get isInitPresenation(): boolean {
- return this.currentPresentation.movements === null
- }
+ // little helper :)
+ private get nullPresentation(): boolean {
+ return this.currentPresentation.movements === null
+ }
- public start = (meta?: Object) => {
- // update the presentation mode
- Doc.UserDoc().presentationMode = 'recording';
-
- // (1a) get start date for presenation
- const startDate = new Date();
- // (1b) set start timestamp to absolute timestamp
- this.absoluteStart = startDate.getTime();
-
- // (2) assign meta content if it exists
- this.currentPresentation.meta = meta || {}
- // (3) assign start date to currentPresenation
- this.currentPresentation.movements = []
- // (4) set tracking true to allow trackMovements
- this.tracking = true
- }
+ public start = (meta?: Object) => {
+ // update the presentation mode
+ Doc.UserDoc().presentationMode = 'recording';
+
+ // (1a) get start date for presenation
+ const startDate = new Date();
+ // (1b) set start timestamp to absolute timestamp
+ this.absoluteStart = startDate.getTime();
+
+ // (2) assign meta content if it exists
+ this.currentPresentation.meta = meta || {}
+ // (3) assign start date to currentPresenation
+ this.currentPresentation.movements = []
+ // (4) set tracking true to allow trackMovements
+ this.tracking = true
+ }
- /* stops the video and returns the presentatation; if no presentation, returns undefined */
- public * yieldPresentation(clearData: boolean = true): Generator<Presentation | null> {
+ /* stops the video and returns the presentatation; if no presentation, returns undefined */
+ public yieldPresentation(clearData: boolean = true): Presentation | null {
// if no presentation or done tracking, return null
- if (!this.isInitPresenation || !this.tracking) return null;
+ if (this.nullPresentation || !this.tracking) return null;
// set the previus recording view to the play view
this.playFFView = this.recordingFFView;
// ensure we add the endTime now that they are done recording
- yield { ...this.currentPresentation, totalTime: new Date().getTime() - this.absoluteStart };
+ const cpy = { ...this.currentPresentation, totalTime: new Date().getTime() - this.absoluteStart };
// reset the current presentation
clearData && this.clear();
+
+ return cpy;
}
- public stop = (): void => {
+ public finish = (): void => {
// make is tracking false
this.tracking = false
+ // reset the RecordingApi instance
+ this.clear();
}
public clear = (): void => {
@@ -137,155 +112,138 @@ export class RecordingApi {
// clear absoluteStart
this.absoluteStart = -1
}
-
- // call on dispose function to stop tracking movements
- public removeRecordingFFView = (): void => {
- this.disposeFunc?.();
- this.disposeFunc = null;
- }
- // public pause = (): Error | undefined => {
- // if (this.isInitPresenation) {
- // console.error('[recordingApi.ts] pause() failed: no presentation started. try calling init() first')
- // return new Error('[recordingApi.ts] pause(): no presentation')
- // }
- // // don't allow track movments
- // this.tracking = false
-
- // // set adjust absoluteStart to add the time difference
- // const timestamp = new Date().getTime()
- // this.absoluteStart = timestamp - this.absoluteStart
- // }
-
- // public resume = () => {
- // this.tracking = true
- // // set absoluteStart to the difference in time
- // this.absoluteStart = new Date().getTime() - this.absoluteStart
- // }
-
- private trackMovements = (panX: number, panY: number, scale: number = 0): Error | undefined => {
- // ensure we are recording
- if (!this.tracking) {
- return new Error('[recordingApi.ts] trackMovements()')
- }
- // check to see if the presetation is init
- if (this.isInitPresenation) {
- return new Error('[recordingApi.ts] trackMovements(): no presentation')
- }
-
- // TO FIX: bob
- // console.debug('track movment')
-
- // get the time
- const time = new Date().getTime() - this.absoluteStart
- // make new movement object
- const movement: Movement = { time, panX, panY, scale }
-
- // add that movement to the current presentation data's movement array
- this.currentPresentation.movements && this.currentPresentation.movements.push(movement)
- }
+ // call on dispose function to stop tracking movements
+ public removeRecordingFFView = (): void => {
+ this.disposeFunc?.();
+ this.disposeFunc = null;
+ }
- // instance variable for the FFView
- private disposeFunc: IReactionDisposer | null;
- private recordingFFView: CollectionFreeFormView | null;
-
- // set the FFView that will be used in a reaction to track the movements
- public setRecordingFFView = (view: CollectionFreeFormView): void => {
- // set the view to the current view
- if (view === this.recordingFFView || view == null) return;
-
- // this.recordingFFView = view;
- // set the reaction to track the movements
- this.disposeFunc = reaction(
- () => ({ x: NumCast(view.Document.panX, -1), y: NumCast(view.Document.panY, -1), scale: NumCast(view.Document.viewScale, -1) }),
- (res) => (res.x !== -1 && res.y !== -1 && this.tracking) && this.trackMovements(res.x, res.y, res.scale)
- )
-
- // for now, set the most recent recordingFFView to the playFFView
- this.recordingFFView = view;
+ private trackMovements = (panX: number, panY: number, scale: number = 0) => {
+ // ensure we are recording
+ if (!this.tracking) {
+ console.error('[recordingApi.ts] trackMovements(): tracking is false')
+ return;
+ }
+ // check to see if the presetation is init
+ if (this.nullPresentation) {
+ console.error('[recordingApi.ts] trackMovements(): no presentation')
+ return;
}
- // TODO: extract this into different class with pause and resume recording
- // TODO: store the FFview with the movements
- private playFFView: CollectionFreeFormView | null;
- private timers: NodeJS.Timeout[] | null;
+ // TO FIX: bob
+ // console.debug('track movment')
+
+ // get the time
+ const time = new Date().getTime() - this.absoluteStart
+ // make new movement object
+ const movement: Movement = { time, panX, panY, scale }
+
+ // add that movement to the current presentation data's movement array
+ this.currentPresentation.movements && this.currentPresentation.movements.push(movement)
+ }
+
+ // instance variable for the FFView
+ private disposeFunc: IReactionDisposer | null;
+ private recordingFFView: CollectionFreeFormView | null;
+
+ // set the FFView that will be used in a reaction to track the movements
+ public setRecordingFFView = (view: CollectionFreeFormView): void => {
+ // set the view to the current view
+ if (view === this.recordingFFView || view == null) return;
+
+ // this.recordingFFView = view;
+ // set the reaction to track the movements
+ this.disposeFunc = reaction(
+ () => ({ x: NumCast(view.Document.panX, -1), y: NumCast(view.Document.panY, -1), scale: NumCast(view.Document.viewScale, -1) }),
+ (res) => (res.x !== -1 && res.y !== -1 && this.tracking) && this.trackMovements(res.x, res.y, res.scale)
+ )
+
+ // for now, set the most recent recordingFFView to the playFFView
+ this.recordingFFView = view;
+ }
+
+ // TODO: extract this into different class with pause and resume recording
+ // TODO: store the FFview with the movements
+ private playFFView: CollectionFreeFormView | null;
+ private timers: NodeJS.Timeout[] | null;
- public setPlayFFView = (view: CollectionFreeFormView): void => {
- this.playFFView = view
+ public setPlayFFView = (view: CollectionFreeFormView): void => {
+ this.playFFView = view
+ }
+
+ // pausing movements will dispose all timers that are planned to replay the movements
+ // play movemvents will recreate them when the user resumes the presentation
+ public pauseMovements = (): undefined | Error => {
+ if (this.playFFView === null) {
+ return new Error('[recordingApi.ts] pauseMovements() failed: no view')
}
- // pausing movements will dispose all timers that are planned to replay the movements
- // play movemvents will recreate them when the user resumes the presentation
- public pauseMovements = (): undefined | Error => {
- if (this.playFFView === null) {
- return new Error('[recordingApi.ts] pauseMovements() failed: no view')
- }
-
- if (!this._isPlaying) {
- //return new Error('[recordingApi.ts] pauseMovements() failed: not playing')
- return
- }
- this._isPlaying = false
- // TODO: set userdoc presentMode to browsing
- this.timers?.map(timer => clearTimeout(timer))
-
- // this.videoBox = null;
+ if (!this._isPlaying) {
+ //return new Error('[recordingApi.ts] pauseMovements() failed: not playing')
+ return
}
-
- private videoBox: VideoBox | null = null;
+ this._isPlaying = false
+ // TODO: set userdoc presentMode to browsing
+ this.timers?.map(timer => clearTimeout(timer))
+
+ // this.videoBox = null;
+ }
+
+ private videoBox: VideoBox | null = null;
+
+ // by calling pause on the VideoBox, the pauseMovements will be called
+ public pauseVideoAndMovements = (): boolean => {
+ this.videoBox?.Pause()
+
+ this.pauseMovements()
+ return this.videoBox == null
+ }
- // by calling pause on the VideoBox, the pauseMovements will be called
- public pauseVideoAndMovements = (): boolean => {
- this.videoBox?.Pause()
+ public _isPlaying = false;
- this.pauseMovements()
- return this.videoBox == null
+ public playMovements = (presentation: Presentation, timeViewed: number = 0, videoBox?: VideoBox): undefined | Error => {
+ if (presentation.movements === null || this.playFFView === null) {
+ return new Error('[recordingApi.ts] followMovements() failed: no presentation data or no view')
}
+ if (this._isPlaying) return;
- public _isPlaying = false;
-
- public playMovements = (presentation: Presentation, timeViewed: number = 0, videoBox?: VideoBox): undefined | Error => {
- if (presentation.movements === null || this.playFFView === null) {
- return new Error('[recordingApi.ts] followMovements() failed: no presentation data or no view')
- }
- if(this._isPlaying) return;
-
- this._isPlaying = true;
- Doc.UserDoc().presentationMode = 'watching';
-
- // TODO: consider this bug at the end of the clip on seek
- this.videoBox = videoBox || null;
-
- // only get the movements that are remaining in the video time left
- const filteredMovements = presentation.movements.filter(movement => movement.time > timeViewed * 1000)
-
- // helper to replay a movement
- const document = this.playFFView
- let preScale = -1;
- const zoomAndPan = (movement: Movement) => {
- const { panX, panY, scale } = movement;
- (scale !== -1 && preScale !== scale) && document.zoomSmoothlyAboutPt([panX, panY], scale, 0);
- document.Document._panX = panX;
- document.Document._panY = panY;
-
- preScale = scale;
- }
-
- // set the first frame to be at the start of the pres
- zoomAndPan(filteredMovements[0]);
-
- // make timers that will execute each movement at the correct replay time
- this.timers = filteredMovements.map(movement => {
- const timeDiff = movement.time - timeViewed*1000
- return setTimeout(() => {
- // replay the movement
- zoomAndPan(movement)
- // if last movement, presentation is done -> set the instance var
- if (movement === filteredMovements[filteredMovements.length - 1]) RecordingApi.Instance._isPlaying = false;
- }, timeDiff)
- })
+ this._isPlaying = true;
+ Doc.UserDoc().presentationMode = 'watching';
+
+ // TODO: consider this bug at the end of the clip on seek
+ this.videoBox = videoBox || null;
+
+ // only get the movements that are remaining in the video time left
+ const filteredMovements = presentation.movements.filter(movement => movement.time > timeViewed * 1000)
+
+ // helper to replay a movement
+ const document = this.playFFView
+ let preScale = -1;
+ const zoomAndPan = (movement: Movement) => {
+ const { panX, panY, scale } = movement;
+ (scale !== -1 && preScale !== scale) && document.zoomSmoothlyAboutPt([panX, panY], scale, 0);
+ document.Document._panX = panX;
+ document.Document._panY = panY;
+
+ preScale = scale;
}
-
+
+ // set the first frame to be at the start of the pres
+ zoomAndPan(filteredMovements[0]);
+
+ // make timers that will execute each movement at the correct replay time
+ this.timers = filteredMovements.map(movement => {
+ const timeDiff = movement.time - timeViewed * 1000
+ return setTimeout(() => {
+ // replay the movement
+ zoomAndPan(movement)
+ // if last movement, presentation is done -> set the instance var
+ if (movement === filteredMovements[filteredMovements.length - 1]) RecordingApi.Instance._isPlaying = false;
+ }, timeDiff)
+ })
+ }
+
// method that concatenates an array of presentatations into one
public concatPresentations = (presentations: Presentation[]): Presentation => {
// these three will lead to the combined presentation
@@ -295,6 +253,7 @@ export class RecordingApi {
presentations.forEach((presentation) => {
const { movements, totalTime, meta } = presentation;
+
// update movements if they had one
if (movements) {
// add the summed time to the movements
@@ -302,8 +261,10 @@ export class RecordingApi {
// concat the movements already in the combined presentation with these new ones
combinedMovements.push(...addedTimeMovements);
}
+
// update the totalTime
sumTime += totalTime;
+
// concatenate the metas
combinedMetas.push(...meta);
});
@@ -312,19 +273,19 @@ export class RecordingApi {
return { movements: combinedMovements, totalTime: sumTime, meta: combinedMetas };
}
- // Unfinished code for tracing multiple free form views
- // export let pres: Map<CollectionFreeFormView, IReactionDisposer> = new Map()
-
- // export function AddRecordingFFView(ffView: CollectionFreeFormView): void {
- // pres.set(ffView,
- // reaction(() => ({ x: ffView.panX, y: ffView.panY }),
- // (pt) => RecordingApi.trackMovements(ffView, pt.x, pt.y)))
- // )
- // }
-
- // export function RemoveRecordingFFView(ffView: CollectionFreeFormView): void {
- // const disposer = pres.get(ffView);
- // disposer?.();
- // pres.delete(ffView)
- // }
+ // Unfinished code for tracing multiple free form views
+ // export let pres: Map<CollectionFreeFormView, IReactionDisposer> = new Map()
+
+ // export function AddRecordingFFView(ffView: CollectionFreeFormView): void {
+ // pres.set(ffView,
+ // reaction(() => ({ x: ffView.panX, y: ffView.panY }),
+ // (pt) => RecordingApi.trackMovements(ffView, pt.x, pt.y)))
+ // )
+ // }
+
+ // export function RemoveRecordingFFView(ffView: CollectionFreeFormView): void {
+ // const disposer = pres.get(ffView);
+ // disposer?.();
+ // pres.delete(ffView)
+ // }
}
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 6fe67b6db..a28677525 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -46,7 +46,7 @@ export class RecordingBox extends ViewBoxBaseComponent() {
this.dataDoc.layout = VideoBox.LayoutString(this.fieldKey);
this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.client);
this.dataDoc[this.fieldKey + "-recorded"] = true;
- // stringify the presenation and store it
+ // stringify the presentation and store it
presentation?.movements && (this.dataDoc[this.fieldKey + "-presentation"] = JSON.stringify(presentation));
}
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index ba9479f41..15883632a 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -60,7 +60,7 @@ export function RecordingView(props: IRecordingViewProps) {
}
}
- useEffect(() => console.log('progress', progress), [progress])
+ // useEffect(() => console.debug('progress', progress), [progress])
useEffect(() => {
if (finished) {
@@ -93,8 +93,7 @@ export function RecordingView(props: IRecordingViewProps) {
useEffect(() => {
let interval: any = null;
if (recording) {
- interval = setTimeout(() => {
- console.log('update interval')
+ interval = setInterval(() => {
setRecordingTimer(unit => unit + 1);
}, 10);
} else if (!recording && recordingTimer !== 0) {
@@ -141,7 +140,6 @@ export function RecordingView(props: IRecordingViewProps) {
}
videoRecorder.current.onstop = () => {
- // RecordingApi.Instance.stop();
// if we have a last portion
if (videoChunks.length > 1) {
// append the current portion to the video pieces
@@ -150,9 +148,10 @@ export function RecordingView(props: IRecordingViewProps) {
endTime: recordingTimerRef.current,
startTime: videos?.lastElement()?.endTime || 0
};
+
// depending on if a presenation exists, add it to the video
- const { done: presError, value: presentation } = RecordingApi.Instance.yieldPresentation().next();
- setVideos(videos => [...videos, (!presError && trackScreen) ? { ...nextVideo, presentation } : nextVideo]);
+ const presentation = RecordingApi.Instance.yieldPresentation();
+ setVideos(videos => [...videos, (presentation != null && trackScreen) ? { ...nextVideo, presentation } : nextVideo]);
}
// reset the temporary chunks
@@ -175,8 +174,8 @@ export function RecordingView(props: IRecordingViewProps) {
const stream = videoElementRef.current!.srcObject;
stream instanceof MediaStream && stream.getTracks().forEach(track => track.stop());
- // clear the recoringApi
- RecordingApi.Instance.clear();
+ // finish/clear the recoringApi
+ RecordingApi.Instance.finish();
// this will call upon progessbar to update videos to be in the correct order
setFinished(true);
@@ -189,12 +188,10 @@ export function RecordingView(props: IRecordingViewProps) {
}
const start = (e: React.PointerEvent) => {
- // the code to start or resume does not get triggered if we start dragging the button
setupMoveUpEvents({}, e, returnTrue, returnFalse, e => {
- if (!videoRecorder.current || videoRecorder.current.state === "inactive") {
- record();
- // trackScreen &&
- }
+ // start recording if not already recording
+ if (!videoRecorder.current || videoRecorder.current.state === "inactive") record();
+
return true; // cancels propagation to documentView to avoid selecting it.
}, false, false);
}
@@ -204,9 +201,7 @@ export function RecordingView(props: IRecordingViewProps) {
setDoUndo(prev => !prev);
}
- const handleOnTimeUpdate = () => {
- playing && setVideoProgressHelper(videoElementRef.current!.currentTime);
- };
+ const handleOnTimeUpdate = () => { playing && setVideoProgressHelper(videoElementRef.current!.currentTime); };
const millisecondToMinuteSecond = (milliseconds: number) => {
const toTwoDigit = (digit: number) => {
@@ -223,7 +218,7 @@ export function RecordingView(props: IRecordingViewProps) {
<video id={`video-${props.id}`}
autoPlay
muted
- onTimeUpdate={handleOnTimeUpdate}
+ onTimeUpdate={() => handleOnTimeUpdate()}
ref={videoElementRef}
/>
<div className="recording-sign">