diff --git a/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx b/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx index 08961af36..c070c3b50 100644 --- a/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx +++ b/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx @@ -26,7 +26,7 @@ function ChatWindow({ userId, incomeStream, localStream, endCall, isPrestart }: >
- Talking to {userId ? userId : 'Anonymous User'} + Call with {userId ? userId : 'Anonymous User'}
{incomeStream && incomeStream.length > 2 ? ' (+ other agents in the call)' : ''}
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))