feat(player): connect performance, xray and events to tab state

This commit is contained in:
nick-delirium 2023-05-16 13:53:40 +02:00
parent dcfd6a553d
commit 6cbdb42035
13 changed files with 49 additions and 687 deletions

View file

@ -1,174 +0,0 @@
import React from 'react';
import copy from 'copy-to-clipboard';
import cn from 'classnames';
import { Icon, TextEllipsis } from 'UI';
import { TYPES } from 'Types/session/event';
import { prorata } from 'App/utils';
import withOverlay from 'Components/hocs/withOverlay';
import LoadInfo from './LoadInfo';
import cls from './event.module.css';
import { numberWithCommas } from 'App/utils';
@withOverlay()
export default class Event extends React.PureComponent {
state = {
menuOpen: false,
}
componentDidMount() {
this.wrapper.addEventListener('contextmenu', this.onContextMenu);
}
onContextMenu = (e) => {
e.preventDefault();
this.setState({ menuOpen: true });
}
onMouseLeave = () => this.setState({ menuOpen: false })
copyHandler = (e) => {
e.stopPropagation();
//const ctrlOrCommandPressed = e.ctrlKey || e.metaKey;
//if (ctrlOrCommandPressed && e.keyCode === 67) {
const { event } = this.props;
copy(event.getIn([ 'target', 'path' ]) || event.url || '');
this.setState({ menuOpen: false });
}
toggleInfo = (e) => {
e.stopPropagation();
this.props.toggleInfo();
}
// eslint-disable-next-line complexity
renderBody = () => {
const { event } = this.props;
let title = event.type;
let body;
switch (event.type) {
case TYPES.LOCATION:
title = 'Visited';
body = event.url;
break;
case TYPES.CLICK:
title = 'Clicked';
body = event.label;
break;
case TYPES.INPUT:
title = 'Input';
body = event.value;
break;
case TYPES.CLICKRAGE:
title = `${ event.count } Clicks`;
body = event.label;
break;
case TYPES.IOS_VIEW:
title = 'View';
body = event.name;
break;
}
const isLocation = event.type === TYPES.LOCATION;
const isClickrage = event.type === TYPES.CLICKRAGE;
return (
<div className={ cn(cls.main, 'flex flex-col w-full') } >
<div className="flex items-center w-full">
{ event.type && <Icon name={`event/${event.type.toLowerCase()}`} size="16" color={isClickrage? 'red' : 'gray-dark' } /> }
<div className="ml-3 w-full">
<div className="flex w-full items-first justify-between">
<div className="flex items-center w-full" style={{ minWidth: '0'}}>
<span className={cls.title}>{ title }</span>
{/* { body && !isLocation && <div className={ cls.data }>{ body }</div> } */}
{ body && !isLocation &&
<TextEllipsis maxWidth="60%" className="w-full ml-2 text-sm color-gray-medium" text={body} />
}
</div>
{ isLocation && event.speedIndex != null &&
<div className="color-gray-medium flex font-medium items-center leading-none justify-end">
<div className="font-size-10 pr-2">{"Speed Index"}</div>
<div>{ numberWithCommas(event.speedIndex || 0) }</div>
</div>
}
</div>
{ event.target && event.target.label &&
<div className={ cls.badge } >{ event.target.label }</div>
}
</div>
</div>
{ isLocation &&
<div className="mt-1">
<span className="text-sm font-normal color-gray-medium">{ body }</span>
</div>
}
</div>
);
};
render() {
const {
event,
selected,
isCurrent,
onClick,
showSelection,
onCheckboxClick,
showLoadInfo,
toggleLoadInfo,
isRed,
extended,
highlight = false,
presentInSearch = false,
isLastInGroup,
whiteBg,
} = this.props;
const { menuOpen } = this.state;
return (
<div
ref={ ref => { this.wrapper = ref } }
onMouseLeave={ this.onMouseLeave }
data-openreplay-label="Event"
data-type={event.type}
className={ cn(cls.event, {
[ cls.menuClosed ]: !menuOpen,
[ cls.highlighted ]: showSelection ? selected : isCurrent,
[ cls.selected ]: selected,
[ cls.showSelection ]: showSelection,
[ cls.red ]: isRed,
[ cls.clickType ]: event.type === TYPES.CLICK,
[ cls.inputType ]: event.type === TYPES.INPUT,
[ cls.clickrageType ]: event.type === TYPES.CLICKRAGE,
[ cls.highlight ] : presentInSearch,
[ cls.lastInGroup ]: whiteBg,
}) }
onClick={ onClick }
>
{ menuOpen &&
<button onClick={ this.copyHandler } className={ cls.contextMenu }>
{ event.target ? 'Copy CSS' : 'Copy URL' }
</button>
}
<div className={ cls.topBlock }>
<div className={ cls.firstLine }>
{ this.renderBody() }
</div>
{/* { event.type === TYPES.LOCATION &&
<div className="text-sm font-normal color-gray-medium">{event.url}</div>
} */}
</div>
{ event.type === TYPES.LOCATION && (event.fcpTime || event.visuallyComplete || event.timeToInteractive) &&
<LoadInfo
showInfo={ showLoadInfo }
onClick={ toggleLoadInfo }
event={ event }
prorata={ prorata({
parts: 100,
elements: { a: event.fcpTime, b: event.visuallyComplete, c: event.timeToInteractive },
startDivisorFn: elements => elements / 1.2,
// eslint-disable-next-line no-mixed-operators
divisorFn: (elements, parts) => elements / (2 * parts + 1),
}) }
/>
}
</div>
);
}
}

