Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 52 additions & 119 deletions packages/insomnia/src/ui/components/websockets/event-log-view.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { useVirtualizer } from '@tanstack/react-virtual';
import { format } from 'date-fns';
import React, { FC, useRef } from 'react';
import { useMeasure } from 'react-use';
import styled from 'styled-components';
import { Cell, Column, Row, Table, TableBody, TableHeader } from 'react-aria-components';

import { CurlEvent } from '../../../main/network/curl';
import { WebSocketEvent } from '../../../main/network/websocket';
Expand All @@ -19,67 +18,6 @@ interface Props {
onSelect: (event: WebSocketEvent | CurlEvent) => void;
}

const Divider = styled('div')({
height: '100%',
width: '1px',
backgroundColor: 'var(--hl-md)',
});

const AutoSize = styled.div({
flex: '1 0',
overflow: 'hidden',
});

const Scrollable = styled.div({
overflowY: 'scroll',
});

const HeadingRow = styled('div')({
flex: '0 0 30px',
display: 'flex',
width: '100%',
alignItems: 'center',
borderBottom: '1px solid var(--hl-md)',
paddingRight: 'var(--scrollbar-width)',
boxSizing: 'border-box',
});

const Row = styled('div')<{ isActive: boolean }>(({ isActive }) => ({
position: 'absolute',
top: 0,
left: 0,
height: '30px',
display: 'flex',
width: '100%',
alignItems: 'center',
borderBottom: '1px solid var(--hl-md)',
boxSizing: 'border-box',
backgroundColor: isActive ? 'var(--hl-lg)' : 'transparent',
}));

const List = styled('div')({
width: '100%',
position: 'relative',
});

const EventLog = styled('div')({
display: 'flex',
flexDirection: 'column',
width: '100%',
height: '100%',
overflow: 'hidden',
borderTop: '1px solid var(--hl-md)',
});

const EventIconCell = styled('div')({
flex: '0 0 15px',
height: '100%',
display: 'flex',
alignItems: 'center',
boxSizing: 'border-box',
padding: 'var(--padding-xs)',
});

