From 6493d95e92c8ed58bb3a8c07ea4ca28dae82ea1d Mon Sep 17 00:00:00 2001
From: Jenny Yu <jennyyu212@outlook.com>
Date: Tue, 7 Jun 2022 08:51:41 -0700
Subject: removing decorations on recording box

---
 .../views/nodes/RecordingBox/RecordingView.tsx       | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 87716e9cc..5826abd65 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -9,6 +9,7 @@ import { Networking } from '../../../Network';
 import { Upload } from '../../../../server/SharedMediaTypes';
 
 import { RecordingApi } from '../../../util/RecordingApi';
+import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils';
 
 interface MediaSegment {
       videoChunks: any[],
@@ -193,12 +194,15 @@ export function RecordingView(props: IRecordingViewProps) {
             }
       }
 
-      const startOrResume = () => {
-            if (!videoRecorder.current || videoRecorder.current.state === "inactive") {
-                  record();
-            } else if (videoRecorder.current.state === "paused") {
-                  videoRecorder.current.resume();
-            }
+      const startOrResume = (e: React.PointerEvent) => {
+            // the code to start or resume does not get triggered if we start dragging the button
+            setupMoveUpEvents({}, e, returnFalse, returnFalse, () => {
+                  if (!videoRecorder.current || videoRecorder.current.state === "inactive") {
+                        record();
+                  } else if (videoRecorder.current.state === "paused") {
+                        videoRecorder.current.resume();
+                  }
+            })
       }
 
       const clearPrevious = () => {
@@ -240,8 +244,8 @@ export function RecordingView(props: IRecordingViewProps) {
                               <div className="controls-inner-container">
                                     <div className="record-button-wrapper">
                                           {recording ?
-                                                <button className="stop-button" onClick={pause} /> :
-                                                <button className="record-button" onClick={startOrResume} />
+                                                <button className="stop-button" onPointerDown={pause} /> :
+                                                <button className="record-button" onPointerDown={startOrResume} />
                                           }
                                     </div>
 
-- 
cgit v1.2.3-70-g09d2


From d3c89f90d376310cd583ae1c6ac4a7eb4c5a03ac Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 7 Jun 2022 13:39:17 -0400
Subject: fixed dragging items in overlayView to not invalidate DocumentView
 and cause a rerender.  fixed loss of ability to select or drag after dragging
 a recording.

---
 src/Utils.ts                                       |  10 +-
 src/client/util/DragManager.ts                     |   4 -
 src/client/views/OverlayView.tsx                   |  13 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      |  85 ++--
 .../views/nodes/RecordingBox/RecordingView.tsx     | 491 +++++++++++----------
 5 files changed, 305 insertions(+), 298 deletions(-)

(limited to 'src/client/views/nodes/RecordingBox/RecordingView.tsx')

diff --git a/src/Utils.ts b/src/Utils.ts
index 6f3a31b49..07e95d438 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -698,6 +698,7 @@ export function setupMoveUpEvents(
     (target as any)._lastTap = Date.now();
     (target as any)._downX = (target as any)._lastX = e.clientX;
     (target as any)._downY = (target as any)._lastY = e.clientY;
+    (target as any)._noClick = false;
 
     const _moveEvent = (e: PointerEvent): void => {
         if (Math.abs(e.clientX - (target as any)._downX) > Utils.DRAG_THRESHOLD || Math.abs(e.clientY - (target as any)._downY) > Utils.DRAG_THRESHOLD) {
@@ -729,17 +730,20 @@ export function setupMoveUpEvents(
                 clearTimeout((target as any)._doubleTime);
                 (target as any)._doubleTime = undefined;
             }
-            clickEvent(e, (target as any)._doubleTap);
+            (target as any)._noClick = clickEvent(e, (target as any)._doubleTap);
         }
         document.removeEventListener("pointermove", _moveEvent);
         document.removeEventListener("pointerup", _upEvent);
     };
+    const _clickEvent = (e: MouseEvent): void => {
+        if ((target as any)._noClick) e.stopPropagation();
+        document.removeEventListener("click", _clickEvent, true);
+    }
     if (stopPropagation) {
         e.stopPropagation();
         e.preventDefault();
     }
-    document.removeEventListener("pointermove", _moveEvent);
-    document.removeEventListener("pointerup", _upEvent);
     document.addEventListener("pointermove", _moveEvent);
     document.addEventListener("pointerup", _upEvent);
+    document.addEventListener("click", _clickEvent, true);
 }
\ No newline at end of file
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index f438a8c11..9f8c49081 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -210,10 +210,6 @@ export namespace DragManager {
         options?: DragOptions,
         dropEvent?: () => any
     ) {
-        // stop an 'accidental' on-click drag that may have occured if the user is in presenting mode
-        // note: dragData.dropAction is only undefined when the element itself being dragged without being selected
-        if (Doc.UserDoc()?.presentationMode === 'recording' && dragData.dropAction === undefined) return false;
-
         const addAudioTag = (dropDoc: any) => {
             dropDoc && !dropDoc.creationDate && (dropDoc.creationDate = new DateField);
             dropDoc instanceof Doc && DocUtils.MakeLinkToActiveAudio(() => dropDoc);
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 9d970c06f..6796db51e 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -1,5 +1,7 @@
+import { docs } from "googleapis/build/src/apis/docs";
 import { action, computed, observable } from "mobx";
 import { observer } from "mobx-react";
+import { computedFn } from "mobx-utils";
 import * as React from "react";
 import ReactLoading from 'react-loading';
 import { Doc, WidthSym, HeightSym } from "../../fields/Doc";
@@ -146,6 +148,12 @@ export class OverlayView extends React.Component {
         return remove;
     }
 
+    removeOverlayDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).map(doc => Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), "data", doc)).length ? true : false;
+
+
+    docScreenToLocalXf = computedFn(function docScreenToLocalXf(this: any, doc: Doc) {
+        return () => new Transform(-NumCast(doc.x), -NumCast(doc.y), 1);
+    }.bind(this));
 
     @computed get overlayDocs() {
         return CurrentUserUtils.OverlayDocs?.map(d => {
@@ -179,17 +187,16 @@ export class OverlayView extends React.Component {
                 offsetx = NumCast(d.x) - e.clientX;
                 offsety = NumCast(d.y) - e.clientY;
             };
-
             return <div className="overlayView-doc" ref={dref} key={d[Id]} onPointerDown={onPointerDown} style={{ top: d.type === 'presentation' ? 0 : undefined, width: NumCast(d._width), height: NumCast(d._height), transform: `translate(${d.x}px, ${d.y}px)` }}>
                 <DocumentView
                     Document={d}
                     rootSelected={returnTrue}
                     bringToFront={emptyFunction}
                     addDocument={undefined}
-                    removeDocument={doc => (doc instanceof Doc ? [doc] : doc).map(doc => Doc.RemoveDocFromList((Doc.UserDoc().myOverlayDocs as Doc), "data", doc)).length ? true : false}
+                    removeDocument={this.removeOverlayDoc}
                     PanelWidth={d[WidthSym]}
                     PanelHeight={d[HeightSym]}
-                    ScreenToLocalTransform={() => new Transform(-NumCast(d.x), -NumCast(d.y), 1)}
+                    ScreenToLocalTransform={this.docScreenToLocalXf(d)}
                     renderDepth={1}
                     isDocumentActive={returnTrue}
                     isContentActive={emptyFunction}
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 159271223..eac1c63f9 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -16,47 +16,46 @@ import { Id } from "../../../../fields/FieldSymbols";
 @observer
 export class RecordingBox extends ViewBoxBaseComponent() {
 
-      public static LayoutString(fieldKey: string) { return FieldView.LayoutString(RecordingBox, fieldKey); }
-
-      private _ref: React.RefObject<HTMLDivElement> = React.createRef();
-
-      constructor(props: any) {
-            super(props);
-      }
-
-      componentDidMount() {
-            console.log("set native width and height")
-            Doc.SetNativeWidth(this.dataDoc, 1280);
-            Doc.SetNativeHeight(this.dataDoc, 720);
-      }
-
-      @observable result: Upload.FileInformation | undefined = undefined
-      @observable videoDuration: number | undefined = undefined
-
-      @action
-      setVideoDuration = (duration: number) => {
-            this.videoDuration = duration
-      }
-
-      @action
-      setResult = (info: Upload.FileInformation, trackScreen: boolean) => {
-            this.result = info
-            this.dataDoc.type = DocumentType.VID;
-            this.dataDoc[this.fieldKey + "-duration"] = this.videoDuration;
-
-            this.dataDoc.layout = VideoBox.LayoutString(this.fieldKey);
-            this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.agnostic.client);
-            this.dataDoc[this.fieldKey + "-recorded"] = true;
-            // stringify the presenation and store it
-            if (trackScreen) {
-                  this.dataDoc[this.fieldKey + "-presentation"] = JSON.stringify(RecordingApi.Instance.clear());
-            }
-      }
-
-      render() {
-            // console.log("Proto[Is]: ", this.rootDoc.proto?.[Id])
-            return <div className="recordingBox" ref={this._ref}>
-                  {!this.result && <RecordingView setResult={this.setResult} setDuration={this.setVideoDuration} id={this.rootDoc.proto?.[Id]} />}
-            </div>;
-      }
+    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(RecordingBox, fieldKey); }
+
+    private _ref: React.RefObject<HTMLDivElement> = React.createRef();
+
+    constructor(props: any) {
+        super(props);
+    }
+
+    componentDidMount() {
+        console.log("set native width and height")
+        Doc.SetNativeWidth(this.dataDoc, 1280);
+        Doc.SetNativeHeight(this.dataDoc, 720);
+    }
+
+    @observable result: Upload.FileInformation | undefined = undefined
+    @observable videoDuration: number | undefined = undefined
+
+    @action
+    setVideoDuration = (duration: number) => {
+        this.videoDuration = duration
+    }
+
+    @action
+    setResult = (info: Upload.FileInformation, trackScreen: boolean) => {
+        this.result = info
+        this.dataDoc.type = DocumentType.VID;
+        this.dataDoc[this.fieldKey + "-duration"] = this.videoDuration;
+
+        this.dataDoc.layout = VideoBox.LayoutString(this.fieldKey);
+        this.dataDoc[this.props.fieldKey] = new VideoField(this.result.accessPaths.agnostic.client);
+        this.dataDoc[this.fieldKey + "-recorded"] = true;
+        // stringify the presenation and store it
+        if (trackScreen) {
+            this.dataDoc[this.fieldKey + "-presentation"] = JSON.stringify(RecordingApi.Instance.clear());
+        }
+    }
+
+    render() {
+        return <div className="recordingBox" ref={this._ref}>
+            {!this.result && <RecordingView setResult={this.setResult} setDuration={this.setVideoDuration} id={this.rootDoc.proto?.[Id]} />}
+        </div>;
+    }
 }
diff --git a/src/client/views/nodes/RecordingBox/RecordingView.tsx b/src/client/views/nodes/RecordingBox/RecordingView.tsx
index 5826abd65..b95335792 100644
--- a/src/client/views/nodes/RecordingBox/RecordingView.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingView.tsx
@@ -9,273 +9,274 @@ import { Networking } from '../../../Network';
 import { Upload } from '../../../../server/SharedMediaTypes';
 
 import { RecordingApi } from '../../../util/RecordingApi';
-import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../../Utils';
+import { emptyFunction, returnFalse, returnTrue, setupMoveUpEvents } from '../../../../Utils';
 
 interface MediaSegment {
-      videoChunks: any[],
-      endTime: number
+    videoChunks: any[],
+    endTime: number
 }
 
 interface IRecordingViewProps {
-      setResult: (info: Upload.FileInformation, trackScreen: boolean) => void
-      setDuration: (seconds: number) => void
-      id: string
+    setResult: (info: Upload.FileInformation, trackScreen: boolean) => void
+    setDuration: (seconds: number) => void
+    id: string
 }
 
 const MAXTIME = 100000;
 
 export function RecordingView(props: IRecordingViewProps) {
 
-      const [recording, setRecording] = useState(false);
-      const recordingTimerRef = useRef<number>(0);
-      const [recordingTimer, setRecordingTimer] = useState(0); // unit is 0.01 second
-      const [playing, setPlaying] = useState(false);
-      const [progress, setProgress] = useState(0);
-
-      const [videos, setVideos] = useState<MediaSegment[]>([]);
-      const videoRecorder = useRef<MediaRecorder | null>(null);
-      const videoElementRef = useRef<HTMLVideoElement | null>(null);
-
-      const [finished, setFinished] = useState<boolean>(false)
-      const [trackScreen, setTrackScreen] = useState<boolean>(true)
-
-
-
-      const DEFAULT_MEDIA_CONSTRAINTS = {
-            video: {
-                  width: 1280,
-                  height: 720,
-            },
-            audio: {
-                  echoCancellation: true,
-                  noiseSuppression: true,
-                  sampleRate: 44100
-            }
-      }
-
-      useEffect(() => {
-
-            if (finished) {
-                  props.setDuration(recordingTimer * 100)
-                  let allVideoChunks: any = []
-                  videos.forEach((vid) => {
-                        console.log(vid.videoChunks)
-                        allVideoChunks = allVideoChunks.concat(vid.videoChunks)
-                  })
-
-                  const videoFile = new File(allVideoChunks, "video.mkv", { type: allVideoChunks[0].type, lastModified: Date.now() });
-
-                  Networking.UploadFilesToServer(videoFile)
-                        .then((data) => {
-                              const result = data[0].result
-                              if (!(result instanceof Error)) { // convert this screenshotBox into normal videoBox
-                                    props.setResult(result, trackScreen)
-                              } else {
-                                    alert("video conversion failed");
-                              }
-                        })
-
-            }
-
-
-      }, [finished])
-
-      useEffect(() => {
-            // check if the browser supports media devices on first load
-            if (!navigator.mediaDevices) {
-                  console.log('This browser does not support getUserMedia.')
-            }
-            console.log('This device has the correct media devices.')
-      }, [])
-
-      useEffect(() => {
-            // get access to the video element on every render
-            videoElementRef.current = document.getElementById(`video-${props.id}`) as HTMLVideoElement;
-      })
-
-      useEffect(() => {
-            let interval: any = null;
-            if (recording) {
-                  interval = setInterval(() => {
-                        setRecordingTimer(unit => unit + 1);
-                  }, 10);
-            } else if (!recording && recordingTimer !== 0) {
-                  clearInterval(interval);
-            }
-            return () => clearInterval(interval);
-      }, [recording])
-
-      useEffect(() => {
-            setVideoProgressHelper(recordingTimer)
-            recordingTimerRef.current = recordingTimer;
-      }, [recordingTimer])
-
-      const setVideoProgressHelper = (progress: number) => {
-            const newProgress = (progress / MAXTIME) * 100;
-            setProgress(newProgress)
-      }
-      const startShowingStream = async (mediaConstraints = DEFAULT_MEDIA_CONSTRAINTS) => {
-            const stream = await navigator.mediaDevices.getUserMedia(mediaConstraints)
-
-            videoElementRef.current!.src = ""
-            videoElementRef.current!.srcObject = stream
-            videoElementRef.current!.muted = true
-
-            return stream
-      }
-
-      const record = async () => {
-            const stream = await startShowingStream();
-            videoRecorder.current = new MediaRecorder(stream)
-
-            // temporary chunks of video
-            let videoChunks: any = []
-
-            videoRecorder.current.ondataavailable = (event: any) => {
-                  if (event.data.size > 0) {
-                        videoChunks.push(event.data)
-                  }
-            }
-
-            videoRecorder.current.onstart = (event: any) => {
-                  setRecording(true);
-                  trackScreen && RecordingApi.Instance.start();
-            }
-
-            videoRecorder.current.onstop = () => {
-                  // if we have a last portion
-                  if (videoChunks.length > 1) {
-                        // append the current portion to the video pieces
-                        setVideos(videos => [...videos, { videoChunks: videoChunks, endTime: recordingTimerRef.current }])
-                  }
-
-                  // reset the temporary chunks
-                  videoChunks = []
-                  setRecording(false);
-                  setFinished(true);
-                  trackScreen && RecordingApi.Instance.pause();
-            }
-
-            // recording paused
-            videoRecorder.current.onpause = (event: any) => {
-                  // append the current portion to the video pieces
-                  setVideos(videos => [...videos, { videoChunks: videoChunks, endTime: recordingTimerRef.current }])
+    const [recording, setRecording] = useState(false);
+    const recordingTimerRef = useRef<number>(0);
+    const [recordingTimer, setRecordingTimer] = useState(0); // unit is 0.01 second
+    const [playing, setPlaying] = useState(false);
+    const [progress, setProgress] = useState(0);
+
+    const [videos, setVideos] = useState<MediaSegment[]>([]);
+    const videoRecorder = useRef<MediaRecorder | null>(null);
+    const videoElementRef = useRef<HTMLVideoElement | null>(null);
+
+    const [finished, setFinished] = useState<boolean>(false)
+    const [trackScreen, setTrackScreen] = useState<boolean>(true)
+
+
+
+    const DEFAULT_MEDIA_CONSTRAINTS = {
+        video: {
+            width: 1280,
+            height: 720,
+        },
+        audio: {
+            echoCancellation: true,
+            noiseSuppression: true,
+            sampleRate: 44100
+        }
+    }
+
+    useEffect(() => {
+
+        if (finished) {
+            props.setDuration(recordingTimer * 100)
+            let allVideoChunks: any = []
+            videos.forEach((vid) => {
+                console.log(vid.videoChunks)
+                allVideoChunks = allVideoChunks.concat(vid.videoChunks)
+            })
 
-                  // reset the temporary chunks
-                  videoChunks = []
-                  setRecording(false);
-                  trackScreen && RecordingApi.Instance.pause();
+            const videoFile = new File(allVideoChunks, "video.mkv", { type: allVideoChunks[0].type, lastModified: Date.now() });
+
+            Networking.UploadFilesToServer(videoFile)
+                .then((data) => {
+                    const result = data[0].result
+                    if (!(result instanceof Error)) { // convert this screenshotBox into normal videoBox
+                        props.setResult(result, trackScreen)
+                    } else {
+                        alert("video conversion failed");
+                    }
+                })
+
+        }
+
+
+    }, [finished])
+
+    useEffect(() => {
+        // check if the browser supports media devices on first load
+        if (!navigator.mediaDevices) {
+            console.log('This browser does not support getUserMedia.')
+        }
+        console.log('This device has the correct media devices.')
+    }, [])
+
+    useEffect(() => {
+        // get access to the video element on every render
+        videoElementRef.current = document.getElementById(`video-${props.id}`) as HTMLVideoElement;
+    })
+
+    useEffect(() => {
+        let interval: any = null;
+        if (recording) {
+            interval = setInterval(() => {
+                setRecordingTimer(unit => unit + 1);
+            }, 10);
+        } else if (!recording && recordingTimer !== 0) {
+            clearInterval(interval);
+        }
+        return () => clearInterval(interval);
+    }, [recording])
+
+    useEffect(() => {
+        setVideoProgressHelper(recordingTimer)
+        recordingTimerRef.current = recordingTimer;
+    }, [recordingTimer])
+
+    const setVideoProgressHelper = (progress: number) => {
+        const newProgress = (progress / MAXTIME) * 100;
+        setProgress(newProgress)
+    }
+    const startShowingStream = async (mediaConstraints = DEFAULT_MEDIA_CONSTRAINTS) => {
+        const stream = await navigator.mediaDevices.getUserMedia(mediaConstraints)
+
+        videoElementRef.current!.src = ""
+        videoElementRef.current!.srcObject = stream
+        videoElementRef.current!.muted = true
+
+        return stream
+    }
+
+    const record = async () => {
+        const stream = await startShowingStream();
+        videoRecorder.current = new MediaRecorder(stream)
+
+        // temporary chunks of video
+        let videoChunks: any = []
+
+        videoRecorder.current.ondataavailable = (event: any) => {
+            if (event.data.size > 0) {
+                videoChunks.push(event.data)
             }
-
-            videoRecorder.current.onresume = async (event: any) => {
-                  await startShowingStream();
-                  setRecording(true);
-                  trackScreen && RecordingApi.Instance.resume();
+        }
+
+        videoRecorder.current.onstart = (event: any) => {
+            setRecording(true);
+            trackScreen && RecordingApi.Instance.start();
+        }
+
+        videoRecorder.current.onstop = () => {
+            // if we have a last portion
+            if (videoChunks.length > 1) {
+                // append the current portion to the video pieces
+                setVideos(videos => [...videos, { videoChunks: videoChunks, endTime: recordingTimerRef.current }])
             }
 
-            videoRecorder.current.start(200)
-      }
-
-
-      const stop = () => {
-            if (videoRecorder.current) {
-                  if (videoRecorder.current.state !== "inactive") {
-                        videoRecorder.current.stop();
-                        // recorder.current.stream.getTracks().forEach((track: any) => track.stop())
-                  }
+            // reset the temporary chunks
+            videoChunks = []
+            setRecording(false);
+            setFinished(true);
+            trackScreen && RecordingApi.Instance.pause();
+        }
+
+        // recording paused
+        videoRecorder.current.onpause = (event: any) => {
+            // append the current portion to the video pieces
+            setVideos(videos => [...videos, { videoChunks: videoChunks, endTime: recordingTimerRef.current }])
+
+            // reset the temporary chunks
+            videoChunks = []
+            setRecording(false);
+            trackScreen && RecordingApi.Instance.pause();
+        }
+
+        videoRecorder.current.onresume = async (event: any) => {
+            await startShowingStream();
+            setRecording(true);
+            trackScreen && RecordingApi.Instance.resume();
+        }
+
+        videoRecorder.current.start(200)
+    }
+
+
+    const stop = () => {
+        if (videoRecorder.current) {
+            if (videoRecorder.current.state !== "inactive") {
+                videoRecorder.current.stop();
+                // recorder.current.stream.getTracks().forEach((track: any) => track.stop())
             }
-      }
+        }
+    }
 
-      const pause = () => {
-            if (videoRecorder.current) {
-                  if (videoRecorder.current.state === "recording") {
-                        videoRecorder.current.pause();
-                  }
+    const pause = () => {
+        if (videoRecorder.current) {
+            if (videoRecorder.current.state === "recording") {
+                videoRecorder.current.pause();
             }
-      }
-
-      const startOrResume = (e: React.PointerEvent) => {
-            // the code to start or resume does not get triggered if we start dragging the button
-            setupMoveUpEvents({}, e, returnFalse, returnFalse, () => {
-                  if (!videoRecorder.current || videoRecorder.current.state === "inactive") {
-                        record();
-                  } else if (videoRecorder.current.state === "paused") {
-                        videoRecorder.current.resume();
-                  }
-            })
-      }
-
-      const clearPrevious = () => {
-            const numVideos = videos.length
-            setRecordingTimer(numVideos == 1 ? 0 : videos[numVideos - 2].endTime)
-            setVideoProgressHelper(numVideos == 1 ? 0 : videos[numVideos - 2].endTime)
-            setVideos(videos.filter((_, idx) => idx !== numVideos - 1));
-      }
-
-      const handleOnTimeUpdate = () => {
-            if (playing) {
-                  setVideoProgressHelper(videoElementRef.current!.currentTime)
+        }
+    }
+
+    const startOrResume = (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();
+            } else if (videoRecorder.current.state === "paused") {
+                videoRecorder.current.resume();
             }
-      };
-
-      const millisecondToMinuteSecond = (milliseconds: number) => {
-            const toTwoDigit = (digit: number) => {
-                  return String(digit).length == 1 ? "0" + digit : digit
-            }
-            const minutes = Math.floor((milliseconds % (1000 * 60 * 60)) / (1000 * 60));
-            const seconds = Math.floor((milliseconds % (1000 * 60)) / 1000);
-            return toTwoDigit(minutes) + " : " + toTwoDigit(seconds);
-      }
-
-      return (
-            <div className="recording-container">
-                  <div className="video-wrapper">
-                        <video id={`video-${props.id}`}
-                              autoPlay
-                              muted
-                              onTimeUpdate={handleOnTimeUpdate}
-                        />
-                        <div className="recording-sign">
-                              <span className="dot" />
-                              <p className="timer">{millisecondToMinuteSecond(recordingTimer * 10)}</p>
+            return true; // cancels propagation to documentView to avoid selecting it.
+        }, false, false);
+    }
+
+    const clearPrevious = () => {
+        const numVideos = videos.length
+        setRecordingTimer(numVideos == 1 ? 0 : videos[numVideos - 2].endTime)
+        setVideoProgressHelper(numVideos == 1 ? 0 : videos[numVideos - 2].endTime)
+        setVideos(videos.filter((_, idx) => idx !== numVideos - 1));
+    }
+
+    const handleOnTimeUpdate = () => {
+        if (playing) {
+            setVideoProgressHelper(videoElementRef.current!.currentTime)
+        }
+    };
+
+    const millisecondToMinuteSecond = (milliseconds: number) => {
+        const toTwoDigit = (digit: number) => {
+            return String(digit).length == 1 ? "0" + digit : digit
+        }
+        const minutes = Math.floor((milliseconds % (1000 * 60 * 60)) / (1000 * 60));
+        const seconds = Math.floor((milliseconds % (1000 * 60)) / 1000);
+        return toTwoDigit(minutes) + " : " + toTwoDigit(seconds);
+    }
+
+    return (
+        <div className="recording-container">
+            <div className="video-wrapper">
+                <video id={`video-${props.id}`}
+                    autoPlay
+                    muted
+                    onTimeUpdate={handleOnTimeUpdate}
+                />
+                <div className="recording-sign">
+                    <span className="dot" />
+                    <p className="timer">{millisecondToMinuteSecond(recordingTimer * 10)}</p>
+                </div>
+                <div className="controls">
+
+                    <div className="controls-inner-container">
+                        <div className="record-button-wrapper">
+                            {recording ?
+                                <button className="stop-button" onPointerDown={pause} /> :
+                                <button className="record-button" onPointerDown={startOrResume} />
+                            }
                         </div>
-                        <div className="controls">
-
-                              <div className="controls-inner-container">
-                                    <div className="record-button-wrapper">
-                                          {recording ?
-                                                <button className="stop-button" onPointerDown={pause} /> :
-                                                <button className="record-button" onPointerDown={startOrResume} />
-                                          }
-                                    </div>
 
-                                    {!recording && (videos.length > 0 ?
+                        {!recording && (videos.length > 0 ?
 
-                                          <div className="options-wrapper video-edit-wrapper">
-                                                {/* <IconContext.Provider value={{ color: "grey", className: "video-edit-buttons" }}>
+                            <div className="options-wrapper video-edit-wrapper">
+                                {/* <IconContext.Provider value={{ color: "grey", className: "video-edit-buttons" }}>
                                                       <MdBackspace onClick={clearPrevious} />
                                                 </IconContext.Provider> */}
-                                                <IconContext.Provider value={{ color: "#cc1c08", className: "video-edit-buttons" }}>
-                                                      <FaCheckCircle onClick={stop} />
-                                                </IconContext.Provider>
-                                          </div>
-
-                                          : <div className="options-wrapper track-screen-wrapper">
-                                                <label className="track-screen">
-                                                      <input type="checkbox" checked={trackScreen} onChange={(e) => { setTrackScreen(e.target.checked) }} />
-                                                      <span className="checkmark"></span>
-                                                      Track Screen
-                                                </label>
-                                          </div>)}
-
-                              </div>
-
-                              <ProgressBar
-                                    progress={progress}
-                                    marks={videos.map((elt) => elt.endTime / MAXTIME * 100)}
-                              // playSegment={playSegment}
-                              />
-                        </div>
-                  </div>
-            </div>)
+                                <IconContext.Provider value={{ color: "#cc1c08", className: "video-edit-buttons" }}>
+                                    <FaCheckCircle onClick={stop} />
+                                </IconContext.Provider>
+                            </div>
+
+                            : <div className="options-wrapper track-screen-wrapper">
+                                <label className="track-screen">
+                                    <input type="checkbox" checked={trackScreen} onChange={(e) => { setTrackScreen(e.target.checked) }} />
+                                    <span className="checkmark"></span>
+                                    Track Screen
+                                </label>
+                            </div>)}
+
+                    </div>
+
+                    <ProgressBar
+                        progress={progress}
+                        marks={videos.map((elt) => elt.endTime / MAXTIME * 100)}
+                    // playSegment={playSegment}
+                    />
+                </div>
+            </div>
+        </div>)
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2

