change(ui): display timeline on the assist by default

This commit is contained in:
sylenien 2022-09-15 15:18:05 +02:00 committed by Delirium
parent 7b65531ca7
commit cac29f9e87
9 changed files with 95 additions and 69 deletions

View file

@ -26,7 +26,7 @@ function ChatWindow({ userId, incomeStream, localStream, endCall, isPrestart }:
>
<div className="handle flex items-center p-2 cursor-move select-none border-b">
<div className={stl.headerTitle}>
<b>Talking to </b> {userId ? userId : 'Anonymous User'}
<b>Call with </b> {userId ? userId : 'Anonymous User'}
<br />
{incomeStream && incomeStream.length > 2 ? ' (+ other agents in the call)' : ''}
</div>

View file

@ -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 (
<div className={styles.controls}>
{!live || liveTimeTravel ? (
<Timeline
live={live}
jump={this.props.jump}
liveTimeTravel={liveTimeTravel}
pause={this.props.pause}
togglePlay={this.props.togglePlay}
/>
) : null}
<Timeline
live={live}
jump={this.props.jump}
liveTimeTravel={liveTimeTravel}
pause={this.props.pause}
togglePlay={this.props.togglePlay}
/>
{!fullscreen && (
<div className={cn(styles.buttons, { '!px-5 !pt-0': live })} data-is-live={live}>
<div className="flex items-center">
@ -370,15 +368,6 @@ export default class Controls extends React.Component {
<div className="font-semibold px-2">
<AssistDuration isLivePlay={livePlay} />
</div>
{!liveTimeTravel && (
<div
onClick={toggleTimetravel}
className="p-2 ml-2 rounded hover:bg-teal-light bg-gray-lightest cursor-pointer"
>
See Past Activity
</div>
)}
</div>
)}
</div>

View file

@ -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 {
<div className="flex items-center absolute w-full" style={{ top: '-4px', zIndex: 100, padding: `0 ${BOUNDRY}px`, maxWidth: '100%' }}>
<div
className={stl.progress}
onClick={disabled ? null : this.seekProgress}
onClick={disabled ? null : this.jumpToTime}
ref={this.progressRef}
role="button"
onMouseMoveCapture={this.showTimeTooltip}
onMouseEnter={this.showTimeTooltip}
onMouseLeave={this.hideTimeTooltip}
>
<TooltipContainer liveTimeTravel={liveTimeTravel} />
<TooltipContainer live={live} />
{/* custo color is live */}
<DraggableCircle left={this.props.time * scale} onDrop={this.onDragEnd} live={this.props.live} />
<CustomDragLayer

View file

@ -3,11 +3,11 @@ import TimeTooltip from '../TimeTooltip';
import store from 'App/store';
import { Provider } from 'react-redux';
function TooltipContainer({ liveTimeTravel }: { liveTimeTravel: boolean }) {
function TooltipContainer({ live }: { live: boolean }) {
return (
<Provider store={store}>
<TimeTooltip liveTimeTravel={liveTimeTravel} />
<TimeTooltip liveTimeTravel={live} />
</Provider>
)
}

View file

@ -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 ? <RequestingWindow /> : null}

View file

@ -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) {

View file

@ -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() {

View file

@ -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);

View file

@ -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))