function getIcon(event: WebSocketEvent | CurlEvent): SvgIconProps['icon'] {
switch (event.type) {
case 'message': {
Expand All @@ -104,14 +42,6 @@ function getIcon(event: WebSocketEvent | CurlEvent): SvgIconProps['icon'] {
}
}

const EventMessageCell = styled('div')({
flex: '1 0',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
padding: 'var(--padding-xs)',
});

const getMessage = (event: WebSocketEvent | CurlEvent): string => {
switch (event.type) {
case 'message': {
Expand All @@ -135,13 +65,8 @@ const getMessage = (event: WebSocketEvent | CurlEvent): string => {
}
};

const EventTimestampCell = styled('div')({
flex: '0 0 80px',
padding: 'var(--padding-xs)',
});

export const EventLogView: FC<Props> = ({ events, onSelect, selectionId }) => {
const parentRef = useRef<HTMLDivElement>(null);
const parentRef = useRef<HTMLTableSectionElement>(null);
const virtualizer = useVirtualizer({
getScrollElement: () => parentRef.current,
count: events.length,
Expand All @@ -150,55 +75,63 @@ export const EventLogView: FC<Props> = ({ events, onSelect, selectionId }) => {
getItemKey: index => events[index]._id,
});

const [autoSizeRef, { height }] = useMeasure<HTMLDivElement>();

return (
<EventLog>
<HeadingRow>
<EventIconCell>
<div style={{ width: '13px' }} />
</EventIconCell>
<Divider />
<EventMessageCell>Data</EventMessageCell>
<Divider />
<EventTimestampCell>Time</EventTimestampCell>
</HeadingRow>
<AutoSize ref={autoSizeRef}>
<Scrollable style={{ height }} ref={parentRef}>
<List
style={{
height: `${virtualizer.getTotalSize()}px`,
}}
<>
<div className='w-full flex-1 overflow-hidden border border-solid border-[--hl-sm] select-none overflow-y-auto max-h-96'>
<Table
selectionMode='single'
selectedKeys={selectionId ? [selectionId] : []}
selectionBehavior='replace'
onSelectionChange={keys => {
if (keys !== 'all') {
const key = keys.values().next().value;

const event = events.find(e => e._id === key);

if (event) {
onSelect(event);
}
}
}}
aria-label='Modified objects'
className="border-separate border-spacing-0 w-full"
>
<TableHeader className='sticky top-0 z-10 backdrop-blur backdrop-filter bg-[--hl-xs]'>
<Column isRowHeader className="p-3 text-left text-xs font-semibold focus:outline-none">
<span />
</Column>
<Column className="p-3 text-left text-xs font-semibold focus:outline-none">
Data
</Column>
<Column className="p-3 text-left text-xs font-semibold focus:outline-none">
Time
</Column>
</TableHeader>
<TableBody
style={{ height: virtualizer.getTotalSize() }}
ref={parentRef}
className="divide divide-[--hl-sm] divide-solid"
items={virtualizer.getVirtualItems()}
>
{virtualizer.getVirtualItems().map(item => {
{item => {
const event = events[item.index];

return (
<Row
key={item.key}
onClick={() => onSelect(event)}
isActive={event._id === selectionId}
style={{
height: `${item.size}px`,
transform: `translateY(${item.start}px)`,
}}
>
<EventIconCell>
<Row className="group focus:outline-none focus-within:bg-[--hl-sm] transition-colors">
<Cell className="p-2 whitespace-nowrap text-sm font-medium border-b border-solid border-[--hl-sm] group-last-of-type:border-none focus:outline-none">
<SvgIcon icon={getIcon(event)} />
</EventIconCell>
<Divider />

<EventMessageCell>{getMessage(event)}</EventMessageCell>
<Divider />
<EventTimestampCell>
</Cell>
<Cell className="whitespace-nowrap text-sm font-medium border-b border-solid border-[--hl-sm] group-last-of-type:border-none focus:outline-none">
{getMessage(event)}
</Cell>
<Cell className="whitespace-nowrap text-sm font-medium border-b border-solid border-[--hl-sm] group-last-of-type:border-none focus:outline-none">
<Timestamp time={event.timestamp} />
</EventTimestampCell>
</Cell>
</Row>
);
})}
</List>
</Scrollable>
</AutoSize>
</EventLog>
}}
</TableBody>
</Table>
</div>
</>
);
};
10 changes: 4 additions & 6 deletions packages/insomnia/src/ui/components/websockets/event-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import React, { FC, useCallback } from 'react';
import { useParams, useRouteLoaderData } from 'react-router-dom';
import styled from 'styled-components';

import { PREVIEW_MODE_FRIENDLY, PREVIEW_MODE_RAW, PREVIEW_MODE_SOURCE, PreviewMode } from '../../../common/constants';
import { PREVIEW_MODE_FRIENDLY, PREVIEW_MODE_RAW, PREVIEW_MODE_SOURCE } from '../../../common/constants';
import { CurlEvent, CurlMessageEvent } from '../../../main/network/curl';
import { WebSocketEvent, WebSocketMessageEvent } from '../../../main/network/websocket';
import { requestMeta } from '../../../models';
import { useRequestMetaPatcher } from '../../hooks/use-request';
import { RequestLoaderData } from '../../routes/request';
import { CodeEditor } from '../codemirror/code-editor';
import { showError } from '../modals';
Expand Down Expand Up @@ -78,9 +78,7 @@ export const MessageEventView: FC<Props<CurlMessageEvent | WebSocketMessageEvent
window.clipboard.writeText(raw);
}, [raw]);

const setPreviewMode = async (previewMode: PreviewMode) => {
return requestMeta.updateOrCreateByParentId(requestId, { previewMode });
};
const patchRequestMeta = useRequestMetaPatcher();

let pretty = raw;
try {
Expand All @@ -98,7 +96,7 @@ export const MessageEventView: FC<Props<CurlMessageEvent | WebSocketMessageEvent
download={handleDownloadResponseBody}
copyToClipboard={handleCopyResponseToClipboard}
previewMode={previewMode}
setPreviewMode={setPreviewMode}
setPreviewMode={previewMode => patchRequestMeta(requestId, { previewMode })}
/>
</PreviewPaneButtons>
<PreviewPaneContents>
Expand Down
Loading