diff --git a/packages/bruno-app/src/components/ResponsePane/index.js b/packages/bruno-app/src/components/ResponsePane/index.js index 6cdd5e9c2..7c82ae69e 100644 --- a/packages/bruno-app/src/components/ResponsePane/index.js +++ b/packages/bruno-app/src/components/ResponsePane/index.js @@ -1,8 +1,7 @@ -import React, { useState, useEffect, useMemo, useRef } from 'react'; +import React, { useState, useEffect, useMemo, useRef, useCallback } from 'react'; import find from 'lodash/find'; -import classnames from 'classnames'; import { useDispatch, useSelector } from 'react-redux'; -import { updateResponsePaneTab } from 'providers/ReduxStore/slices/tabs'; +import { updateResponsePaneTab, updateResponseFormat, updateResponseViewTab } from 'providers/ReduxStore/slices/tabs'; import QueryResult from './QueryResult'; import Overlay from './Overlay'; import Placeholder from './Placeholder'; @@ -35,22 +34,44 @@ const ResponsePane = ({ item, collection }) => { const activeTabUid = useSelector((state) => state.tabs.activeTabUid); const isLoading = ['queued', 'sending'].includes(item.requestState); const [showScriptErrorCard, setShowScriptErrorCard] = useState(false); - const [selectedFormat, setSelectedFormat] = useState('raw'); - const [selectedTab, setSelectedTab] = useState('editor'); const rightContentRef = useRef(null); const response = item.response || {}; + // Get the focused tab for reading persisted format/view state + const focusedTab = find(tabs, (t) => t.uid === activeTabUid); + // Initialize format and tab only once when data loads. const { initialFormat, initialTab } = useInitialResponseFormat(response?.dataBuffer, response?.headers); const previewFormatOptions = useResponsePreviewFormatOptions(response?.dataBuffer, response?.headers); + const persistedFormat = focusedTab?.responseFormat; + const persistedViewTab = focusedTab?.responseViewTab; + + // Use persisted values from Redux, falling back to initial values or defaults + const selectedFormat = persistedFormat ?? initialFormat ?? 'raw'; + const selectedViewTab = persistedViewTab ?? initialTab ?? 'editor'; + useEffect(() => { - if (initialFormat !== null && initialTab !== null) { - setSelectedFormat(initialFormat); - setSelectedTab(initialTab); + if (!focusedTab || initialFormat === null || initialTab === null) { + return; } - }, [initialFormat, initialTab]); + if (persistedFormat === null) { + dispatch(updateResponseFormat({ uid: item.uid, responseFormat: initialFormat })); + } + if (persistedViewTab === null) { + dispatch(updateResponseViewTab({ uid: item.uid, responseViewTab: initialTab })); + } + }, [initialFormat, initialTab, persistedFormat, persistedViewTab, focusedTab, item.uid, dispatch]); + + const handleFormatChange = useCallback((newFormat) => { + dispatch(updateResponseFormat({ uid: item.uid, responseFormat: newFormat })); + }, [dispatch, item.uid]); + + const handleViewTabToggle = useCallback(() => { + const newViewTab = selectedViewTab === 'editor' ? 'preview' : 'editor'; + dispatch(updateResponseViewTab({ uid: item.uid, responseViewTab: newViewTab })); + }, [dispatch, item.uid, selectedViewTab]); const requestTimeline = ([...(collection.timeline || [])]).filter((obj) => { if (obj.itemUid === item.uid) return true; @@ -138,7 +159,7 @@ const ResponsePane = ({ item, collection }) => { error={response.error} key={item.filename} selectedFormat={selectedFormat} - selectedTab={selectedTab} + selectedTab={selectedViewTab} /> ); } @@ -193,7 +214,6 @@ const ResponsePane = ({ item, collection }) => { return
Something went wrong
; } - const focusedTab = find(tabs, (t) => t.uid === activeTabUid); if (!focusedTab || !focusedTab.uid || !focusedTab.responsePaneTab) { return
An error occurred!
; } @@ -211,13 +231,9 @@ const ResponsePane = ({ item, collection }) => { { - setSelectedFormat(newFormat); - }} - onPreviewTabSelect={() => { - setSelectedTab((prev) => prev === 'editor' ? 'preview' : 'editor'); - }} - selectedTab={selectedTab} + onFormatChange={handleFormatChange} + onPreviewTabSelect={handleViewTabToggle} + selectedTab={selectedViewTab} /> ) : null} diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/tabs.js b/packages/bruno-app/src/providers/ReduxStore/slices/tabs.js index fde898715..2a08f15f2 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/tabs.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/tabs.js @@ -59,6 +59,8 @@ export const tabsSlice = createSlice({ requestPaneWidth: null, requestPaneTab: requestPaneTab || defaultRequestPaneTab, responsePaneTab: 'response', + responseFormat: null, + responseViewTab: null, type: type || 'request', preview: preview !== undefined ? preview @@ -79,6 +81,8 @@ export const tabsSlice = createSlice({ requestPaneTab: requestPaneTab || defaultRequestPaneTab, responsePaneTab: 'response', responsePaneScrollPosition: null, + responseFormat: null, + responseViewTab: null, type: type || 'request', ...(uid ? { folderUid: uid } : {}), preview: preview !== undefined @@ -147,6 +151,20 @@ export const tabsSlice = createSlice({ tab.responsePaneScrollPosition = action.payload.scrollY; } }, + updateResponseFormat: (state, action) => { + const tab = find(state.tabs, (t) => t.uid === action.payload.uid); + + if (tab) { + tab.responseFormat = action.payload.responseFormat; + } + }, + updateResponseViewTab: (state, action) => { + const tab = find(state.tabs, (t) => t.uid === action.payload.uid); + + if (tab) { + tab.responseViewTab = action.payload.responseViewTab; + } + }, closeTabs: (state, action) => { const activeTab = find(state.tabs, (t) => t.uid === state.activeTabUid); const tabUids = action.payload.tabUids || []; @@ -231,6 +249,8 @@ export const { updateRequestPaneTab, updateResponsePaneTab, updateResponsePaneScrollPosition, + updateResponseFormat, + updateResponseViewTab, closeTabs, closeAllCollectionTabs, makeTabPermanent,