View file

@ -1,130 +0,0 @@
import React from 'react';
import cn from 'classnames';
import { connect } from 'react-redux'
import { TextEllipsis } from 'UI';
import withToggle from 'HOCs/withToggle';
import { TYPES } from 'Types/session/event';
import Event from './Event'
import stl from './eventGroupWrapper.module.css';
import NoteEvent from './NoteEvent';
import { setEditNoteTooltip } from 'Duck/sessions';;
// TODO: incapsulate toggler in LocationEvent
@withToggle('showLoadInfo', 'toggleLoadInfo')
@connect(
(state) => ({
members: state.getIn(['members', 'list']),
currentUserId: state.getIn(['user', 'account', 'id']),
}),
{ setEditNoteTooltip }
)
class EventGroupWrapper extends React.Component {
toggleLoadInfo = (e) => {
e.stopPropagation();
this.props.toggleLoadInfo();
};
componentDidUpdate(prevProps) {
if (
prevProps.showLoadInfo !== this.props.showLoadInfo ||
prevProps.query !== this.props.query ||
prevProps.event.timestamp !== this.props.event.timestamp ||
prevProps.isNote !== this.props.isNote
) {
this.props.mesureHeight();
}
}
componentDidMount() {
this.props.toggleLoadInfo(this.props.isFirst);
this.props.mesureHeight();
}
onEventClick = (e) => this.props.onEventClick(e, this.props.event);
onCheckboxClick = (e) => this.props.onCheckboxClick(e, this.props.event);
render() {
const {
event,
isLastEvent,
isLastInGroup,
isSelected,
isCurrent,
isEditing,
showSelection,
showLoadInfo,
isFirst,
presentInSearch,
isNote,
filterOutNote,
} = this.props;
const isLocation = event.type === TYPES.LOCATION;
const whiteBg =
(isLastInGroup && event.type !== TYPES.LOCATION) ||
(!isLastEvent && event.type !== TYPES.LOCATION);
const safeRef = String(event.referrer || '');
return (
<div
className={cn(
stl.container,
'!py-1',
{
[stl.last]: isLastInGroup,
[stl.first]: event.type === TYPES.LOCATION,
[stl.dashAfter]: isLastInGroup && !isLastEvent,
},
isLastInGroup && '!pb-2',
event.type === TYPES.LOCATION && '!pt-2 !pb-2'
)}
>
{isFirst && isLocation && event.referrer && (
<div className={stl.referrer}>
<TextEllipsis>
Referrer: <span className={stl.url}>{safeRef}</span>
</TextEllipsis>
</div>
)}
{isNote ? (
<NoteEvent
note={event}
filterOutNote={filterOutNote}
onEdit={this.props.setEditNoteTooltip}
noEdit={this.props.currentUserId !== event.userId}
/>
) : isLocation ? (
<Event
extended={isFirst}
key={event.key}
event={event}
onClick={this.onEventClick}
selected={isSelected}
showLoadInfo={showLoadInfo}
toggleLoadInfo={this.toggleLoadInfo}
isCurrent={isCurrent}
presentInSearch={presentInSearch}
isLastInGroup={isLastInGroup}
whiteBg={whiteBg}
/>
) : (
<Event
key={event.key}
event={event}
onClick={this.onEventClick}
onCheckboxClick={this.onCheckboxClick}
selected={isSelected}
isCurrent={isCurrent}
showSelection={showSelection}
overlayed={isEditing}
presentInSearch={presentInSearch}
isLastInGroup={isLastInGroup}
whiteBg={whiteBg}
/>
)}
</div>
);
}
}
export default EventGroupWrapper

