feat: persist scroll across tabs (#7695)

* fix: persist scroll

* fix: persist scroll

* chore: style

* fix: remove persisted variabled from localstorage on boot

* fix: persist scroll in request tabs

* fix: persist scroll in folder tabs

* fix: hooks for container and editor scrolls

* fix: persist scroll position in response tabs

* fix: persist scroll for different request bodies

* fix: persist scroll for collection tabs

* fix: test cases

* test: scroll persists tests

* tests: resolved coderabbit comments for tests

* tests: resolved coderabbit comments for tests

* fix: remove only

* fix: test cases

* fix: flaky create collection path as name

* move scrollbar tests

* test cases

* test cases

* test cases

* test cases

* test cases

* fix: moved redundant code to common useTrackScroll function

* chore: spaces

* fix: move usetrackscroll to hook

* chore: cleanup un-needed setTimeout

* fix: linting issues

* chore: example fix

* fix: test cases

* fix: test cases

* fix: flaky scroll tests cases

* chore: revert prop name change

* chore: blank commit

* chore: blank commit

---------

Co-authored-by: shubh-bruno <shubh-bruno@shubh-bruno.local>
Co-authored-by: Sid <siddharth@usebruno.com>
This commit is contained in:
shubh-bruno
2026-04-29 18:19:24 +05:30
committed by GitHub
parent 13a9f9b8ef
commit 0adf7cd90a
50 changed files with 1598 additions and 197 deletions

View File

@@ -9,6 +9,7 @@ import { updateScriptPaneTab } from 'providers/ReduxStore/slices/tabs';
import { useTheme } from 'providers/Theme';
import { Tabs, TabsList, TabsTrigger, TabsContent } from 'components/Tabs';
import StatusDot from 'components/StatusDot';
import { usePersistedState } from 'hooks/usePersistedState';
const Script = ({ item, collection }) => {
const dispatch = useDispatch();
@@ -33,14 +34,21 @@ const Script = ({ item, collection }) => {
const { displayedTheme } = useTheme();
const preferences = useSelector((state) => state.app.preferences);
// Refresh CodeMirror when tab becomes visible
const [preReqScroll, setPreReqScroll] = usePersistedState({ key: `request-pre-req-scroll-${item.uid}`, default: 0 });
const [postResScroll, setPostResScroll] = usePersistedState({ key: `request-post-res-scroll-${item.uid}`, default: 0 });
// Refresh CodeMirror when tab becomes visible and restore scroll position.
// CodeMirror's scrollTo() is silently ignored when the editor is inside a display:none container
// (TabsContent hides inactive tabs via display:none). So the scroll set during componentDidMount
// is lost for the hidden editor. After refresh() recalculates layout, we re-apply scrollTo().
useEffect(() => {
// Small delay to ensure DOM is updated
const timer = setTimeout(() => {
if (activeTab === 'pre-request' && preRequestEditorRef.current?.editor) {
preRequestEditorRef.current.editor.refresh();
preRequestEditorRef.current.editor.scrollTo(null, preReqScroll);
} else if (activeTab === 'post-response' && postResponseEditorRef.current?.editor) {
postResponseEditorRef.current.editor.refresh();
postResponseEditorRef.current.editor.scrollTo(null, postResScroll);
}
}, 0);
@@ -108,6 +116,8 @@ const Script = ({ item, collection }) => {
onRun={onRun}
onSave={onSave}
showHintsFor={['req', 'bru']}
initialScroll={preReqScroll}
onScroll={setPreReqScroll}
/>
</TabsContent>
@@ -124,6 +134,8 @@ const Script = ({ item, collection }) => {
onRun={onRun}
onSave={onSave}
showHintsFor={['req', 'res', 'bru']}
initialScroll={postResScroll}
onScroll={setPostResScroll}
/>
</TabsContent>
</Tabs>