aboutsummaryrefslogtreecommitdiff
path: root/src/client/apis
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/apis')
-rw-r--r--src/client/apis/recording/recordingApi.ts300
1 files changed, 0 insertions, 300 deletions
diff --git a/src/client/apis/recording/recordingApi.ts b/src/client/apis/recording/recordingApi.ts
deleted file mode 100644
index b57e675b7..000000000
--- a/src/client/apis/recording/recordingApi.ts
+++ /dev/null
@@ -1,300 +0,0 @@
-import { CollectionFreeFormView } from "../../views/collections/collectionFreeForm";
-import React, { useState } from "react";
-import { IReactionDisposer, observable, reaction } from "mobx";
-import { NumCast } from "../../../fields/Types";
-
-type Movement = {
- time: number,
- panX: number,
- panY: number,
-}
-
-type Presentation = {
- movements: Array<Movement>
- meta: Object,
- startDate: Date | null,
-}
-
-export class RecordingApi {
-
- private static NULL_PRESENTATION: Presentation = {
- movements: [],
- meta: {},
- startDate: null,
- }
-
- // instance variables
- private currentPresentation: Presentation;
- private isRecording: 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.isRecording = false;
- this.absoluteStart = -1;
-
- // used for tracking movements in the view frame
- this.disposeFunc = null;
-
- // for now, set playFFView
- this.playFFView = null;
- this.timers = null;
- }
-
- // little helper :)
- private get isInitPresenation(): boolean {
- return this.currentPresentation.startDate === null
- }
-
- public start = (view: CollectionFreeFormView, meta?: Object): Error | undefined => {
- // check if already init a presentation
- if (!this.isInitPresenation) {
- console.error('[recordingApi.ts] start() failed: current presentation data exists. please call clear() first.')
- return new Error('[recordingApi.ts] start()')
- }
-
- // (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.startDate = startDate
- // (4) set isRecording true to allow trackMovements
- this.isRecording = true
- }
-
- public clear = (): Error | undefined => {
- // TODO: maybe archive the data?
- if (this.isRecording) {
- console.error('[recordingApi.ts] clear() failed: currently recording presentation. call pause() or finish() first')
- return new Error('[recordingApi.ts] clear()')
- }
-
- // clear presenation data
- this.currentPresentation = RecordingApi.NULL_PRESENTATION
- // clear isRecording
- this.isRecording = false
- // clear absoluteStart
- this.absoluteStart = -1
-
- // clear the disposeFunc
- this.disposeFunc = null
- }
-
- public pause = (): Error | undefined => {
- if (this.currentPresentation.startDate === null) {
- console.error('[recordingApi.ts] pause() failed: no presentation started. try calling init() first')
- return new Error('[recordingApi.ts] pause(): no presenation')
- }
- // don't allow track movments
- this.isRecording = false
-
- // set relativeStart to the pausedTimestamp
- const timestamp = new Date().getTime()
- this.absoluteStart = timestamp
- }
-
- public resume = () => {
- const timestamp = new Date().getTime()
- const startTimestamp = this.currentPresentation.startDate?.getTime()
- if (!startTimestamp) {
- console.error('[recordingApi.ts] resume() failed: no presentation data. try calling start() first')
- return new Error('[recordingApi.ts] pause()')
- }
-
- // update absoluteStart to bridge the paused time
- const absoluteTimePaused = timestamp - this.absoluteStart
- this.absoluteStart = absoluteTimePaused
- }
-
- public finish = (): Error | Presentation => {
- if (this.isInitPresenation) {
- console.error('[recordingApi.ts] finish() failed: no presentation data. try calling start() first')
- return new Error('[recordingApi.ts] finish()')
- }
-
- // return a copy of the the presentation data
- return { ...this.currentPresentation }
- }
-
- private trackMovements = (panX: number, panY: number): Error | undefined => {
- // ensure we are recording
- if (!this.isRecording) {
- console.error('[recordingApi.ts] pause() failed: recording is paused()')
- return new Error('[recordingApi.ts] pause()')
- }
-
- // get the relative time
- const timestamp = new Date().getTime()
- const relativeTime = timestamp - this.absoluteStart
-
- // make new movement struct
- const movement: Movement = { time: relativeTime, panX, panY }
-
- // add that movement to the current presentation data's movement array
- this.currentPresentation.movements.push(movement)
- }
-
- // instance variable for the FFView
- private disposeFunc: IReactionDisposer | 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 === 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) }),
- (res) => (res.x !== -1 && res.y !== -1) && this.trackMovements(res.x, res.y)
- )
-
- // for now, set the most recent recordingFFView to the playFFView
- this.playFFView = view;
- }
-
- // call on dispose function to stop tracking movements
- public removeRecordingFFView = (): void => {
- this.disposeFunc?.();
- this.disposeFunc = null;
- }
-
- // TODO: extract this into different class with pause and resume recording
- private playFFView: CollectionFreeFormView | null;
- private timers: Timer[] | null;
-
- public followMovements = (presentation: Presentation): undefined | Error => {
- if (presentation.startDate === null || this.playFFView === null) {
- return new Error('[recordingApi.ts] followMovements() failed: no presentation data or no view')
- }
-
- const document = this.playFFView.Document
- const { movements } = presentation
- this.timers = movements.map(movement => {
- const { panX, panY, time } = movement
- return new Timer(() => {
- document._panX = panX;
- document._panY = panY;
- // TODO: consider cleaning this array to null or some state
- }, time)
- })
- }
-
- public pauseMovements = (): undefined | Error => {
- if (this.playFFView === null) {
- return new Error('[recordingApi.ts] pauseMovements() failed: no view')
- }
- // TODO: set userdoc presentMode to browsing
- this.timers?.forEach(timer => timer.pause())
- }
-
- public resumeMovements = (): undefined | Error => {
- if (this.playFFView === null) {
- return new Error('[recordingApi.ts] resumeMovements() failed: no view')
- }
- this.timers?.forEach(timer => timer.resume())
- }
-
- // public followMovements = (presentation: Presentation): undefined | Error => {
- // if (presentation.startDate === null || this.playFFView === null) {
- // return new Error('[recordingApi.ts] followMovements() failed: no presentation data or no view')
- // }
-
- // const document = this.playFFView.Document
- // const { movements } = presentation
- // movements.forEach(movement => {
- // const { panX, panY, time } = movement
- // // set the pan to what was stored
- // setTimeout(() => {
- // document._panX = panX;
- // document._panY = panY;
- // }, time)
- // })
- // }
- // 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)
- // }
-}
-
-/** Represents the `setTimeout` with an ability to perform pause/resume actions
- * citation: https://stackoverflow.com/questions/3969475/javascript-pause-settimeout
- */
-export class Timer {
- private _start: Date;
- private _remaining: number;
- private _durationTimeoutId?: NodeJS.Timeout;
- private _callback: (...args: any[]) => void;
- private _done = false;
- get done () {
- return this._done;
- }
-
- public constructor(callback: (...args: any[]) => void, ms = 0) {
- this._callback = () => {
- callback();
- this._done = true;
- };
- this._remaining = ms;
- this.resume();
- }
-
- /** pauses the timer */
- public pause(): Timer {
- if (this._durationTimeoutId && !this._done) {
- this._clearTimeoutRef();
- this._remaining -= new Date().getTime() - this._start.getTime();
- }
- return this;
- }
-
- /** resumes the timer */
- public resume(): Timer {
- if (!this._durationTimeoutId && !this._done) {
- this._start = new Date;
- this._durationTimeoutId = setTimeout(this._callback, this._remaining);
- }
- return this;
- }
-
- /**
- * clears the timeout and marks it as done.
- *
- * After called, the timeout will not resume
- */
- public clearTimeout() {
- this._clearTimeoutRef();
- this._done = true;
- }
-
- private _clearTimeoutRef() {
- if (this._durationTimeoutId) {
- clearTimeout(this._durationTimeoutId);
- this._durationTimeoutId = undefined;
- }
- }
-
-} \ No newline at end of file