View file

@ -1,192 +0,0 @@
import React from 'react';
import { connect } from 'react-redux';
import cn from 'classnames';
import { Icon } from 'UI';
import { List, AutoSizer, CellMeasurer } from "react-virtualized";
import { TYPES } from 'Types/session/event';
import { setEventFilter, filterOutNote } from 'Duck/sessions';
import EventGroupWrapper from './EventGroupWrapper';
import styles from './eventsBlock.module.css';
import EventSearch from './EventSearch/EventSearch';
import { PlayerContext } from 'App/components/Session/playerContext';
import { observer } from 'mobx-react-lite';
import { RootStore } from 'App/duck'
import useCellMeasurerCache from 'App/hooks/useCellMeasurerCache'
import { InjectedEvent } from 'Types/session/event'
import Session from 'Types/session'
interface IProps {
setEventFilter: (filter: { query: string }) => void
filteredEvents: InjectedEvent[]
setActiveTab: (tab?: string) => void
query: string
events: Session['events']
notesWithEvents: Session['notesWithEvents']
filterOutNote: (id: string) => void
eventsIndex: number[]
}
function EventsBlock(props: IProps) {
const [mouseOver, setMouseOver] = React.useState(true)
const scroller = React.useRef<List>(null)
const cache = useCellMeasurerCache( {
fixedWidth: true,
defaultHeight: 300
});
const { store, player } = React.useContext(PlayerContext)
const { eventListNow, playing } = store.get()
const {
filteredEvents,
eventsIndex,
filterOutNote,
query,
setActiveTab,
events,
notesWithEvents,
} = props
const currentTimeEventIndex = eventListNow.length > 0 ? eventListNow.length - 1 : 0
const usedEvents = filteredEvents || notesWithEvents
const write = ({ target: { value } }: React.ChangeEvent<HTMLInputElement>) => {
props.setEventFilter({ query: value })
setTimeout(() => {
if (!scroller.current) return;
scroller.current.scrollToRow(0);
}, 100)
}
const clearSearch = () => {
props.setEventFilter({ query: '' })
if (scroller.current) {
scroller.current.forceUpdateGrid();
}
setTimeout(() => {
if (!scroller.current) return;
scroller.current.scrollToRow(0);
}, 100)
}
React.useEffect(() => {
return () => {
clearSearch()
}
}, [])
React.useEffect(() => {
if (scroller.current) {
scroller.current.forceUpdateGrid();
if (!mouseOver) {
scroller.current.scrollToRow(currentTimeEventIndex);
}
}
}, [currentTimeEventIndex])
const onEventClick = (_: React.MouseEvent, event: { time: number }) => player.jump(event.time)
const onMouseOver = () => setMouseOver(true)
const onMouseLeave = () => setMouseOver(false)
const renderGroup = ({ index, key, style, parent }: { index: number; key: string; style: React.CSSProperties; parent: any }) => {
const isLastEvent = index === usedEvents.length - 1;
const isLastInGroup = isLastEvent || usedEvents[index + 1]?.type === TYPES.LOCATION;
const event = usedEvents[index];
const isNote = 'noteId' in event
const isCurrent = index === currentTimeEventIndex;
const heightBug = index === 0 && event?.type === TYPES.LOCATION && 'referrer' in event ? { top: 2 } : {}
return (
<CellMeasurer
key={key}
cache={cache}
parent={parent}
rowIndex={index}
>
{({measure, registerChild}) => (
<div style={{ ...style, ...heightBug }} ref={registerChild}>
<EventGroupWrapper
query={query}
presentInSearch={eventsIndex.includes(index)}
isFirst={index==0}
mesureHeight={measure}
onEventClick={ onEventClick }
event={ event }
isLastEvent={ isLastEvent }
isLastInGroup={ isLastInGroup }
isCurrent={ isCurrent }
showSelection={ !playing }
isNote={isNote}
filterOutNote={filterOutNote}
/>
</div>
)}
</CellMeasurer>
);
}
const isEmptySearch = query && (usedEvents.length === 0 || !usedEvents)
return (
<>
<div className={ cn(styles.header, 'p-4') }>
<div className={ cn(styles.hAndProgress, 'mt-3') }>
<EventSearch
onChange={write}
setActiveTab={setActiveTab}
value={query}
header={
<div className="text-xl">User Events <span className="color-gray-medium">{ events.length }</span></div>
}
/>
</div>
</div>
<div
className={ cn("flex-1 px-4 pb-4", styles.eventsList) }
id="eventList"
data-openreplay-masked
onMouseOver={ onMouseOver }
onMouseLeave={ onMouseLeave }
>
{isEmptySearch && (
<div className='flex items-center'>
<Icon name="binoculars" size={18} />
<span className='ml-2'>No Matching Results</span>
</div>
)}
<AutoSizer disableWidth>
{({ height }) => (
<List
ref={scroller}
className={ styles.eventsList }
height={height + 10}
width={248}
overscanRowCount={6}
itemSize={230}
rowCount={usedEvents.length}
deferredMeasurementCache={cache}
rowHeight={cache.rowHeight}
rowRenderer={renderGroup}
scrollToAlignment="start"
/>
)}
</AutoSizer>
</div>
</>
);
}
export default connect((state: RootStore) => ({
session: state.getIn([ 'sessions', 'current' ]),
notesWithEvents: state.getIn([ 'sessions', 'current' ]).notesWithEvents,
events: state.getIn([ 'sessions', 'current' ]).events,
filteredEvents: state.getIn([ 'sessions', 'filteredEvents' ]),
query: state.getIn(['sessions', 'eventsQuery']),
eventsIndex: state.getIn([ 'sessions', 'eventsIndex' ]),
}), {
setEventFilter,
filterOutNote
})(observer(EventsBlock))

