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 3709aee51..827dfc55c 100644
--- a/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSMessagesList/StyledWrapper.js
+++ b/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSMessagesList/StyledWrapper.js
@@ -3,8 +3,13 @@ import styled from 'styled-components';
const StyledWrapper = styled.div`
overflow-y: auto;
+ .ws-message.new {
+ color: white;
+ background-color: ${({theme}) => theme.table.striped};
+ }
+
.ws-message:not(:last-child) {
- border-bottom: 1px solid ${(props) => props.theme.table.border};
+ border-bottom: 1px solid ${({theme}) => theme.table.border};
}
.ws-message:not(:last-child).open {
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 912fc26e6..a18acff23 100644
--- a/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSMessagesList/index.js
+++ b/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSMessagesList/index.js
@@ -7,7 +7,8 @@ import { useTheme } from 'providers/Theme';
import { useState } from 'react';
import { useSelector } from 'react-redux';
import _ from 'lodash';
-import { forwardRef } from 'react';
+import { useRef } from 'react';
+import { useEffect } from 'react';
const getContentMeta = (content) => {
if (typeof content === 'object') {
@@ -60,27 +61,42 @@ const TypeIcon = ({type})=>{
}[type]
}
-const WSMessageItem = ({ message, isLast }) => {
+const WSMessageItem = ({ message, inFocus }) => {
const [isOpen, setIsOpen] = useState(false);
const preferences = useSelector((state) => state.app.preferences);
-
const { displayedTheme } = useTheme();
+ const [isNew, setIsNew] = useState(false)
+ const notified = useRef(false)
const isIncoming = message.type === 'incoming';
const isInfo = message.type === 'info';
let parsedContent = parseContent(message.message);
const dataType = getDataTypeText(parsedContent.type);
+ useEffect(()=>{
+ if(notified.current === true) return
+ const dateDiff = Date.now() - new Date(message.timestamp).getTime()
+ if(dateDiff < 1000 * 10){
+ setIsNew(true)
+ setTimeout(()=>{
+ notified.current = true
+ setIsNew(false)
+ },2500)
+ }
+ }, [message])
+
+
return (
{
if (!node) return;
- if (isLast) node.scrollIntoView();
+ if (inFocus) node.scrollIntoView()
}}
- className={classnames('ws-message flex flex-col py-2', {
+ className={classnames('ws-message flex flex-col p-2', {
'ws-incoming': isIncoming,
'ws-outgoing': !isIncoming,
- 'open': isOpen
+ 'open': isOpen,
+ 'new': isNew
})}
>
{
if (!messages.length) {
return
No messages yet.
;
}
-
+ const ordered = order === -1 ? messages : messages.slice().reverse()
return (
- {messages
- .toSorted((x, y) => {
- let a = order == -1 ? x : y
- let b = order == -1 ? y : x
- return (new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
- })
+ {ordered
.map((msg, idx, src) => {
- const isLast = src.length - 1 === idx;
- return ;
+ const inFocus = order === -1 ? src.length - 1 === idx : idx === 0;
+ return ;
})}
);
diff --git a/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSResponseSortOrder/index.js b/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSResponseSortOrder/index.js
index 9422da9ab..f91e7359c 100644
--- a/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSResponseSortOrder/index.js
+++ b/packages/bruno-app/src/components/ResponsePane/WsResponsePane/WSResponseSortOrder/index.js
@@ -7,7 +7,7 @@ import { wsUpdateResponseSortOrder } from 'providers/ReduxStore/slices/collectio
const WSResponseSortOrder = ({ collection, item }) => {
const dispatch = useDispatch();
- const order = item.response?.initiatedWsResponse?.sortOrder ?? -1
+ const order = item.response?.sortOrder ?? -1
const toggleSortOrder = ()=>{
dispatch(
@@ -20,10 +20,10 @@ const WSResponseSortOrder = ({ collection, item }) => {
return (
-
);
diff --git a/packages/bruno-app/src/components/ResponsePane/WsResponsePane/index.js b/packages/bruno-app/src/components/ResponsePane/WsResponsePane/index.js
index 931ab973c..d8ef1490a 100644
--- a/packages/bruno-app/src/components/ResponsePane/WsResponsePane/index.js
+++ b/packages/bruno-app/src/components/ResponsePane/WsResponsePane/index.js
@@ -22,7 +22,7 @@ const WSResult = ({ response }) => {
{response.error}
) : (
-
+
);
};
diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
index 410ed97bf..fd27fdadd 100644
--- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
+++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js
@@ -2771,6 +2771,7 @@ export const collectionsSlice = createSlice({
item.requestSent = eventData;
item.requestSent.timestamp = Date.now();
item.response = {
+ ...initiatedWsResponse,
initiatedWsResponse,
statusText: 'CONNECTING'
};
@@ -2891,7 +2892,7 @@ export const collectionsSlice = createSlice({
if (collection) {
const item = findItemInCollection(collection, action.payload.itemUid);
if (item) {
- item.response.initiatedWsResponse.sortOrder = item.response?.initiatedWsResponse?.sortOrder ? -item.response.initiatedWsResponse.sortOrder : -1;
+ item.response.sortOrder = item.response.sortOrder ? -item.response.sortOrder : -1;
}
}
}
diff --git a/packages/bruno-requests/src/ws/ws-client.js b/packages/bruno-requests/src/ws/ws-client.js
index 497ddc2e9..c645332f6 100644
--- a/packages/bruno-requests/src/ws/ws-client.js
+++ b/packages/bruno-requests/src/ws/ws-client.js
@@ -94,10 +94,7 @@ class WsClient {
});
// Set up event handlers
- this.#setupWsEventHandlers(wsConnection, requestId, collectionUid, {
- url: parsedUrl.fullUrl,
- headers
- });
+ this.#setupWsEventHandlers(wsConnection, requestId, collectionUid, {keepAlive,keepAliveInterval});
// Store the connection
this.#addConnection(requestId, wsConnection);
@@ -105,18 +102,6 @@ class WsClient {
// Emit connecting event
this.eventCallback('ws:connecting', requestId, collectionUid);
- wsConnection.addEventListener('open', () => {
- this.#flushQueue(requestId, collectionUid);
-
- if (keepAlive) {
- const handle = setInterval(() => {
- wsConnection.isAlive = false;
- wsConnection.ping();
- }, keepAliveInterval);
- this.connectionKeepAlive.set(requestId, handle);
- }
- });
-
return wsConnection;
} catch (error) {
console.error('Error creating WebSocket connection:', error);
@@ -259,10 +244,25 @@ class WsClient {
* @param {WebSocket} ws - The WebSocket instance
* @param {string} requestId - The request ID
* @param {string} collectionUid - The collection UID
+ * @param {object} options
+ * @param {boolean} options.keepAlive - keep the connection alive
+ * @param {number} options.keepAliveInterval - What the interval for keeping interval
* @private
*/
- #setupWsEventHandlers(ws, requestId, collectionUid) {
+ #setupWsEventHandlers(ws, requestId, collectionUid, options) {
ws.on('open', () => {
+ this.#flushQueue(requestId, collectionUid);
+
+ if(options.keepAlive){
+ const handle = setInterval(() => {
+ console.log("pinging to keep alive")
+ ws.isAlive = false;
+ ws.ping();
+ }, options.keepAliveInterval);
+
+ this.connectionKeepAlive.set(requestId, handle);
+ }
+
this.eventCallback('ws:open', requestId, collectionUid, {
timestamp: Date.now(),
url: ws.url