feat: Persist response body scroll position across tabs (#3902)

This commit is contained in:
Coel Aspey
2025-08-25 12:51:34 +01:00
committed by GitHub
parent 54c41c861e
commit 325d03b92f
4 changed files with 84 additions and 33 deletions

View File

@@ -186,6 +186,8 @@ export default class CodeEditor extends React.Component {
if (editor) {
editor.setOption('lint', this.props.mode && editor.getValue().trim().length > 0 ? this.lintOptions : false);
editor.on('change', this._onEdit);
editor.on('scroll', this.onScroll);
editor.scrollTo(null, this.props.initialScroll);
this.addOverlay();
const getAllVariablesHandler = () => getAllVariables(this.props.collection, this.props.item);
@@ -230,12 +232,18 @@ export default class CodeEditor extends React.Component {
if (this.props.theme !== prevProps.theme && this.editor) {
this.editor.setOption('theme', this.props.theme === 'dark' ? 'monokai' : 'default');
}
if (this.props.initialScroll !== prevProps.initialScroll) {
this.editor.scrollTo(null, this.props.initialScroll);
}
this.ignoreChangeEvent = false;
}
componentWillUnmount() {
if (this.editor) {
this.editor.off('change', this._onEdit);
this.editor.off('scroll', this.onScroll);
this.editor = null;
}
@@ -271,6 +279,8 @@ export default class CodeEditor extends React.Component {
this.editor.setOption('mode', 'brunovariables');
};
onScroll = (event) => this.props.onScroll?.(event);
_onEdit = () => {
if (!this.ignoreChangeEvent && this.editor) {
this.editor.setOption('lint', this.editor.getValue().trim().length > 0 ? this.lintOptions : false);

View File

@@ -1,7 +1,9 @@
import React, { useState, useEffect } from 'react';
import CodeEditor from 'components/CodeEditor/index';
import { get } from 'lodash';
import find from 'lodash/find';
import { useDispatch, useSelector } from 'react-redux';
import { updateResponsePaneScrollPosition } from 'providers/ReduxStore/slices/tabs';
import { sendRequest } from 'providers/ReduxStore/slices/collections/actions';
import { Document, Page } from 'react-pdf';
import 'pdfjs-dist/build/pdf.worker';
@@ -51,6 +53,10 @@ const QueryResultPreview = ({
displayedTheme
}) => {
const preferences = useSelector((state) => state.app.preferences);
const tabs = useSelector((state) => state.tabs.tabs);
const activeTabUid = useSelector((state) => state.tabs.activeTabUid);
const focusedTab = find(tabs, (t) => t.uid === activeTabUid);
const dispatch = useDispatch();
const [numPages, setNumPages] = useState(null);
@@ -66,9 +72,19 @@ const QueryResultPreview = ({
if (disableRunEventListener) {
return;
}
dispatch(sendRequest(item, collection.uid));
};
const onScroll = (event) => {
dispatch(
updateResponsePaneScrollPosition({
uid: focusedTab.uid,
scrollY: event.doc.scrollTop
})
);
};
switch (previewTab?.mode) {
case 'preview-web': {
const webViewSrc = data.replace('<head>', `<head><base href="${item.requestSent?.url || ''}">`);
@@ -111,8 +127,10 @@ const QueryResultPreview = ({
fontSize={get(preferences, 'font.codeFontSize')}
theme={displayedTheme}
onRun={onRun}
onScroll={onScroll}
value={formattedData}
mode={mode}
initialScroll={focusedTab.responsePaneScrollPosition || 0}
readOnly
/>
);