View file

@ -1,40 +0,0 @@
import React from 'react';
import styles from './loadInfo.module.css';
import { numberWithCommas } from 'App/utils'
const LoadInfo = ({ showInfo = false, onClick, event: { fcpTime, visuallyComplete, timeToInteractive }, prorata: { a, b, c } }) => (
<div>
<div className={ styles.bar } onClick={ onClick }>
{ typeof fcpTime === 'number' && <div style={ { width: `${ a }%` } } /> }
{ typeof visuallyComplete === 'number' && <div style={ { width: `${ b }%` } } /> }
{ typeof timeToInteractive === 'number' && <div style={ { width: `${ c }%` } } /> }
</div>
<div className={ styles.bottomBlock } data-hidden={ !showInfo }>
{ typeof fcpTime === 'number' &&
<div className={ styles.wrapper }>
<div className={ styles.lines } />
<div className={ styles.label } >{ 'Time to Render' }</div>
<div className={ styles.value }>{ `${ numberWithCommas(fcpTime || 0) }ms` }</div>
</div>
}
{ typeof visuallyComplete === 'number' &&
<div className={ styles.wrapper }>
<div className={ styles.lines } />
<div className={ styles.label } >{ 'Visually Complete' }</div>
<div className={ styles.value }>{ `${ numberWithCommas(visuallyComplete || 0) }ms` }</div>
</div>
}
{ typeof timeToInteractive === 'number' &&
<div className={ styles.wrapper }>
<div className={ styles.lines } />
<div className={ styles.label } >{ 'Time To Interactive' }</div>
<div className={ styles.value }>{ `${ numberWithCommas(timeToInteractive || 0) }ms` }</div>
</div>
}
</div>
</div>
);
LoadInfo.displayName = 'LoadInfo';
export default LoadInfo;

