feat(ui): allow devtools to be resizeable (#1605)

This commit is contained in:
Delirium 2023-11-21 11:28:40 +01:00 committed by GitHub
parent 07046cc2fb
commit 0e3b1df344
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 397 additions and 310 deletions

View file

@ -26,6 +26,7 @@ import { MobilePlayerContext } from 'App/components/Session/playerContext';
import { MobileStackEventPanel } from 'Shared/DevTools/StackEventPanel';
import ReplayWindow from "Components/Session/Player/MobilePlayer/ReplayWindow";
import PerfWarnings from "Components/Session/Player/MobilePlayer/PerfWarnings";
import { debounceUpdate, getDefaultPanelHeight } from "Components/Session/Player/ReplayPlayer/PlayerInst";
interface IProps {
fullView: boolean;
@ -42,6 +43,8 @@ interface IProps {
}
function Player(props: IProps) {
const defaultHeight = getDefaultPanelHeight()
const [panelHeight, setPanelHeight] = React.useState(defaultHeight);
const {
fullscreen,
fullscreenOff,
@ -77,6 +80,30 @@ function Player(props: IProps) {
if (!playerContext.player) return null;
const maxWidth = activeTab ? 'calc(100vw - 270px)' : '100vw';
const handleResize = (e: React.MouseEvent<HTMLDivElement>) => {
e.preventDefault();
const startY = e.clientY;
const startHeight = panelHeight;
const handleMouseUp = () => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
const handleMouseMove = (e: MouseEvent) => {
const deltaY = e.clientY - startY;
const diff = startHeight - deltaY;
const max = diff > window.innerHeight / 2 ? window.innerHeight / 2 : diff;
const newHeight = Math.max(50, max);
setPanelHeight(newHeight);
debounceUpdate(newHeight)
};
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
};
return (
<div
className={cn(stl.playerBody, 'flex-1 flex flex-col relative', fullscreen && 'pb-2')}
@ -92,11 +119,23 @@ function Player(props: IProps) {
</div>
</div>
{!fullscreen && !!bottomBlock && (
<div style={{ maxWidth, width: '100%' }}>
<div
style={{
height: panelHeight,
maxWidth,
width: '100%',
position: 'relative',
overflow: 'hidden',
}}
>
<div
onMouseDown={handleResize}
className={'w-full h-2 cursor-ns-resize absolute top-0 left-0 z-20'}
/>
{bottomBlock === OVERVIEW && <MobileOverviewPanel />}
{bottomBlock === CONSOLE && <MobileConsolePanel isLive={false} />}
{bottomBlock === CONSOLE && <MobileConsolePanel />}
{bottomBlock === STACKEVENTS && <MobileStackEventPanel />}
{bottomBlock === NETWORK && <MobileNetworkPanel />}
{bottomBlock === NETWORK && <MobileNetworkPanel panelHeight={panelHeight} />}
{bottomBlock === PERFORMANCE && <MobilePerformance />}
{bottomBlock === EXCEPTIONS && <MobileExceptions />}
</div>

View file

@ -32,6 +32,7 @@ import { OverviewPanel } from 'Components/Session_/OverviewPanel';
import ConsolePanel from 'Shared/DevTools/ConsolePanel';
import ProfilerPanel from 'Shared/DevTools/ProfilerPanel';
import { PlayerContext } from 'App/components/Session/playerContext';
import { debounce } from 'App/utils';
interface IProps {
fullView: boolean;
@ -45,7 +46,23 @@ interface IProps {
updateLastPlayedSession: (id: string) => void;
}
export const heightKey = 'playerPanelHeight'
export const debounceUpdate = debounce((height: number) => {
localStorage.setItem(heightKey, height.toString());
}, 500)
export const getDefaultPanelHeight = () => {
const storageHeight = localStorage.getItem(heightKey)
if (storageHeight) {
const height = parseInt(storageHeight, 10)
return height > window.innerHeight / 2 ? window.innerHeight / 2 : height
} else {
return 300
}
}
function Player(props: IProps) {
const defaultHeight = getDefaultPanelHeight()
const [panelHeight, setPanelHeight] = React.useState(defaultHeight);
const { fullscreen, fullscreenOff, nextId, bottomBlock, activeTab, fullView } = props;
const playerContext = React.useContext(PlayerContext);
const isReady = playerContext.store.get().ready;
@ -69,6 +86,30 @@ function Player(props: IProps) {
if (!playerContext.player) return null;
const maxWidth = activeTab ? 'calc(100vw - 270px)' : '100vw';
const handleResize = (e: React.MouseEvent<HTMLDivElement>) => {
e.preventDefault();
const startY = e.clientY;
const startHeight = panelHeight;
const handleMouseUp = () => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
const handleMouseMove = (e: MouseEvent) => {
const deltaY = e.clientY - startY;
const diff = startHeight - deltaY;
const max = diff > window.innerHeight / 2 ? window.innerHeight / 2 : diff;
const newHeight = Math.max(50, max);
setPanelHeight(newHeight);
debounceUpdate(newHeight)
};
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
};
return (
<div
className={cn(stl.playerBody, 'flex-1 flex flex-col relative', fullscreen && 'pb-2')}
@ -80,13 +121,25 @@ function Player(props: IProps) {
<div className={cn(stl.screenWrapper)} ref={screenWrapper} />
</div>
{!fullscreen && !!bottomBlock && (
<div style={{ maxWidth, width: '100%' }}>
<div
style={{
height: panelHeight,
maxWidth,
width: '100%',
position: 'relative',
overflow: 'hidden',
}}
>
<div
onMouseDown={handleResize}
className={'w-full h-2 cursor-ns-resize absolute top-0 left-0 z-20'}
/>
{bottomBlock === OVERVIEW && <OverviewPanel />}
{bottomBlock === CONSOLE && <ConsolePanel />}
{bottomBlock === NETWORK && <WebNetworkPanel />}
{bottomBlock === NETWORK && <WebNetworkPanel panelHeight={panelHeight} />}
{bottomBlock === STACKEVENTS && <WebStackEventPanel />}
{bottomBlock === STORAGE && <Storage />}
{bottomBlock === PROFILER && <ProfilerPanel />}
{bottomBlock === PROFILER && <ProfilerPanel panelHeight={panelHeight} />}
{bottomBlock === PERFORMANCE && <ConnectedPerformance />}
{bottomBlock === GRAPHQL && <GraphQL />}
{bottomBlock === EXCEPTIONS && <Exceptions />}

View file

@ -3,7 +3,6 @@
background: $white;
/* padding-right: 10px; */
/* border: solid thin $gray-light; */
height: 300px;
height: 100%;
border-top: thin dashed #cccccc;
}

View file

@ -3,7 +3,7 @@
background: $white;
/* padding-right: 10px; */
/* border: solid thin $gray-light; */
height: 300px;
height: 100%;
border-top: thin dashed #cccccc;
}

View file

@ -161,7 +161,7 @@ function ConsolePanel({ isLive }: { isLive?: boolean }) {
return (
<BottomBlock
style={{ height: '300px' }}
style={{ height: '100%' }}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>

View file

@ -79,15 +79,11 @@ function MobileConsolePanel() {
const {
logList,
// exceptionsList,
logListNow,
exceptionsListNow,
} = store.get();
const list = logList as ILog[];
// useMemo(() => logList.concat(exceptionsList).sort((a, b) => a.time - b.time),
// [ logList.length, exceptionsList.length ],
// ) as ILog[]
let filteredList = useRegExListFilterMemo(list, (l) => l.value, filter);
filteredList = useTabListFilterMemo(filteredList, (l) => LEVEL_TAB[l.level], ALL, activeTab);
@ -163,7 +159,7 @@ function MobileConsolePanel() {
return (
<BottomBlock
style={{ height: '300px' }}
style={{ height: '100%' }}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>

View file

@ -147,7 +147,7 @@ function renderStatus({ status, cached }: { status: string; cached: boolean }) {
);
}
function NetworkPanelCont({ startedAt }: { startedAt: number }) {
function NetworkPanelCont({ startedAt, panelHeight }: { startedAt: number; panelHeight: number }) {
const { player, store } = React.useContext(PlayerContext);
const { domContentLoadedTime, loadTime, domBuildingTime, tabStates, currentTab } = store.get();
@ -161,6 +161,7 @@ function NetworkPanelCont({ startedAt }: { startedAt: number }) {
return (
<NetworkPanelComp
loadTime={loadTime}
panelHeight={panelHeight}
domBuildingTime={domBuildingTime}
domContentLoadedTime={domContentLoadedTime}
fetchList={fetchList}
@ -173,7 +174,7 @@ function NetworkPanelCont({ startedAt }: { startedAt: number }) {
);
}
function MobileNetworkPanelCont({ startedAt }: { startedAt: number }) {
function MobileNetworkPanelCont({ startedAt, panelHeight }: { startedAt: number, panelHeight: number }) {
const { player, store } = React.useContext(MobilePlayerContext);
const domContentLoadedTime = undefined;
@ -189,6 +190,7 @@ function MobileNetworkPanelCont({ startedAt }: { startedAt: number }) {
return (
<NetworkPanelComp
isMobile
panelHeight={panelHeight}
loadTime={loadTime}
domBuildingTime={domBuildingTime}
domContentLoadedTime={domContentLoadedTime}
@ -219,297 +221,304 @@ interface Props {
player: WebPlayer | MobilePlayer;
startedAt: number;
isMobile?: boolean;
panelHeight: number;
}
const NetworkPanelComp = observer(({
loadTime,
domBuildingTime,
domContentLoadedTime,
fetchList,
resourceList,
fetchListNow,
resourceListNow,
player,
startedAt,
isMobile
}: Props) => {
const { showModal } = useModal();
const [sortBy, setSortBy] = useState('time');
const [sortAscending, setSortAscending] = useState(true);
const [showOnlyErrors, setShowOnlyErrors] = useState(false);
const NetworkPanelComp = observer(
({
loadTime,
domBuildingTime,
domContentLoadedTime,
fetchList,
resourceList,
fetchListNow,
resourceListNow,
player,
startedAt,
isMobile,
panelHeight,
}: Props) => {
const { showModal } = useModal();
const [sortBy, setSortBy] = useState('time');
const [sortAscending, setSortAscending] = useState(true);
const [showOnlyErrors, setShowOnlyErrors] = useState(false);
const [isDetailsModalActive, setIsDetailsModalActive] = useState(false);
const {
sessionStore: { devTools },
} = useStore();
const filter = devTools[INDEX_KEY].filter;
const activeTab = devTools[INDEX_KEY].activeTab;
const activeIndex = devTools[INDEX_KEY].index;
const [isDetailsModalActive, setIsDetailsModalActive] = useState(false);
const {
sessionStore: { devTools },
} = useStore();
const filter = devTools[INDEX_KEY].filter;
const activeTab = devTools[INDEX_KEY].activeTab;
const activeIndex = devTools[INDEX_KEY].index;
const list = useMemo(
() =>
// TODO: better merge (with body size info) - do it in player
resourceList
.filter(
(res) =>
!fetchList.some((ft) => {
// res.url !== ft.url doesn't work on relative URLs appearing within fetchList (to-fix in player)
if (res.name === ft.name) {
if (res.time === ft.time) return true;
if (res.url.includes(ft.url)) {
return (
Math.abs(res.time - ft.time) < 350 ||
Math.abs(res.timestamp - ft.timestamp) < 350
);
const list = useMemo(
() =>
// TODO: better merge (with body size info) - do it in player
resourceList
.filter(
(res) =>
!fetchList.some((ft) => {
// res.url !== ft.url doesn't work on relative URLs appearing within fetchList (to-fix in player)
if (res.name === ft.name) {
if (res.time === ft.time) return true;
if (res.url.includes(ft.url)) {
return (
Math.abs(res.time - ft.time) < 350 ||
Math.abs(res.timestamp - ft.timestamp) < 350
);
}
}
}
if (res.name !== ft.name) {
return false;
}
if (Math.abs(res.time - ft.time) > 250) {
return false;
} // TODO: find good epsilons
if (Math.abs(res.duration - ft.duration) > 200) {
return false;
}
if (res.name !== ft.name) {
return false;
}
if (Math.abs(res.time - ft.time) > 250) {
return false;
} // TODO: find good epsilons
if (Math.abs(res.duration - ft.duration) > 200) {
return false;
}
return true;
})
)
.concat(fetchList)
.sort((a, b) => a.time - b.time),
[resourceList.length, fetchList.length]
);
let filteredList = useMemo(() => {
if (!showOnlyErrors) {
return list;
}
return list.filter((it) => parseInt(it.status) >= 400 || !it.success);
}, [showOnlyErrors, list]);
filteredList = useRegExListFilterMemo(
filteredList,
(it) => [it.status, it.name, it.type],
filter
);
filteredList = useTabListFilterMemo(filteredList, (it) => TYPE_TO_TAB[it.type], ALL, activeTab);
const onTabClick = (activeTab: (typeof TAP_KEYS)[number]) =>
devTools.update(INDEX_KEY, { activeTab });
const onFilterChange = ({ target: { value } }: React.ChangeEvent<HTMLInputElement>) =>
devTools.update(INDEX_KEY, { filter: value });
// AutoScroll
const [timeoutStartAutoscroll, stopAutoscroll] = useAutoscroll(
filteredList,
getLastItemTime(fetchListNow, resourceListNow),
activeIndex,
(index) => devTools.update(INDEX_KEY, { index })
);
const onMouseEnter = stopAutoscroll;
const onMouseLeave = () => {
if (isDetailsModalActive) {
return;
}
timeoutStartAutoscroll();
};
const resourcesSize = useMemo(
() => resourceList.reduce((sum, { decodedBodySize }) => sum + (decodedBodySize || 0), 0),
[resourceList.length]
);
const transferredSize = useMemo(
() =>
resourceList.reduce(
(sum, { headerSize, encodedBodySize }) => sum + (headerSize || 0) + (encodedBodySize || 0),
0
),
[resourceList.length]
);
const referenceLines = useMemo(() => {
const arr = [];
if (domContentLoadedTime != null) {
arr.push({
time: domContentLoadedTime.time,
color: DOM_LOADED_TIME_COLOR,
});
}
if (loadTime != null) {
arr.push({
time: loadTime.time,
color: LOAD_TIME_COLOR,
});
}
return arr;
}, [domContentLoadedTime, loadTime]);
const showDetailsModal = (item: any) => {
setIsDetailsModalActive(true);
showModal(
<FetchDetailsModal
time={item.time + startedAt}
resource={item}
rows={filteredList}
fetchPresented={fetchList.length > 0}
/>,
{
right: true,
width: 500,
onClose: () => {
setIsDetailsModalActive(false);
timeoutStartAutoscroll();
},
}
return true;
})
)
.concat(fetchList)
.sort((a, b) => a.time - b.time),
[resourceList.length, fetchList.length]
);
devTools.update(INDEX_KEY, { index: filteredList.indexOf(item) });
stopAutoscroll();
};
return (
<React.Fragment>
<BottomBlock
style={{ height: '300px' }}
className="border"
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
<BottomBlock.Header>
<div className="flex items-center">
<span className="font-semibold color-gray-medium mr-4">Network</span>
{isMobile ? null :
<Tabs
className="uppercase"
tabs={TABS}
active={activeTab}
onClick={onTabClick}
border={false}
/>
}
</div>
<Input
className="input-small"
placeholder="Filter by name, type or value"
icon="search"
name="filter"
onChange={onFilterChange}
height={28}
width={230}
value={filter}
/>
</BottomBlock.Header>
<BottomBlock.Content>
<div className="flex items-center justify-between px-4">
<div>
<Toggler
checked={showOnlyErrors}
name="test"
onChange={() => setShowOnlyErrors(!showOnlyErrors)}
label="4xx-5xx Only"
/>
let filteredList = useMemo(() => {
if (!showOnlyErrors) {
return list;
}
return list.filter((it) => parseInt(it.status) >= 400 || !it.success);
}, [showOnlyErrors, list]);
filteredList = useRegExListFilterMemo(
filteredList,
(it) => [it.status, it.name, it.type],
filter
);
filteredList = useTabListFilterMemo(filteredList, (it) => TYPE_TO_TAB[it.type], ALL, activeTab);
const onTabClick = (activeTab: (typeof TAP_KEYS)[number]) =>
devTools.update(INDEX_KEY, { activeTab });
const onFilterChange = ({ target: { value } }: React.ChangeEvent<HTMLInputElement>) =>
devTools.update(INDEX_KEY, { filter: value });
// AutoScroll
const [timeoutStartAutoscroll, stopAutoscroll] = useAutoscroll(
filteredList,
getLastItemTime(fetchListNow, resourceListNow),
activeIndex,
(index) => devTools.update(INDEX_KEY, { index })
);
const onMouseEnter = stopAutoscroll;
const onMouseLeave = () => {
if (isDetailsModalActive) {
return;
}
timeoutStartAutoscroll();
};
const resourcesSize = useMemo(
() => resourceList.reduce((sum, { decodedBodySize }) => sum + (decodedBodySize || 0), 0),
[resourceList.length]
);
const transferredSize = useMemo(
() =>
resourceList.reduce(
(sum, { headerSize, encodedBodySize }) =>
sum + (headerSize || 0) + (encodedBodySize || 0),
0
),
[resourceList.length]
);
const referenceLines = useMemo(() => {
const arr = [];
if (domContentLoadedTime != null) {
arr.push({
time: domContentLoadedTime.time,
color: DOM_LOADED_TIME_COLOR,
});
}
if (loadTime != null) {
arr.push({
time: loadTime.time,
color: LOAD_TIME_COLOR,
});
}
return arr;
}, [domContentLoadedTime, loadTime]);
const showDetailsModal = (item: any) => {
setIsDetailsModalActive(true);
showModal(
<FetchDetailsModal
time={item.time + startedAt}
resource={item}
rows={filteredList}
fetchPresented={fetchList.length > 0}
/>,
{
right: true,
width: 500,
onClose: () => {
setIsDetailsModalActive(false);
timeoutStartAutoscroll();
},
}
);
devTools.update(INDEX_KEY, { index: filteredList.indexOf(item) });
stopAutoscroll();
};
return (
<React.Fragment>
<BottomBlock
style={{ height: '100%' }}
className="border"
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
<BottomBlock.Header>
<div className="flex items-center">
<span className="font-semibold color-gray-medium mr-4">Network</span>
{isMobile ? null : (
<Tabs
className="uppercase"
tabs={TABS}
active={activeTab}
onClick={onTabClick}
border={false}
/>
)}
</div>
<InfoLine>
<InfoLine.Point label={filteredList.length + ''} value=" requests" />
<InfoLine.Point
label={formatBytes(transferredSize)}
value="transferred"
display={transferredSize > 0}
/>
<InfoLine.Point
label={formatBytes(resourcesSize)}
value="resources"
display={resourcesSize > 0}
/>
<InfoLine.Point
label={formatMs(domBuildingTime)}
value="DOM Building Time"
display={domBuildingTime != null}
/>
<InfoLine.Point
label={domContentLoadedTime && formatMs(domContentLoadedTime.value)}
value="DOMContentLoaded"
display={domContentLoadedTime != null}
dotColor={DOM_LOADED_TIME_COLOR}
/>
<InfoLine.Point
label={loadTime && formatMs(loadTime.value)}
value="Load"
display={loadTime != null}
dotColor={LOAD_TIME_COLOR}
/>
</InfoLine>
</div>
<NoContent
title={
<div className="capitalize flex items-center mt-16">
<Icon name="info-circle" className="mr-2" size="18" />
No Data
<Input
className="input-small"
placeholder="Filter by name, type or value"
icon="search"
name="filter"
onChange={onFilterChange}
height={28}
width={230}
value={filter}
/>
</BottomBlock.Header>
<BottomBlock.Content>
<div className="flex items-center justify-between px-4">
<div>
<Toggler
checked={showOnlyErrors}
name="test"
onChange={() => setShowOnlyErrors(!showOnlyErrors)}
label="4xx-5xx Only"
/>
</div>
}
size="small"
show={filteredList.length === 0}
>
<TimeTable
rows={filteredList}
referenceLines={referenceLines}
renderPopup
onRowClick={showDetailsModal}
sortBy={sortBy}
sortAscending={sortAscending}
onJump={(row: any) => {
devTools.update(INDEX_KEY, { index: filteredList.indexOf(row) });
player.jump(row.time);
}}
activeIndex={activeIndex}
<InfoLine>
<InfoLine.Point label={filteredList.length + ''} value=" requests" />
<InfoLine.Point
label={formatBytes(transferredSize)}
value="transferred"
display={transferredSize > 0}
/>
<InfoLine.Point
label={formatBytes(resourcesSize)}
value="resources"
display={resourcesSize > 0}
/>
<InfoLine.Point
label={formatMs(domBuildingTime)}
value="DOM Building Time"
display={domBuildingTime != null}
/>
<InfoLine.Point
label={domContentLoadedTime && formatMs(domContentLoadedTime.value)}
value="DOMContentLoaded"
display={domContentLoadedTime != null}
dotColor={DOM_LOADED_TIME_COLOR}
/>
<InfoLine.Point
label={loadTime && formatMs(loadTime.value)}
value="Load"
display={loadTime != null}
dotColor={LOAD_TIME_COLOR}
/>
</InfoLine>
</div>
<NoContent
title={
<div className="capitalize flex items-center mt-16">
<Icon name="info-circle" className="mr-2" size="18" />
No Data
</div>
}
size="small"
show={filteredList.length === 0}
>
{[
// {
// label: 'Start',
// width: 120,
// render: renderStart,
// },
{
label: 'Status',
dataKey: 'status',
width: 90,
render: renderStatus,
},
{
label: 'Type',
dataKey: 'type',
width: 90,
render: renderType,
},
{
label: 'Name',
width: 240,
dataKey: 'name',
render: renderName,
},
{
label: 'Size',
width: 80,
dataKey: 'decodedBodySize',
render: renderSize,
hidden: activeTab === XHR,
},
{
label: 'Duration',
width: 80,
dataKey: 'duration',
render: renderDuration,
},
]}
</TimeTable>
</NoContent>
</BottomBlock.Content>
</BottomBlock>
</React.Fragment>
);
})
{/*@ts-ignore*/}
<TimeTable
rows={filteredList}
tableHeight={panelHeight - 102}
referenceLines={referenceLines}
renderPopup
onRowClick={showDetailsModal}
sortBy={sortBy}
sortAscending={sortAscending}
onJump={(row: any) => {
devTools.update(INDEX_KEY, { index: filteredList.indexOf(row) });
player.jump(row.time);
}}
activeIndex={activeIndex}
>
{[
// {
// label: 'Start',
// width: 120,
// render: renderStart,
// },
{
label: 'Status',
dataKey: 'status',
width: 90,
render: renderStatus,
},
{
label: 'Type',
dataKey: 'type',
width: 90,
render: renderType,
},
{
label: 'Name',
width: 240,
dataKey: 'name',
render: renderName,
},
{
label: 'Size',
width: 80,
dataKey: 'decodedBodySize',
render: renderSize,
hidden: activeTab === XHR,
},
{
label: 'Duration',
width: 80,
dataKey: 'duration',
render: renderDuration,
},
]}
</TimeTable>
</NoContent>
</BottomBlock.Content>
</BottomBlock>
</React.Fragment>
);
}
);
const WebNetworkPanel = connect((state: any) => ({
startedAt: state.getIn(['sessions', 'current']).startedAt,
@ -519,7 +528,4 @@ const MobileNetworkPanel = connect((state: any) => ({
startedAt: state.getIn(['sessions', 'current']).startedAt,
}))(observer(MobileNetworkPanelCont));
export {
WebNetworkPanel,
MobileNetworkPanel
}
export { WebNetworkPanel, MobileNetworkPanel };

View file

@ -13,7 +13,7 @@ import { useRegExListFilterMemo } from '../useListFilter'
const renderDuration = (p: any) => `${p.duration}ms`;
const renderName = (p: any) => <TextEllipsis text={p.name} />;
function ProfilerPanel() {
function ProfilerPanel({ panelHeight }: { panelHeight: number }) {
const { store } = React.useContext(PlayerContext)
const { tabStates, currentTab } = store.get()
const profiles = tabStates[currentTab].profilesList || [] as any[] // TODO lest internal types
@ -26,7 +26,7 @@ function ProfilerPanel() {
showModal(<ProfilerModal profile={profile} />, { right: true, width: 500 });
};
return (
<BottomBlock>
<BottomBlock style={{ height: '100%' }}>
<BottomBlock.Header>
<div className="flex items-center">
<span className="font-semibold color-gray-medium mr-4">Profiler</span>
@ -41,7 +41,7 @@ function ProfilerPanel() {
/>
</BottomBlock.Header>
<BottomBlock.Content>
<TimeTable rows={filtered} onRowClick={onRowClick} hoverable>
<TimeTable tableHeight={panelHeight - 40} rows={filtered} onRowClick={onRowClick} hoverable>
{[
{
label: 'Name',

View file

@ -139,7 +139,7 @@ function EventsPanel({
return (
<BottomBlock
style={{ height: '300px' }}
style={{ height: '100%' }}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>

View file

@ -143,12 +143,6 @@ export default class TimeTable extends React.PureComponent<Props, State> {
scroller = React.createRef<List>();
autoScroll = true;
// componentDidMount() {
// if (this.scroller.current) {
// this.scroller.current.scrollToRow(this.props.activeIndex);
// }
// }
adjustScroll(prevActiveIndex: number) {
if (
this.props.activeIndex &&