diff --git a/frontend/app/components/Session_/Player/Controls/Controls.js b/frontend/app/components/Session_/Player/Controls/Controls.js
index 1dcbbaa21..4cc09b77a 100644
--- a/frontend/app/components/Session_/Player/Controls/Controls.js
+++ b/frontend/app/components/Session_/Player/Controls/Controls.js
@@ -10,7 +10,7 @@ import {
import LiveTag from 'Shared/LiveTag';
import { toggleTimetravel, jumpToLive } from 'Player';
-import { Icon, Button } from 'UI';
+import { Icon } from 'UI';
import { toggleInspectorMode } from 'Player';
import {
fullscreenOn,
@@ -326,15 +326,13 @@ export default class Controls extends React.Component {
return (
- {!live || liveTimeTravel ? (
-
- ) : null}
+
{!fullscreen && (
@@ -370,15 +368,6 @@ export default class Controls extends React.Component {
-
- {!liveTimeTravel && (
-
- See Past Activity
-
- )}
)}
diff --git a/frontend/app/components/Session_/Player/Controls/Timeline.js b/frontend/app/components/Session_/Player/Controls/Timeline.js
index c53018362..febd988e0 100644
--- a/frontend/app/components/Session_/Player/Controls/Timeline.js
+++ b/frontend/app/components/Session_/Player/Controls/Timeline.js
@@ -1,16 +1,12 @@
import React from 'react';
import { connect } from 'react-redux';
-import cn from 'classnames';
-import { connectPlayer, Controls } from 'Player';
-import { TimelinePointer, Icon } from 'UI';
+import { connectPlayer, Controls, toggleTimetravel } from 'Player';
import TimeTracker from './TimeTracker';
import stl from './timeline.module.css';
-import { TYPES } from 'Types/session/event';
import { setTimelinePointer, setTimelineHoverTime } from 'Duck/sessions';
import DraggableCircle from './DraggableCircle';
import CustomDragLayer from './CustomDragLayer';
import { debounce } from 'App/utils';
-import { Tooltip } from 'react-tippy';
import TooltipContainer from './components/TooltipContainer';
const BOUNDRY = 0;
@@ -84,6 +80,7 @@ let debounceTooltipChange = () => null;
@connect(
(state) => ({
issues: state.getIn(['sessions', 'current', 'issues']),
+ startedAt: state.getIn(['sessions', 'current', 'startedAt']),
clickRageTime: state.getIn(['sessions', 'current', 'clickRage']) && state.getIn(['sessions', 'current', 'clickRageTime']),
returningLocationTime:
state.getIn(['sessions', 'current', 'returningLocation']) && state.getIn(['sessions', 'current', 'returningLocationTime']),
@@ -102,10 +99,28 @@ export default class Timeline extends React.PureComponent {
this.hideTimeTooltip();
};
- getTime = (e) => {
+ loadAndSeek = async (e) => {
+ e.persist();
+ await toggleTimetravel();
+
+ setTimeout(() => {
+ this.seekProgress(e)
+ })
+ }
+
+ jumpToTime = (e) => {
+ if (this.props.live && !this.props.liveTimeTravel) {
+ this.loadAndSeek(e)
+ } else {
+ this.seekProgress(e)
+ }
+ }
+
+ getTime = (e, customEndTime) => {
const { endTime } = this.props;
const p = e.nativeEvent.offsetX / e.target.offsetWidth;
- const time = Math.max(Math.round(p * endTime), 0);
+ const targetTime = customEndTime || endTime
+ const time = Math.max(Math.round(p * targetTime), 0);
return time;
};
@@ -129,13 +144,17 @@ export default class Timeline extends React.PureComponent {
}
onDragEnd = () => {
+ const { live, liveTimeTravel } = this.props;
+ if (live && !liveTimeTravel) return;
+
if (this.wasPlaying) {
this.props.togglePlay();
}
};
onDrag = (offset) => {
- const { endTime } = this.props;
+ const { endTime, live, liveTimeTravel } = this.props;
+ if (live && !liveTimeTravel) return;
const p = (offset.x - BOUNDRY) / this.progressRef.current.offsetWidth;
const time = Math.max(Math.round(p * endTime), 0);
@@ -147,18 +166,39 @@ export default class Timeline extends React.PureComponent {
}
};
+ getLiveTime = (e) => {
+ const { startedAt } = this.props;
+ const duration = new Date().getTime() - startedAt
+ const p = e.nativeEvent.offsetX / e.target.offsetWidth;
+ const time = Math.max(Math.round(p * duration), 0);
+
+ return [time, duration];
+ };
+
showTimeTooltip = (e) => {
if (e.target !== this.progressRef.current && e.target !== this.timelineRef.current) {
return this.props.tooltipVisible && this.hideTimeTooltip();
}
- const time = this.getTime(e);
- const { endTime, liveTimeTravel } = this.props;
- const timeLineTooltip = {
- time: liveTimeTravel ? endTime - time : time,
- offset: e.nativeEvent.offsetX,
- isVisible: true,
- };
+ const { live } = this.props;
+ let timeLineTooltip;
+
+ if (live) {
+ const [time, duration] = this.getLiveTime(e);
+ timeLineTooltip = {
+ time: (duration - time),
+ offset: e.nativeEvent.offsetX,
+ isVisible: true,
+ };
+ } else {
+ const time = this.getTime(e);
+ timeLineTooltip = {
+ time: time,
+ offset: e.nativeEvent.offsetX,
+ isVisible: true,
+ }
+ }
+
debounceTooltipChange(timeLineTooltip);
};
@@ -174,13 +214,7 @@ export default class Timeline extends React.PureComponent {
skipIntervals,
disabled,
endTime,
- exceptionsList,
- resourceList,
- clickRageTime,
- stackList,
- fetchList,
- issues,
- liveTimeTravel,
+ live,
} = this.props;
const scale = 100 / endTime;
@@ -189,14 +223,14 @@ export default class Timeline extends React.PureComponent {
-
+
{/* custo color is live */}
-
+
)
}
diff --git a/frontend/app/components/Session_/Player/Overlay.tsx b/frontend/app/components/Session_/Player/Overlay.tsx
index 20e84225d..85ec89487 100644
--- a/frontend/app/components/Session_/Player/Overlay.tsx
+++ b/frontend/app/components/Session_/Player/Overlay.tsx
@@ -51,7 +51,6 @@ function Overlay({
const showPlayIconLayer = !live && !markedTargets && !inspectorMode && !loading && !showAutoplayTimer;
const showLiveStatusText = live && livePlay && liveStatusText && !loading;
- console.log(calling, live)
return (
<>
{live && calling === CallingState.Connecting ? : null}
diff --git a/frontend/app/components/shared/SessionItem/Counter.tsx b/frontend/app/components/shared/SessionItem/Counter.tsx
index fd923e6c0..20731f4fc 100644
--- a/frontend/app/components/shared/SessionItem/Counter.tsx
+++ b/frontend/app/components/shared/SessionItem/Counter.tsx
@@ -1,6 +1,5 @@
import React, { useState, useEffect } from 'react'
-import { Duration } from 'luxon';
-import { durationFormatted, convertTimestampToUtcTimestamp } from 'App/date';
+import { convertTimestampToUtcTimestamp } from 'App/date';
interface Props {
startTime: any,
@@ -10,7 +9,11 @@ interface Props {
function Counter({ startTime, className }: Props) {
let intervalId: NodeJS.Timer;
const [duration, setDuration] = useState(convertTimestampToUtcTimestamp(new Date().getTime()) - convertTimestampToUtcTimestamp(startTime));
- const formattedDuration = durationFormatted(Duration.fromMillis(duration));
+
+ const secsFull = ~~(duration / 1000)
+ const mins = ~~(secsFull / 60)
+ const secs = secsFull - mins * 60
+ const formattedDuration = `${mins}:${secs < 10 ? 0 : ''}${secs}`
useEffect(() => {
if (!intervalId) {
diff --git a/frontend/app/player/MessageDistributor/MessageDistributor.ts b/frontend/app/player/MessageDistributor/MessageDistributor.ts
index 8c47debe2..fefd703fd 100644
--- a/frontend/app/player/MessageDistributor/MessageDistributor.ts
+++ b/frontend/app/player/MessageDistributor/MessageDistributor.ts
@@ -6,7 +6,7 @@ import Resource, { TYPES } from 'Types/session/resource'; // MBTODO: player type
import { TYPES as EVENT_TYPES } from 'Types/session/event';
import Log from 'Types/session/log';
-import { update, getState } from '../store';
+import { update } from '../store';
import { toast } from 'react-toastify';
import {
@@ -248,7 +248,6 @@ export default class MessageDistributor extends StatedScreen {
const onData = (byteArray: Uint8Array) => {
const onReadCallback = () => this.setLastRecordedMessageTime(this.lastMessageTime)
const msgs = this.readAndDistributeMessages(byteArray, onReadCallback)
- this.sessionStart = msgs[0].time
this.processStateUpdates(msgs)
}
@@ -275,6 +274,8 @@ export default class MessageDistributor extends StatedScreen {
this.waitingForFiles = false
this.setMessagesLoading(false)
}
+
+
}
private reloadMessageManagers() {
diff --git a/frontend/app/player/Player.ts b/frontend/app/player/Player.ts
index 4d4f40ed4..ee9814275 100644
--- a/frontend/app/player/Player.ts
+++ b/frontend/app/player/Player.ts
@@ -72,15 +72,15 @@ export default class Player extends MessageDistributor {
private _startAnimation() {
let prevTime = getState().time;
let animationPrevTime = performance.now();
-
+
const nextFrame = (animationCurrentTime: number) => {
- const {
- speed,
+ const {
+ speed,
skip,
- autoplay,
- skipIntervals,
- endTime,
- live,
+ autoplay,
+ skipIntervals,
+ endTime,
+ live,
livePlay,
disconnected,
messagesLoading,
@@ -159,7 +159,7 @@ export default class Player extends MessageDistributor {
jump(time = getState().time, index: number) {
const { live, liveTimeTravel, endTime } = getState();
if (live && !liveTimeTravel) return;
-
+
if (getState().playing) {
cancelAnimationFrame(this._animationFrameRequestId);
// this._animationFrameRequestId = requestAnimationFrame(() => {
@@ -188,7 +188,7 @@ export default class Player extends MessageDistributor {
const { inspectorMode } = getState();
flag = !inspectorMode;
}
-
+
if (flag) {
this.pause();
update({ inspectorMode: true });
@@ -199,7 +199,7 @@ export default class Player extends MessageDistributor {
}
}
- markTargets(targets: { selector: string, count: number }[] | null) {
+ markTargets(targets: { selector: string, count: number }[] | null) {
this.pause();
this.setMarkedTargets(targets);
}
@@ -207,7 +207,7 @@ export default class Player extends MessageDistributor {
activeTarget(index: number) {
this.setActiveTarget(index);
}
-
+
toggleSkipToIssue() {
const skipToIssue = !getState().skipToIssue;
localStorage.setItem(SKIP_TO_ISSUE_STORAGE_KEY, `${skipToIssue}`);
@@ -219,13 +219,13 @@ export default class Player extends MessageDistributor {
update({ skipToIssue });
return skipToIssue;
}
-
+
toggleAutoplay() {
const autoplay = !getState().autoplay;
localStorage.setItem(AUTOPLAY_STORAGE_KEY, `${autoplay}`);
update({ autoplay });
}
-
+
toggleEvents(shouldShow?: boolean) {
const showEvents = shouldShow || !getState().showEvents;
localStorage.setItem(SHOW_EVENTS_STORAGE_KEY, `${showEvents}`);
@@ -252,13 +252,12 @@ export default class Player extends MessageDistributor {
this._updateSpeed(Math.max(1, speed/2));
}
- toggleTimetravel() {
+ async toggleTimetravel() {
if (!getState().liveTimeTravel) {
- this.reloadWithUnprocessedFile()
- this.play()
+ return await this.reloadWithUnprocessedFile()
}
}
-
+
jumpToLive() {
cancelAnimationFrame(this._animationFrameRequestId);
this._setTime(getState().endTime);
diff --git a/frontend/app/player/singletone.js b/frontend/app/player/singletone.js
index 3c3156aa8..2d3d2255d 100644
--- a/frontend/app/player/singletone.js
+++ b/frontend/app/player/singletone.js
@@ -79,6 +79,7 @@ export const requestReleaseRemoteControl = initCheck((...args) => instance.assis
export const markTargets = initCheck((...args) => instance.markTargets(...args))
export const activeTarget = initCheck((...args) => instance.activeTarget(...args))
export const toggleAnnotation = initCheck((...args) => instance.assistManager.toggleAnnotation(...args))
+/** @type {Player.toggleTimetravel} */
export const toggleTimetravel = initCheck((...args) => instance.toggleTimetravel(...args))
export const jumpToLive = initCheck((...args) => instance.jumpToLive(...args))