View file

@ -1,127 +0,0 @@
import React from 'react';
import { Icon } from 'UI';
import { tagProps, Note } from 'App/services/NotesService';
import { formatTimeOrDate } from 'App/date';
import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import { ItemMenu } from 'UI';
import copy from 'copy-to-clipboard';
import { toast } from 'react-toastify';
import { session } from 'App/routes';
import { confirm } from 'UI';
import { TeamBadge } from 'Shared/SessionListContainer/components/Notes';
interface Props {
note: Note;
noEdit: boolean;
filterOutNote: (id: number) => void;
onEdit: (noteTooltipObj: Record<string, any>) => void;
}
function NoteEvent(props: Props) {
const { settingsStore, notesStore } = useStore();
const { timezone } = settingsStore.sessionSettings;
const onEdit = () => {
props.onEdit({
isVisible: true,
isEdit: true,
time: props.note.timestamp,
note: {
timestamp: props.note.timestamp,
tag: props.note.tag,
isPublic: props.note.isPublic,
message: props.note.message,
sessionId: props.note.sessionId,
noteId: props.note.noteId,
},
});
};
const onCopy = () => {
copy(
`${window.location.origin}/${window.location.pathname.split('/')[1]}${session(
props.note.sessionId
)}${props.note.timestamp > 0 ? `?jumpto=${props.note.timestamp}&note=${props.note.noteId}` : `?note=${props.note.noteId}`}`
);
toast.success('Note URL copied to clipboard');
};
const onDelete = async () => {
if (
await confirm({
header: 'Confirm',
confirmButton: 'Yes, delete',
confirmation: `Are you sure you want to delete this note?`,
})
) {
notesStore.deleteNote(props.note.noteId).then((r) => {
props.filterOutNote(props.note.noteId);
toast.success('Note deleted');
});
}
};
const menuItems = [
{ icon: 'pencil', text: 'Edit', onClick: onEdit, disabled: props.noEdit },
{ icon: 'link-45deg', text: 'Copy URL', onClick: onCopy },
{ icon: 'trash', text: 'Delete', onClick: onDelete },
];
return (
<div
className="flex items-start flex-col p-2 border rounded"
style={{ background: '#FFFEF5' }}
>
<div className="flex items-center w-full relative">
<div className="p-3 bg-gray-light rounded-full">
<Icon name="quotes" color="main" />
</div>
<div className="ml-2">
<div
className="text-base"
style={{
maxWidth: 150,
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
>
{props.note.userName}
</div>
<div className="text-disabled-text text-sm">
{formatTimeOrDate(props.note.createdAt as unknown as number, timezone)}
</div>
</div>
<div className="cursor-pointer absolute" style={{ right: -5 }}>
<ItemMenu bold items={menuItems} />
</div>
</div>
<div
className="text-base capitalize-first my-3 overflow-y-scroll overflow-x-hidden"
style={{ maxHeight: 200, maxWidth: 220 }}
>
{props.note.message}
</div>
<div>
<div className="flex items-center gap-2 flex-wrap w-full">
{props.note.tag ? (
<div
key={props.note.tag}
style={{
// @ts-ignore
background: tagProps[props.note.tag],
userSelect: 'none',
padding: '1px 6px',
}}
className="rounded-full text-white text-xs select-none w-fit"
>
{props.note.tag}
</div>
) : null}
{!props.note.isPublic ? null : <TeamBadge />}
</div>
</div>
</div>
);
}
export default observer(NoteEvent);

View file

@ -1 +0,0 @@
export { default } from './EventsBlock';

View file

@ -29,14 +29,14 @@ interface IProps {
function EventsBlock(props: IProps) {
const [mouseOver, setMouseOver] = React.useState(true);
const scroller = React.useRef<List>(null);
const cache = useCellMeasurerCache( {
const cache = useCellMeasurerCache({
fixedWidth: true,
defaultHeight: 300,
});
const { store, player } = React.useContext(PlayerContext);
const { eventListNow, playing } = store.get();
const { playing, tabStates } = store.get();
const {
filteredEvents,
@ -44,10 +44,14 @@ function EventsBlock(props: IProps) {
filterOutNote,
query,
setActiveTab,
events,
notesWithEvents,
} = props;
// TODO! multitab tab id
const eventListNow = Object.values(tabStates).reduce((acc: any[], tab) => {
return acc.concat(tab.eventListNow)
}, [])
const currentTimeEventIndex = eventListNow.length > 0 ? eventListNow.length - 1 : 0;
const usedEvents = filteredEvents || notesWithEvents;

View file

@ -21,6 +21,7 @@ import stl from './performance.module.css';
import BottomBlock from '../BottomBlock';
import InfoLine from '../BottomBlock/InfoLine';
import { toJS } from "mobx";
const CPU_VISUAL_OFFSET = 10;
@ -183,17 +184,22 @@ function Performance({
const [_data, setData] = React.useState<any[]>([])
const {
performanceChartTime,
performanceChartData,
connType,
connBandwidth,
performanceAvailability: availability,
tabStates,
currentTab,
} = store.get();
React.useState(() => {
const {
performanceChartTime = [],
performanceChartData = [],
performanceAvailability: availability = {}
} = tabStates[currentTab];
React.useEffect(() => {
setTicks(generateTicks(performanceChartData));
setData(addFpsMetadata(performanceChartData));
})
}, [currentTab])
const onDotClick = ({ index: pointer }: { index: number }) => {

View file

@ -151,11 +151,16 @@ function NetworkPanel({ startedAt }: { startedAt: number }) {
domContentLoadedTime,
loadTime,
domBuildingTime,
fetchList,
resourceList,
fetchListNow,
resourceListNow,
tabStates,
currentTab
} = store.get()
const {
fetchList = [],
resourceList = [],
fetchListNow = [],
resourceListNow = []
} = tabStates[currentTab]
const { showModal } = useModal();
const [sortBy, setSortBy] = useState('time');
const [sortAscending, setSortAscending] = useState(true);

View file

@ -22,7 +22,12 @@ const TABS = TAB_KEYS.map((tab) => ({ text: tab, key: tab }))
function StackEventPanel() {
const { player, store } = React.useContext(PlayerContext)
const jump = (t: number) => player.jump(t)
const { stackList: list, stackListNow: listNow } = store.get()
const { currentTab, tabStates } = store.get()
const {
stackList: list = [],
stackListNow: listNow = [],
} = tabStates[currentTab]
const {
sessionStore: { devTools },

View file

@ -6,7 +6,6 @@ import useCancelableTimeout from 'App/hooks/useCancelableTimeout'
const TIMEOUT_DURATION = 5000;
export function getLastItemTime(...lists: Timed[][]) {
console.log(lists)
return Math.max(...lists.map(l => l.length ? l[l.length-1].time : 0))
}

View file

@ -64,9 +64,7 @@ export const visualChanges = [
export default class MessageManager {
static INITIAL_STATE: State = {
...SCREEN_INITIAL_STATE,
tabStates: {
'': { ...TabSessionManager.INITIAL_STATE },
},
tabStates: {},
skipIntervals: [],
error: false,
ready: false,
@ -125,6 +123,7 @@ export default class MessageManager {
this.activityManager.end()
this.state.update({ skipIntervals: this.activityManager.list })
}
Object.values(this.tabs).forEach(tab => tab.onFileReadSuccess?.())
}
public onFileReadFailed = (e: any) => {
@ -176,7 +175,7 @@ export default class MessageManager {
this.activeTab = tabId
}
if (!this.tabs[this.activeTab]) {
console.log(this.tabs, this.activeTab, tabId, this.activeTabManager.list)
console.error('missing tab state', this.tabs, this.activeTab, tabId, this.activeTabManager.list)
}
// console.log(this.tabs, this.activeTab)
this.tabs[this.activeTab].move(t)
@ -187,7 +186,7 @@ export default class MessageManager {
}
}
public changeTab(tabId) {
public changeTab(tabId: string) {
this.activeTab = tabId
this.state.update({ currentTab: tabId })
this.tabs[tabId].move(this.state.get().time)

View file

@ -1,7 +1,7 @@
import ListWalker from "Player/common/ListWalker";
import {
ConnectionInformation,
Message, MType,
Message, MType, ResourceTiming,
SetPageLocation,
SetViewportScroll,
SetViewportSize
@ -22,13 +22,20 @@ import { isDOMType } from "Player/web/messages/filters.gen";
export interface TabState extends ListsState {
performanceAvailability?: PerformanceTrackManager['availability']
performanceChartData: PerformanceChartPoint[],
performanceChartTime: PerformanceChartPoint[]
cssLoading: boolean,
}
/**
* DO NOT DELETE UNUSED METHODS
* THEY'RE ALL USED IN MESSAGE MANAGER VIA this.tabs[id]
* */
export default class TabSessionManager {
static INITIAL_STATE: TabState = {
...LISTS_INITIAL_STATE,
performanceChartData: [],
performanceChartTime: [],
cssLoading: false,
}
@ -155,7 +162,7 @@ export default class TabSessionManager {
case MType.ResourceTiming:
// TODO: merge `resource` and `fetch` lists into one here instead of UI
if (msg.initiator !== ResourceType.FETCH && msg.initiator !== ResourceType.XHR) {
this.lists.lists.resource.insert(getResourceFromResourceTiming(msg, this.sessionStart))
this.lists.lists.resource.insert(getResourceFromResourceTiming(msg as ResourceTiming, this.sessionStart))
}
break;
case MType.Fetch:
@ -211,7 +218,7 @@ export default class TabSessionManager {
}
move(t: number, index?: number): void {
const stateToUpdate: Partial<State> = {};
const stateToUpdate: Record<string, any> = {};
/* == REFACTOR_ME == */
const lastLoadedLocationMsg = this.loadedLocationManager.moveGetLast(t, index);
if (!!lastLoadedLocationMsg) {
@ -300,7 +307,8 @@ export default class TabSessionManager {
}
public onFileReadSuccess = () => {
const stateToUpdate : Partial<State>= {
console.log('triggered', this.performanceTrackManager)
const stateToUpdate : Partial<Record<string,any>> = {
performanceChartData: this.performanceTrackManager.chartData,
performanceAvailability: this.performanceTrackManager.availability,
...this.lists.getFullListsState(),