diff --git a/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSMessagesList/StyledWrapper.js b/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSMessagesList/StyledWrapper.js index 18e4caf24..a03c31dec 100644 --- a/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSMessagesList/StyledWrapper.js +++ b/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSMessagesList/StyledWrapper.js @@ -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}; } diff --git a/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSMessagesList/index.js b/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSMessagesList/index.js index 2268ea3b2..1c429c565 100644 --- a/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSMessagesList/index.js +++ b/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSMessagesList/index.js @@ -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 ( +
+
{ + setIsOpen(!isOpen); + }} + > +
+ + {isIncoming ? : } + + {!isOpen ? {parsedContent.sliced} : null} + {isOpen ? {dataType} : null} +
+
+ {message.timestamp && ( + {new Date(message.timestamp).toISOString()} + )} + + {isOpen ? ( + + ) : ( + + )} + +
+
+ {isOpen && ( +
+ +
+ )} +
+ ); +}; + const WSMessagesList = ({ messages = [] }) => { if (!messages.length) { return
No messages yet.
; @@ -11,39 +116,9 @@ const WSMessagesList = ({ messages = [] }) => { return ( - {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 ( -
-
- - {isIncoming ? : } - {isIncoming ? 'RCVD' : 'SENT'} - - {msg.timestamp && ( - {new Date(msg.timestamp).toLocaleTimeString()} - )} -
-
{content}
-
- ); + {messages.map((msg, idx,src) => { + const isLast = idx === src.length-1 + return ; })}
);