mirror of
https://github.com/usebruno/bruno.git
synced 2026-07-02 08:58:32 +00:00
feat: enhance ResponsePane with persisted response format and view tab state management (#6475)
- Added Redux state management for response format and view tab in ResponsePane. - Implemented useCallback hooks for handling format changes and view tab toggling. - Updated component to utilize persisted values from Redux, improving user experience by maintaining state across sessions.
This commit is contained in:
@@ -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 <div>Something went wrong</div>;
|
||||
}
|
||||
|
||||
const focusedTab = find(tabs, (t) => t.uid === activeTabUid);
|
||||
if (!focusedTab || !focusedTab.uid || !focusedTab.responsePaneTab) {
|
||||
return <div className="pb-4 px-4">An error occurred!</div>;
|
||||
}
|
||||
@@ -211,13 +231,9 @@ const ResponsePane = ({ item, collection }) => {
|
||||
<QueryResultTypeSelector
|
||||
formatOptions={previewFormatOptions}
|
||||
formatValue={selectedFormat}
|
||||
onFormatChange={(newFormat) => {
|
||||
setSelectedFormat(newFormat);
|
||||
}}
|
||||
onPreviewTabSelect={() => {
|
||||
setSelectedTab((prev) => prev === 'editor' ? 'preview' : 'editor');
|
||||
}}
|
||||
selectedTab={selectedTab}
|
||||
onFormatChange={handleFormatChange}
|
||||
onPreviewTabSelect={handleViewTabToggle}
|
||||
selectedTab={selectedViewTab}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user