From 3c3e8b757f304bcd18d4121437e650dda7139dc1 Mon Sep 17 00:00:00 2001 From: Neeraj Rithaliya Date: Sun, 12 Jul 2026 13:04:22 +0530 Subject: [PATCH 1/3] feat: save unsaved progress in session --- .../App/ConfirmAppClose/SaveRequestsModal.js | 21 ++- .../src/providers/App/useIpcEvents.js | 6 + .../ReduxStore/slices/collections/actions.js | 19 ++- .../ReduxStore/slices/collections/index.js | 81 ++++++++- .../ReduxStore/slices/global-environments.js | 26 +++ .../ReduxStore/utils/draftSession.js | 157 ++++++++++++++++++ 6 files changed, 298 insertions(+), 12 deletions(-) create mode 100644 packages/bruno-app/src/providers/ReduxStore/utils/draftSession.js diff --git a/packages/bruno-app/src/providers/App/ConfirmAppClose/SaveRequestsModal.js b/packages/bruno-app/src/providers/App/ConfirmAppClose/SaveRequestsModal.js index 78f2a26505c..9dd4a5f063c 100644 --- a/packages/bruno-app/src/providers/App/ConfirmAppClose/SaveRequestsModal.js +++ b/packages/bruno-app/src/providers/App/ConfirmAppClose/SaveRequestsModal.js @@ -1,10 +1,9 @@ import React, { useEffect, useMemo } from 'react'; import each from 'lodash/each'; import filter from 'lodash/filter'; -import groupBy from 'lodash/groupBy'; import { useSelector } from 'react-redux'; import { useDispatch } from 'react-redux'; -import { findCollectionByUid, flattenItems, isItemARequest, hasRequestChanges, findEnvironmentInCollection } from 'utils/collections'; +import { flattenItems, isItemARequest, hasRequestChanges, findEnvironmentInCollection } from 'utils/collections'; import { pluralizeWord } from 'utils/common'; import { getInvalidVariableNames } from 'utils/common/variables'; import { isEnvironmentValidationError } from 'utils/environments'; @@ -16,14 +15,16 @@ import { IconAlertTriangle } from '@tabler/icons'; import Modal from 'components/Modal'; import Button from 'ui/Button'; import toast from 'react-hot-toast'; +import { useStore } from 'react-redux'; +import { clearPersistedDraftSession, persistDraftSession } from 'providers/ReduxStore/utils/draftSession'; const SaveRequestsModal = ({ onClose, forceCloseTabs = false, tabUidsToClose = [] }) => { const MAX_UNSAVED_ITEMS_TO_SHOW = 5; const collections = useSelector((state) => state.collections.collections); - const tabs = useSelector((state) => state.tabs.tabs); const globalEnvironments = useSelector((state) => state.globalEnvironments.globalEnvironments); const globalEnvironmentDraft = useSelector((state) => state.globalEnvironments.globalEnvironmentDraft); const dispatch = useDispatch(); + const store = useStore(); const allDrafts = useMemo(() => { const requestDrafts = []; @@ -34,8 +35,8 @@ const SaveRequestsModal = ({ onClose, forceCloseTabs = false, tabUidsToClose = [ const relevantTabs = forceCloseTabs ? tabs.filter((t) => tabUidsToClose.includes(t.uid)) : tabs; const tabsByCollection = groupBy(relevantTabs, (t) => t.collectionUid); - Object.keys(tabsByCollection).forEach((collectionUid) => { - const collection = findCollectionByUid(collections, collectionUid); + collections.forEach((collection) => { + const collectionUid = collection?.uid; if (collection) { // Check for collection draft if (collection.draft) { @@ -108,8 +109,8 @@ const SaveRequestsModal = ({ onClose, forceCloseTabs = false, tabUidsToClose = [ } } - return [...collectionDrafts, ...folderDrafts, ...environmentDrafts, ...appDrafts, ...requestDrafts]; - }, [collections, tabs, globalEnvironments, globalEnvironmentDraft, forceCloseTabs, tabUidsToClose]); + return [...collectionDrafts, ...folderDrafts, ...environmentDrafts, ...requestDrafts]; + }, [collections, globalEnvironments, globalEnvironmentDraft]); const totalDraftsCount = allDrafts.length; @@ -121,6 +122,8 @@ const SaveRequestsModal = ({ onClose, forceCloseTabs = false, tabUidsToClose = [ } else { dispatch(completeQuitFlow()); } + clearPersistedDraftSession(); + return dispatch(completeQuitFlow()); } }, [totalDraftsCount, dispatch, forceCloseTabs, tabUidsToClose]); @@ -151,6 +154,8 @@ const SaveRequestsModal = ({ onClose, forceCloseTabs = false, tabUidsToClose = [ } else { dispatch(completeQuitFlow()); } + persistDraftSession(store.getState()); + dispatch(completeQuitFlow()); onClose(); }; @@ -229,6 +234,8 @@ const SaveRequestsModal = ({ onClose, forceCloseTabs = false, tabUidsToClose = [ } else { dispatch(completeQuitFlow()); } + clearPersistedDraftSession(); + dispatch(completeQuitFlow()); onClose(); } catch (error) { console.error('Error saving drafts:', error); diff --git a/packages/bruno-app/src/providers/App/useIpcEvents.js b/packages/bruno-app/src/providers/App/useIpcEvents.js index 81a5830c91d..737f444fb36 100644 --- a/packages/bruno-app/src/providers/App/useIpcEvents.js +++ b/packages/bruno-app/src/providers/App/useIpcEvents.js @@ -48,6 +48,8 @@ import { isElectron } from 'utils/common/platform'; import { globalEnvironmentsUpdateEvent, updateGlobalEnvironments, _clearScriptGlobalEnvBaseline } from 'providers/ReduxStore/slices/global-environments'; import { collectionAddOauth2CredentialsByUrl, collectionClearOauth2CredentialsByCredentialsId, updateCollectionLoadingState, collectionLoadedFromTree } from 'providers/ReduxStore/slices/collections/index'; import { migrationProgressEvent } from 'providers/ReduxStore/slices/collection-migration'; +import { globalEnvironmentsUpdateEvent, restoreGlobalEnvironmentDraftFromSession, updateGlobalEnvironments } from 'providers/ReduxStore/slices/global-environments'; +import { collectionAddOauth2CredentialsByUrl, collectionClearOauth2CredentialsByCredentialsId, updateCollectionLoadingState } from 'providers/ReduxStore/slices/collections/index'; import { addLog } from 'providers/ReduxStore/slices/logs'; import { loadNotifications } from 'providers/ReduxStore/slices/notifications'; import { updateSystemResources } from 'providers/ReduxStore/slices/performance'; @@ -174,6 +176,7 @@ const useIpcEvents = () => { workspacePath: workspace.pathname }).then((result) => { dispatch(updateGlobalEnvironments(result)); + dispatch(restoreGlobalEnvironmentDraftFromSession()); }).catch((error) => { console.error('Error refreshing global environments:', error); }); @@ -192,6 +195,7 @@ const useIpcEvents = () => { workspacePath: workspace.pathname }).then((result) => { dispatch(updateGlobalEnvironments(result)); + dispatch(restoreGlobalEnvironmentDraftFromSession()); }).catch((error) => { console.error('Error refreshing global environments:', error); }); @@ -210,6 +214,7 @@ const useIpcEvents = () => { workspacePath: workspace.pathname }).then((result) => { dispatch(updateGlobalEnvironments(result)); + dispatch(restoreGlobalEnvironmentDraftFromSession()); }).catch((error) => { console.error('Error refreshing global environments:', error); }); @@ -346,6 +351,7 @@ const useIpcEvents = () => { const removeGlobalEnvironmentsUpdatesListener = ipcRenderer.on('main:load-global-environments', (val) => { dispatch(updateGlobalEnvironments(val)); + dispatch(restoreGlobalEnvironmentDraftFromSession()); }); const removeSnapshotHydrationListener = ipcRenderer.on('main:hydrate-app-with-ui-state-snapshot', (val) => { diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js index 69cad0c2565..72cf3708e7d 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js @@ -117,6 +117,7 @@ import { hydrateCollectionTabs, hydrateSnapshotLookups } from 'utils/snapshot'; +import { getPersistedCollectionDraftSession } from 'providers/ReduxStore/utils/draftSession'; // Display name for a cloned/pasted item: always " copy" (semantic). // Filename uniqueness is resolved silently by the electron main process @@ -2892,12 +2893,19 @@ export const openScratchCollectionEvent = (uid, pathname, brunoConfig) => (dispa brunoConfig }; + const persistedDraftSession = getPersistedCollectionDraftSession(pathname); + ipcRenderer .invoke('renderer:get-collection-security-config', pathname) .then((securityConfig) => { collectionSchema .validate(collection) - .then(() => dispatch(_createCollection({ ...collection, securityConfig }))) + .then(() => dispatch(_createCollection({ + ...collection, + securityConfig, + draft: persistedDraftSession?.collectionDraft || null, + persistedDraftSession + }))) .then(resolve) .catch(reject); }) @@ -2979,10 +2987,17 @@ export const openCollectionEvent = (uid, pathname, brunoConfig, options = {}) => brunoConfig: brunoConfig }; + const persistedDraftSession = getPersistedCollectionDraftSession(pathname); + ipcRenderer.invoke('renderer:get-collection-security-config', pathname).then((securityConfig) => { collectionSchema .validate(collection) - .then(() => dispatch(_createCollection({ ...collection, securityConfig }))) + .then(() => dispatch(_createCollection({ + ...collection, + securityConfig, + draft: persistedDraftSession?.collectionDraft || null, + persistedDraftSession + }))) .then(() => { const currentState = getState(); 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 8289658fe9c..04ee3dfa108 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -21,7 +21,7 @@ import { applyScriptEnvVars, getScriptModifiedKeys } from 'utils/environments'; import { getSubdirectoriesFromRoot } from 'utils/common/platform'; import toast from 'react-hot-toast'; import mime from 'mime-types'; -import path from 'utils/common/path'; +import path, { normalizePath } from 'utils/common/path'; import { getUniqueTagsFromItems } from 'utils/collections/index'; import { DEFAULT_HTTP_ITEM_SETTINGS, GRPC_SCRIPT_KEYS, SCRIPT_TYPES } from '@usebruno/common'; import * as exampleReducers from './exampleReducers'; @@ -194,6 +194,57 @@ const mergeRequestWithPreservedUids = (existingRequest, newRequest) => const mergeRootWithPreservedUids = (existingRoot, newRoot) => preserveUidsAtPaths(existingRoot, newRoot, ROOT_UID_PATHS); +const consumePersistedItemDraft = (collection, draftType, pathname) => { + if (!collection?.persistedDraftSession || !pathname) { + return null; + } + + const normalizedPath = normalizePath(pathname); + const draft = collection.persistedDraftSession?.[draftType]?.[normalizedPath]; + + if (draft) { + delete collection.persistedDraftSession[draftType][normalizedPath]; + } + + return draft || null; +}; + +const applyPersistedFolderDraft = (collection, folderItem, pathname) => { + if (!folderItem?.draft) { + const draft = consumePersistedItemDraft(collection, 'folderDrafts', pathname || folderItem?.pathname); + if (draft) { + folderItem.draft = draft; + } + } +}; + +const applyPersistedRequestDraft = (collection, requestItem, pathname) => { + if (!requestItem?.draft) { + const draft = consumePersistedItemDraft(collection, 'requestDrafts', pathname || requestItem?.pathname); + if (draft) { + requestItem.draft = draft; + } + } +}; + +const applyPersistedEnvironmentDraft = (collection, environment) => { + const persistedDraft = collection?.persistedDraftSession?.environmentsDraft; + if (collection?.environmentsDraft || !persistedDraft || !environment) { + return; + } + + const isMatch = (persistedDraft.environmentUid && persistedDraft.environmentUid === environment.uid) + || (persistedDraft.environmentName && persistedDraft.environmentName === environment.name); + + if (isMatch) { + collection.environmentsDraft = { + environmentUid: environment.uid, + variables: persistedDraft.variables + }; + delete collection.persistedDraftSession.environmentsDraft; + } +}; + const initialState = { collections: [], collectionSortOrder: 'default', @@ -3063,6 +3114,7 @@ export const collectionsSlice = createSlice({ if (file?.data?.meta?.seq) { folderItem.seq = file.data?.meta?.seq; } + applyPersistedFolderDraft(collection, folderItem, folderPath); } return; } @@ -3094,6 +3146,7 @@ export const collectionsSlice = createSlice({ // Update existing folder to be transient if the file is transient childItem.isTransient = true; } + applyPersistedFolderDraft(collection, childItem, currentPath); currentSubItems = childItem.items; } @@ -3119,8 +3172,9 @@ export const collectionsSlice = createSlice({ currentItem.size = file.size; currentItem.error = file.error; currentItem.isTransient = isTransientFile; + applyPersistedRequestDraft(collection, currentItem, file.meta.pathname); } else { - currentSubItems.push({ + const newItem = { uid: file.data.uid, name: file.data.name, type: file.data.type, @@ -3139,7 +3193,9 @@ export const collectionsSlice = createSlice({ size: file.size, error: file.error, isTransient: isTransientFile - }); + }; + applyPersistedRequestDraft(collection, newItem, file.meta.pathname); + currentSubItems.push(newItem); } } } @@ -3191,6 +3247,7 @@ export const collectionsSlice = createSlice({ // Update existing folder to be transient if the directory is transient childItem.isTransient = true; } + applyPersistedFolderDraft(collection, childItem, currentPath); currentSubItems = childItem.items; }); } @@ -3218,6 +3275,7 @@ export const collectionsSlice = createSlice({ folderItem.seq = file?.data?.meta?.seq; } folderItem.root = mergeRootWithPreservedUids(folderItem.root, file.data); + applyPersistedFolderDraft(collection, folderItem, folderPath); } return; } @@ -3281,6 +3339,8 @@ export const collectionsSlice = createSlice({ item.draft = null; } } + + applyPersistedRequestDraft(collection, item, file.meta.pathname); } } }, @@ -3324,9 +3384,24 @@ export const collectionsSlice = createSlice({ existingEnv.color = environment.color; existingEnv.externalSecrets = environment.externalSecrets; existingEnv.extends = environment.extends; + /* + Apply temporary (ephemeral) values only to variables that actually exist in the file. This prevents deleted temporaries from “popping back” after a save. If a variable is present in the file, we temporarily override the UI value while also remembering the on-disk value in persistedValue for future saves. + */ + prevEphemerals.forEach((ev) => { + const target = existingEnv.variables?.find((v) => v.name === ev.name); + if (target) { + if (target.value !== ev.value) { + if (target.persistedValue === undefined) target.persistedValue = target.value; + target.value = ev.value; + } + target.ephemeral = true; + } + }); + applyPersistedEnvironmentDraft(collection, existingEnv); } else { collection.environments.push(environment); collection.environments.sort((a, b) => a.name.localeCompare(b.name)); + applyPersistedEnvironmentDraft(collection, environment); const lastAction = collection.lastAction; if (lastAction && lastAction.type === 'ADD_ENVIRONMENT') { diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/global-environments.js b/packages/bruno-app/src/providers/ReduxStore/slices/global-environments.js index 58f93d062a8..7d7e11fa7e1 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/global-environments.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/global-environments.js @@ -5,6 +5,7 @@ import { getDataTypeFromValue, parseValueByDataType, resolveEnvironmentInheritan import { cloneDeep, isEqual } from 'lodash'; import { applyScriptEnvVars, getScriptModifiedKeys, writesCollidingSecrets, DUPLICATE_SECRET_NAMES_ERROR } from 'utils/environments'; import { getInvalidVariableNames, invalidVariableNamesError } from 'utils/common/variables'; +import { getPersistedDraftSession } from 'providers/ReduxStore/utils/draftSession'; const initialState = { globalEnvironments: [], @@ -418,4 +419,29 @@ export const updateGlobalEnvironmentColor = (environmentUid, color) => (dispatch }); }; +export const restoreGlobalEnvironmentDraftFromSession = () => (dispatch, getState) => { + const session = getPersistedDraftSession(); + const persistedDraft = session?.globalEnvironmentDraft; + + if (!persistedDraft) { + return; + } + + const state = getState(); + const globalEnvironments = state.globalEnvironments?.globalEnvironments || []; + const environment = globalEnvironments.find((env) => + env.uid === persistedDraft.environmentUid + || (persistedDraft.environmentName && env.name === persistedDraft.environmentName) + ); + + if (!environment) { + return; + } + + dispatch(setGlobalEnvironmentDraft({ + environmentUid: environment.uid, + variables: persistedDraft.variables + })); +}; + export default globalEnvironmentsSlice.reducer; diff --git a/packages/bruno-app/src/providers/ReduxStore/utils/draftSession.js b/packages/bruno-app/src/providers/ReduxStore/utils/draftSession.js new file mode 100644 index 00000000000..33dedee4490 --- /dev/null +++ b/packages/bruno-app/src/providers/ReduxStore/utils/draftSession.js @@ -0,0 +1,157 @@ +import { flattenItems, findEnvironmentInCollection, hasRequestChanges, isItemAFolder, isItemARequest } from 'utils/collections'; +import { normalizePath } from 'utils/common/path'; + +const STORAGE_KEY = 'bruno.appCloseDraftSession.v1'; + +const isStorageAvailable = () => { + try { + return typeof window !== 'undefined' && !!window.localStorage; + } catch (error) { + return false; + } +}; + +const safeParse = (value) => { + if (!value) { + return null; + } + + try { + return JSON.parse(value); + } catch (error) { + return null; + } +}; + +const getCollectionEnvironmentDraft = (collection) => { + if (!collection?.environmentsDraft?.environmentUid || !collection?.environmentsDraft?.variables) { + return null; + } + + const environment = findEnvironmentInCollection(collection, collection.environmentsDraft.environmentUid); + + return { + environmentUid: collection.environmentsDraft.environmentUid, + environmentName: environment?.name || null, + variables: collection.environmentsDraft.variables + }; +}; + +const getGlobalEnvironmentDraft = (state) => { + const draft = state?.globalEnvironments?.globalEnvironmentDraft; + if (!draft?.environmentUid || !draft?.variables) { + return null; + } + + const environment = state?.globalEnvironments?.globalEnvironments?.find((env) => env.uid === draft.environmentUid); + + return { + environmentUid: draft.environmentUid, + environmentName: environment?.name || null, + variables: draft.variables + }; +}; + +const getCollectionDraftSession = (collection) => { + if (!collection?.pathname) { + return null; + } + + const requestDrafts = {}; + const folderDrafts = {}; + const items = flattenItems(collection.items || []); + + items.forEach((item) => { + if (!item?.draft || !item?.pathname) { + return; + } + + const normalizedPath = normalizePath(item.pathname); + + if (isItemARequest(item) && hasRequestChanges(item)) { + requestDrafts[normalizedPath] = item.draft; + return; + } + + if (isItemAFolder(item)) { + folderDrafts[normalizedPath] = item.draft; + } + }); + + const environmentsDraft = getCollectionEnvironmentDraft(collection); + const hasRequestDrafts = Object.keys(requestDrafts).length > 0; + const hasFolderDrafts = Object.keys(folderDrafts).length > 0; + const hasCollectionDraft = !!collection.draft; + const hasEnvironmentDraft = !!environmentsDraft; + + if (!hasRequestDrafts && !hasFolderDrafts && !hasCollectionDraft && !hasEnvironmentDraft) { + return null; + } + + return { + pathname: normalizePath(collection.pathname), + collectionDraft: collection.draft || null, + requestDrafts, + folderDrafts, + environmentsDraft + }; +}; + +export const getPersistedDraftSession = () => { + if (!isStorageAvailable()) { + return null; + } + + return safeParse(window.localStorage.getItem(STORAGE_KEY)); +}; + +export const getPersistedCollectionDraftSession = (pathname) => { + if (!pathname) { + return null; + } + + const session = getPersistedDraftSession(); + return session?.collections?.[normalizePath(pathname)] || null; +}; + +export const persistDraftSession = (state) => { + console.log('[draftSession] Persisting draft session'); + if (!isStorageAvailable()) { + return; + } + + const collections = state?.collections?.collections || []; + const snapshot = { + version: 1, + collections: {}, + globalEnvironmentDraft: getGlobalEnvironmentDraft(state) + }; + + collections.forEach((collection) => { + const collectionDraftSession = getCollectionDraftSession(collection); + if (collectionDraftSession) { + snapshot.collections[collectionDraftSession.pathname] = collectionDraftSession; + } + }); + + const hasCollectionDrafts = Object.keys(snapshot.collections).length > 0; + const hasGlobalDraft = !!snapshot.globalEnvironmentDraft; + + if (!hasCollectionDrafts && !hasGlobalDraft) { + console.log('[draftSession] clearing persisted draft session'); + window.localStorage.removeItem(STORAGE_KEY); + return; + } + + console.log('[draftSession] writing persisted draft session', snapshot); + window.localStorage.setItem(STORAGE_KEY, JSON.stringify(snapshot)); +}; + +export const clearPersistedDraftSession = () => { + if (!isStorageAvailable()) { + return; + } + + console.log('[draftSession] removing persisted draft session'); + window.localStorage.removeItem(STORAGE_KEY); +}; From 5c97bc4b3638d6149d72056f0d64d3535edd3fa2 Mon Sep 17 00:00:00 2001 From: Neeraj Rithaliya Date: Sat, 29 Aug 2026 16:18:53 +0530 Subject: [PATCH 2/3] fix undefined tabs & import --- .../src/providers/App/ConfirmAppClose/SaveRequestsModal.js | 2 ++ packages/bruno-app/src/providers/App/useIpcEvents.js | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/bruno-app/src/providers/App/ConfirmAppClose/SaveRequestsModal.js b/packages/bruno-app/src/providers/App/ConfirmAppClose/SaveRequestsModal.js index 9dd4a5f063c..97cf539a34e 100644 --- a/packages/bruno-app/src/providers/App/ConfirmAppClose/SaveRequestsModal.js +++ b/packages/bruno-app/src/providers/App/ConfirmAppClose/SaveRequestsModal.js @@ -1,6 +1,7 @@ import React, { useEffect, useMemo } from 'react'; import each from 'lodash/each'; import filter from 'lodash/filter'; +import groupBy from 'lodash/groupBy'; import { useSelector } from 'react-redux'; import { useDispatch } from 'react-redux'; import { flattenItems, isItemARequest, hasRequestChanges, findEnvironmentInCollection } from 'utils/collections'; @@ -21,6 +22,7 @@ import { clearPersistedDraftSession, persistDraftSession } from 'providers/Redux const SaveRequestsModal = ({ onClose, forceCloseTabs = false, tabUidsToClose = [] }) => { const MAX_UNSAVED_ITEMS_TO_SHOW = 5; const collections = useSelector((state) => state.collections.collections); + const tabs = useSelector((state) => state.tabs.tabs); const globalEnvironments = useSelector((state) => state.globalEnvironments.globalEnvironments); const globalEnvironmentDraft = useSelector((state) => state.globalEnvironments.globalEnvironmentDraft); const dispatch = useDispatch(); diff --git a/packages/bruno-app/src/providers/App/useIpcEvents.js b/packages/bruno-app/src/providers/App/useIpcEvents.js index 737f444fb36..2305dcf1d16 100644 --- a/packages/bruno-app/src/providers/App/useIpcEvents.js +++ b/packages/bruno-app/src/providers/App/useIpcEvents.js @@ -45,11 +45,9 @@ import { workspaceDotEnvUpdateEvent, setWorkspaceDotEnvVariables } from 'provide import toast from 'react-hot-toast'; import { useDispatch, useStore } from 'react-redux'; import { isElectron } from 'utils/common/platform'; -import { globalEnvironmentsUpdateEvent, updateGlobalEnvironments, _clearScriptGlobalEnvBaseline } from 'providers/ReduxStore/slices/global-environments'; +import { globalEnvironmentsUpdateEvent, updateGlobalEnvironments, _clearScriptGlobalEnvBaseline, restoreGlobalEnvironmentDraftFromSession } from 'providers/ReduxStore/slices/global-environments'; import { collectionAddOauth2CredentialsByUrl, collectionClearOauth2CredentialsByCredentialsId, updateCollectionLoadingState, collectionLoadedFromTree } from 'providers/ReduxStore/slices/collections/index'; import { migrationProgressEvent } from 'providers/ReduxStore/slices/collection-migration'; -import { globalEnvironmentsUpdateEvent, restoreGlobalEnvironmentDraftFromSession, updateGlobalEnvironments } from 'providers/ReduxStore/slices/global-environments'; -import { collectionAddOauth2CredentialsByUrl, collectionClearOauth2CredentialsByCredentialsId, updateCollectionLoadingState } from 'providers/ReduxStore/slices/collections/index'; import { addLog } from 'providers/ReduxStore/slices/logs'; import { loadNotifications } from 'providers/ReduxStore/slices/notifications'; import { updateSystemResources } from 'providers/ReduxStore/slices/performance'; From 17a72a3dcca2ad8b4ac5fc0dad2c9741a90136f9 Mon Sep 17 00:00:00 2001 From: Neeraj Rithaliya Date: Sat, 29 Aug 2026 18:41:26 +0530 Subject: [PATCH 3/3] fix: Removed unnecessary logs & unused import --- .../src/providers/ReduxStore/utils/draftSession.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/bruno-app/src/providers/ReduxStore/utils/draftSession.js b/packages/bruno-app/src/providers/ReduxStore/utils/draftSession.js index 33dedee4490..8c9c89aef72 100644 --- a/packages/bruno-app/src/providers/ReduxStore/utils/draftSession.js +++ b/packages/bruno-app/src/providers/ReduxStore/utils/draftSession.js @@ -102,7 +102,11 @@ export const getPersistedDraftSession = () => { return null; } - return safeParse(window.localStorage.getItem(STORAGE_KEY)); + try { + return safeParse(window.localStorage.getItem(STORAGE_KEY)); + } catch (error) { + return null; + } }; export const getPersistedCollectionDraftSession = (pathname) => { @@ -115,7 +119,6 @@ export const getPersistedCollectionDraftSession = (pathname) => { }; export const persistDraftSession = (state) => { - console.log('[draftSession] Persisting draft session'); if (!isStorageAvailable()) { return; } @@ -138,12 +141,10 @@ export const persistDraftSession = (state) => { const hasGlobalDraft = !!snapshot.globalEnvironmentDraft; if (!hasCollectionDrafts && !hasGlobalDraft) { - console.log('[draftSession] clearing persisted draft session'); window.localStorage.removeItem(STORAGE_KEY); return; } - console.log('[draftSession] writing persisted draft session', snapshot); window.localStorage.setItem(STORAGE_KEY, JSON.stringify(snapshot)); }; @@ -152,6 +153,5 @@ export const clearPersistedDraftSession = () => { return; } - console.log('[draftSession] removing persisted draft session'); window.localStorage.removeItem(STORAGE_KEY); };