fix(player): extract time state observing components from controls

This commit is contained in:
nick-delirium 2023-06-20 14:44:54 +02:00
parent cea9ca87e4
commit 9ba3a7e7f6
8 changed files with 139 additions and 78 deletions

View file

@ -188,8 +188,8 @@ function Performance({
const [_data, setData] = React.useState<any[]>([])
const {
connType,
connBandwidth,
// connType,
// connBandwidth,
tabStates,
currentTab,
} = store.get();
@ -237,18 +237,6 @@ function Performance({
value={formatBytes(userDeviceHeapSize)}
display={true}
/>
<InfoLine.Point
label="Connection Type"
value={connType}
display={connType != null && connType !== 'unknown'}
/>
<InfoLine.Point
label="Connection Speed"
value={
connBandwidth >= 1000 ? `${connBandwidth / 1000} Mbps` : `${connBandwidth} Kbps`
}
display={connBandwidth != null}
/>
</InfoLine>
</div>
</BottomBlock.Header>

View file

@ -0,0 +1,28 @@
import React, { useContext } from 'react';
import stl from './timeline.module.css';
import { PlayerContext } from 'Components/Session/playerContext';
import { observer } from 'mobx-react-lite';
import { getTimelinePosition } from './getTimelinePosition'
function EventsList({ scale }: { scale: number }) {
const { store } = useContext(PlayerContext);
const { tabStates, eventCount } = store.get();
const events = React.useMemo(() => {
return Object.values(tabStates)[0]?.eventList || [];
}, [eventCount]);
return (
<>
{events.map((e) => (
<div
/*@ts-ignore TODO */
key={e.key}
className={stl.event}
style={{ left: `${getTimelinePosition(e.time, scale)}%` }}
/>
))}
</>
);
}
export default observer(EventsList);

View file

@ -0,0 +1,37 @@
import React from 'react';
import { Icon } from 'UI';
import { useStore } from "App/mstore";
import { observer } from 'mobx-react-lite'
import { getTimelinePosition } from './getTimelinePosition'
function NotesList({ scale }: { scale: number }) {
const { notesStore } = useStore();
const notes = notesStore.sessionNotes;
const visibleNotes = React.useMemo(() => {
return notes.filter(note => note.timestamp > 0)
}, [notes.length])
return (
<>
{visibleNotes.map((note) => (
<div
key={note.noteId}
style={{
position: 'absolute',
background: 'white',
zIndex: 3,
pointerEvents: 'none',
height: 10,
width: 16,
left: `${getTimelinePosition(note.timestamp, scale)}%`,
}}
>
<Icon name="quotes" style={{ width: 16, height: 10 }} color="main" />
</div>
))}
</>
);
}
export default observer(NotesList)

View file

@ -0,0 +1,29 @@
import React, { useContext } from 'react';
import stl from 'Components/Session_/Player/Controls/timeline.module.css';
import { PlayerContext } from 'Components/Session/playerContext';
import { getTimelinePosition } from './getTimelinePosition';
import { observer } from 'mobx-react-lite';
function SkipIntervalsList({ scale }: { scale: number }) {
const { store } = useContext(PlayerContext);
const { skipIntervals, skip } = store.get();
if (!skip) return null;
return (
<>
{skipIntervals.map((interval) => (
<div
key={interval.start}
className={stl.skipInterval}
style={{
left: `${getTimelinePosition(interval.start, scale)}%`,
width: `${(interval.end - interval.start) * scale}%`,
}}
/>
))}
</>
);
}
export default observer(SkipIntervalsList);

View file

@ -1,6 +1,5 @@
import React, { useEffect, useMemo, useContext, useState, useRef } from 'react';
import { connect } from 'react-redux';
import { Icon } from 'UI'
import TimeTracker from './TimeTracker';
import stl from './timeline.module.css';
import { setTimelinePointer, setTimelineHoverTime } from 'Duck/sessions';
@ -13,12 +12,10 @@ import { observer } from 'mobx-react-lite';
import { useStore } from 'App/mstore';
import { DateTime, Duration } from 'luxon';
import Issue from "Types/session/issue";
function getTimelinePosition(value: number, scale: number) {
const pos = value * scale;
return pos > 100 ? 99 : pos;
}
import EventsList from './EventsList';
import NotesList from './NotesList';
import SkipIntervalsList from './SkipIntervalsList'
import TimelineTracker from "Components/Session_/Player/Controls/TimelineTracker";
interface IProps {
issues: Issue[]
@ -30,28 +27,19 @@ interface IProps {
function Timeline(props: IProps) {
const { player, store } = useContext(PlayerContext)
const [wasPlaying, setWasPlaying] = useState(false)
const { notesStore, settingsStore } = useStore();
const { settingsStore } = useStore();
const {
playing,
time,
skipIntervals,
skip,
skipToIssue,
ready,
endTime,
devtoolsLoading,
domLoading,
tabStates,
eventCount,
} = store.get()
const { issues } = props;
const notes = notesStore.sessionNotes;
const progressRef = useRef<HTMLDivElement>(null)
const timelineRef = useRef<HTMLDivElement>(null)
const events = React.useMemo(() => {
return Object.values(tabStates)[0]?.eventList || []
}, [eventCount])
const scale = 100 / endTime;
@ -151,42 +139,22 @@ function Timeline(props: IProps) {
onMouseLeave={hideTimeTooltip}
>
<TooltipContainer />
<DraggableCircle
left={time * scale}
onDrop={onDragEnd}
/>
<TimelineTracker scale={scale} onDragEnd={onDragEnd} />
<CustomDragLayer
onDrag={onDrag}
minX={0}
maxX={progressRef.current ? progressRef.current.offsetWidth : 0}
/>
<TimeTracker scale={scale} left={time * scale} />
{skip ?
skipIntervals.map((interval) => (
<div
key={interval.start}
className={stl.skipInterval}
style={{
left: `${getTimelinePosition(interval.start, scale)}%`,
width: `${(interval.end - interval.start) * scale}%`,
}}
/>
)) : null}
<div className={stl.timeline} ref={timelineRef}>
{devtoolsLoading || domLoading || !ready ? <div className={stl.stripes} /> : null}
</div>
{events.map((e) => {
if (!e || e.key == undefined) console.log(e)
return (
<div
/*@ts-ignore TODO */
key={e.key}
className={stl.event}
style={{ left: `${getTimelinePosition(e.time, scale)}%` }}
/>
)})}
<EventsList scale={scale} />
<NotesList scale={scale} />
<SkipIntervalsList scale={scale} />
{/* TODO: refactor and make any sense out of this */}
{/* {issues.map((i: Issue) => (*/}
@ -196,22 +164,6 @@ function Timeline(props: IProps) {
{/* style={{ left: `${getTimelinePosition(i.time, scale)}%` }}*/}
{/* />*/}
{/*))}*/}
{notes.map((note) => note.timestamp > 0 ? (
<div
key={note.noteId}
style={{
position: 'absolute',
background: 'white',
zIndex: 3,
pointerEvents: 'none',
height: 10,
width: 16,
left: `${getTimelinePosition(note.timestamp, scale)}%`,
}}
>
<Icon name="quotes" style={{ width: 16, height: 10 }} color="main" />
</div>
) : null)}
</div>
</div>
)

View file

@ -0,0 +1,20 @@
import React, { useContext } from 'react';
import { observer } from 'mobx-react-lite';
import DraggableCircle from 'Components/Session_/Player/Controls/components/DraggableCircle';
import TimeTracker from 'Components/Session_/Player/Controls/TimeTracker';
import { PlayerContext } from 'Components/Session/playerContext';
function TimelineTracker({ scale, onDragEnd }: { scale: number, onDragEnd: () => void }) {
const { store } = useContext(PlayerContext);
const { time } = store.get();
return (
<>
<DraggableCircle left={time * scale} onDrop={onDragEnd} />
<TimeTracker scale={scale} left={time * scale} />
</>
);
}
export default observer(TimelineTracker);

View file

@ -0,0 +1,6 @@
export function getTimelinePosition(value: number, scale: number) {
const pos = value * scale;
return pos > 100 ? 99 : pos;
}

View file

@ -264,11 +264,12 @@ export default class TabSessionManager {
// @ts-ignore comes from parent state
this.state.update({ location: lastLocationMsg.url })
}
const lastConnectionInfoMsg = this.connectionInfoManger.moveGetLast(t, index);
if (!!lastConnectionInfoMsg) {
stateToUpdate.connType = lastConnectionInfoMsg.type;
stateToUpdate.connBandwidth = lastConnectionInfoMsg.downlink;
}
// ConnectionInformation message is not used at this moment
// const lastConnectionInfoMsg = this.connectionInfoManger.moveGetLast(t, index);
// if (!!lastConnectionInfoMsg) {
// stateToUpdate.connType = lastConnectionInfoMsg.type;
// stateToUpdate.connBandwidth = lastConnectionInfoMsg.downlink;
// }
const lastPerformanceTrackMessage = this.performanceTrackManager.moveGetLast(t, index);
if (!!lastPerformanceTrackMessage) {
stateToUpdate.performanceChartTime = lastPerformanceTrackMessage.time;