fix: restyle web ui

This commit is contained in:
Siddharth Gelera
2025-09-16 15:30:59 +05:30
parent 95d801ac07
commit 8eefe7c68b
2 changed files with 110 additions and 35 deletions

View File

@@ -4,7 +4,7 @@ const StyledWrapper = styled.div`
overflow-y: auto;
.ws-incoming {
background: ${(props) => props.theme.table.striped};
background: ${(props) => props.theme.bg};
border-color: ${(props) => props.theme.table.border};
}

View File

@@ -1,9 +1,114 @@
import React from 'react';
import classnames from 'classnames';
import StyledWrapper from './StyledWrapper';
import { IconArrowDown, IconArrowUp } from '@tabler/icons';
import { IconChevronUp, IconChevronDown, IconArrowUpRight, IconArrowDownLeft } from '@tabler/icons';
import CodeEditor from 'components/CodeEditor/index';
import { useTheme } from 'providers/Theme';
import { useState } from 'react';
import { useSelector } from 'react-redux';
// Example message structure: { direction: 'incoming' | 'outgoing', timestamp, data }
const parseContent = (content) => {
if (typeof content === 'string') {
let isJSON = false;
let resultContent = content;
let trimmedContent = content;
try {
JSON.parse(content);
isJSON = true;
resultContent = JSON.stringify(resultContent, null, 2);
trimmedContent = JSON.stringify(resultContent, null, 0);
} catch (err) {
// digest error
}
return {
type: isJSON ? 'application/json' : 'text/plain',
content: resultContent,
sliced: trimmedContent.slice(0, 30)
};
}
if (typeof content === 'object') {
return {
type: 'application/json',
content: JSON.stringify(content, null, 2),
sliced: JSON.stringify(content, null, 0).slice(0, 30)
};
}
};
const getDataTypeText = (type) => {
const textMap = {
'text/plain': 'RAW',
'application/json': 'JSON'
};
return textMap[type] ?? 'RAW';
};
const WSMessageItem = ({ message, defaultOpen }) => {
const [isOpen, setIsOpen] = useState(defaultOpen ?? false);
const preferences = useSelector((state) => state.app.preferences);
const { displayedTheme } = useTheme();
const isIncoming = message.direction === 'incoming';
let parsedContent = parseContent(message.message);
const dataType = getDataTypeText(parsedContent.type);
return (
<div
className={classnames('ws-message flex flex-col rounded border p-2', {
'ws-incoming': isIncoming,
'ws-outgoing': !isIncoming
})}
>
<div
className="flex items-center justify-between"
onClick={(e) => {
setIsOpen(!isOpen);
}}
>
<div className="flex">
<span
className={classnames(
'font-semibold flex items-center gap-1',
isIncoming ? 'text-blue-700' : 'text-green-700'
)}
>
{isIncoming ? <IconArrowDownLeft size={18} /> : <IconArrowUpRight size={18} />}
</span>
{!isOpen ? <span className="ml-3">{parsedContent.sliced}</span> : null}
{isOpen ? <span className="ml-3 text-xs font-bold">{dataType}</span> : null}
</div>
<div className="flex gap-2">
{message.timestamp && (
<span className="text-xs text-gray-400">{new Date(message.timestamp).toISOString()}</span>
)}
<span className="text-gray-600">
{isOpen ? (
<IconChevronDown size={16} strokeWidth={1.5} className="text-zinc-700 dark:text-zinc-300" />
) : (
<IconChevronUp size={16} strokeWidth={1.5} className="text-zinc-700 dark:text-zinc-300" />
)}
</span>
</div>
</div>
{isOpen && (
<div className="mt-2 h-[300px]">
<CodeEditor
mode={parsedContent.type}
theme={displayedTheme}
font={preferences.codeFont || 'default'}
value={parsedContent.content}
/>
</div>
)}
</div>
);
};
const WSMessagesList = ({ messages = [] }) => {
if (!messages.length) {
return <div className="p-4 text-gray-500">No messages yet.</div>;
@@ -11,39 +116,9 @@ const WSMessagesList = ({ messages = [] }) => {
return (
<StyledWrapper className="ws-messages-list flex flex-col gap-2 mt-4">
{messages.map((msg, idx) => {
const isIncoming = msg.direction === 'incoming';
let content;
try {
content = typeof msg.message === 'string' ? msg.message : JSON.stringify(msg.message, null, 2);
} catch {
content = String(msg.message);
}
return (
<div
key={idx}
className={classnames('ws-message flex flex-col rounded border p-2', {
'ws-incoming': isIncoming,
'ws-outgoing': !isIncoming
})}
>
<div className="flex items-center justify-between mb-1">
<span
className={classnames(
'font-semibold flex items-center gap-1',
isIncoming ? 'text-blue-700' : 'text-green-700'
)}
>
{isIncoming ? <IconArrowDown size={18} /> : <IconArrowUp size={18} />}
{isIncoming ? 'RCVD' : 'SENT'}
</span>
{msg.timestamp && (
<span className="text-xs text-gray-400">{new Date(msg.timestamp).toLocaleTimeString()}</span>
)}
</div>
<pre className="whitespace-pre-wrap break-all text-sm">{content}</pre>
</div>
);
{messages.map((msg, idx,src) => {
const isLast = idx === src.length-1
return <WSMessageItem id={idx} message={msg} defaultOpen={isLast} />;
})}
</StyledWrapper>
);