From 1adfad63162c0b9d4f4bc82cc57e867ea84e26f6 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Mon, 30 Sep 2024 11:01:30 +0530 Subject: [PATCH 01/15] release: v1.31.0 --- packages/bruno-app/src/components/Sidebar/index.js | 2 +- packages/bruno-app/src/providers/App/useTelemetry.js | 2 +- packages/bruno-electron/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/bruno-app/src/components/Sidebar/index.js b/packages/bruno-app/src/components/Sidebar/index.js index cc878bcc9..2423bce68 100644 --- a/packages/bruno-app/src/components/Sidebar/index.js +++ b/packages/bruno-app/src/components/Sidebar/index.js @@ -185,7 +185,7 @@ const Sidebar = () => { Star */} -
v1.30.1
+
v1.31.0
diff --git a/packages/bruno-app/src/providers/App/useTelemetry.js b/packages/bruno-app/src/providers/App/useTelemetry.js index 55b0bbdad..279b96a2c 100644 --- a/packages/bruno-app/src/providers/App/useTelemetry.js +++ b/packages/bruno-app/src/providers/App/useTelemetry.js @@ -60,7 +60,7 @@ const trackStart = () => { event: 'start', properties: { os: platformLib.os.family, - version: '1.30.1' + version: '1.31.0' } }); }; diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json index b158989aa..b2b382754 100644 --- a/packages/bruno-electron/package.json +++ b/packages/bruno-electron/package.json @@ -1,5 +1,5 @@ { - "version": "v1.30.1", + "version": "v1.31.0", "name": "bruno", "description": "Opensource API Client for Exploring and Testing APIs", "homepage": "https://www.usebruno.com", From 727fa26e44dd6461d41b4c4e27d48f02781337b4 Mon Sep 17 00:00:00 2001 From: Sanjai Kumar <84461672+sanjai0py@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:18:02 +0530 Subject: [PATCH 02/15] Refactor CodeMirror styling to remove glow outline around folded JSON (#3208) * Refactor CodeMirror styling to remove glow outline around folded JSON * Improved font color for better legibility. * chore: used colot from theme for codemirror fold count --------- Co-authored-by: Anoop M D --- .../bruno-app/src/components/CodeEditor/StyledWrapper.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/bruno-app/src/components/CodeEditor/StyledWrapper.js b/packages/bruno-app/src/components/CodeEditor/StyledWrapper.js index c77749cb8..4d47186c0 100644 --- a/packages/bruno-app/src/components/CodeEditor/StyledWrapper.js +++ b/packages/bruno-app/src/components/CodeEditor/StyledWrapper.js @@ -10,6 +10,12 @@ const StyledWrapper = styled.div` flex: 1 1 0; } + /* Removes the glow outline around the folded json */ + .CodeMirror-foldmarker { + text-shadow: none; + color: ${(props) => props.theme.textLink}; + } + .CodeMirror-overlayscroll-horizontal div, .CodeMirror-overlayscroll-vertical div { background: #d2d7db; From f35b715c6f2af0b019e8afc295fc8b1d00bc26b9 Mon Sep 17 00:00:00 2001 From: lohit Date: Mon, 30 Sep 2024 16:39:05 +0530 Subject: [PATCH 03/15] feat: restrict access to system process env vars (#3226) --- packages/bruno-electron/src/app/watcher.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/bruno-electron/src/app/watcher.js b/packages/bruno-electron/src/app/watcher.js index 589cd29d8..b93b01a55 100644 --- a/packages/bruno-electron/src/app/watcher.js +++ b/packages/bruno-electron/src/app/watcher.js @@ -201,7 +201,6 @@ const add = async (win, pathname, collectionUid, collectionPath) => { const payload = { collectionUid, processEnvVariables: { - ...process.env, ...jsonData } }; @@ -331,7 +330,6 @@ const change = async (win, pathname, collectionUid, collectionPath) => { const payload = { collectionUid, processEnvVariables: { - ...process.env, ...jsonData } }; From d448599a531ce29b9a8c0feb661b8cfa99557789 Mon Sep 17 00:00:00 2001 From: lohit Date: Mon, 30 Sep 2024 16:51:49 +0530 Subject: [PATCH 04/15] feat: ui-state-snapshot (#3215) * wip: save env * feat: updates * feat: updates --- .../src/providers/App/useIpcEvents.js | 7 ++- .../ReduxStore/slices/collections/actions.js | 41 +++++++++++-- .../bruno-app/src/utils/collections/index.js | 4 ++ packages/bruno-electron/src/app/watcher.js | 9 +++ packages/bruno-electron/src/ipc/collection.js | 10 ++++ .../src/store/ui-state-snapshot.js | 60 +++++++++++++++++++ 6 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 packages/bruno-electron/src/store/ui-state-snapshot.js diff --git a/packages/bruno-app/src/providers/App/useIpcEvents.js b/packages/bruno-app/src/providers/App/useIpcEvents.js index f4a04030f..b885ad74d 100644 --- a/packages/bruno-app/src/providers/App/useIpcEvents.js +++ b/packages/bruno-app/src/providers/App/useIpcEvents.js @@ -19,7 +19,7 @@ import { runRequestEvent, scriptEnvironmentUpdateEvent } from 'providers/ReduxStore/slices/collections'; -import { collectionAddEnvFileEvent, openCollectionEvent } from 'providers/ReduxStore/slices/collections/actions'; +import { collectionAddEnvFileEvent, openCollectionEvent, hydrateCollectionsWithUiStateSnapshot } from 'providers/ReduxStore/slices/collections/actions'; import toast from 'react-hot-toast'; import { useDispatch } from 'react-redux'; import { isElectron } from 'utils/common/platform'; @@ -149,6 +149,10 @@ const useIpcEvents = () => { dispatch(updateCookies(val)); }); + const removeSnapshotHydrationListener = ipcRenderer.on('main:hydrate-app-with-ui-state-snapshot', (val) => { + dispatch(hydrateCollectionsWithUiStateSnapshot(val)); + }) + return () => { removeCollectionTreeUpdateListener(); removeOpenCollectionListener(); @@ -165,6 +169,7 @@ const useIpcEvents = () => { removePreferencesUpdatesListener(); removeCookieUpdateListener(); removeSystemProxyEnvUpdatesListener(); + removeSnapshotHydrationListener(); }; }, [isElectron]); }; 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 777a194ab..e582b0f1f 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js @@ -44,6 +44,7 @@ import { parsePathParams, parseQueryParams, splitOnFirst } from 'utils/url/index import { sendCollectionOauth2Request as _sendCollectionOauth2Request } from 'utils/network/index'; import { name } from 'file-loader'; import slash from 'utils/common/slash'; +import { findCollectionByPathname, findEnvironmentInCollectionByName } from 'utils/collections/index'; export const renameCollection = (newName, collectionUid) => (dispatch, getState) => { const state = getState(); @@ -972,13 +973,15 @@ export const selectEnvironment = (environmentUid, collectionUid) => (dispatch, g const collectionCopy = cloneDeep(collection); if (environmentUid) { const environment = findEnvironmentInCollection(collectionCopy, environmentUid); - if (!environment) { + if (environment) { + ipcRenderer.invoke('renderer:update-ui-state-snapshot', { type: 'COLLECTION_ENVIRONMENT', data: { collectionPath: collection?.pathname, environmentName: environment?.name } }) + dispatch(_selectEnvironment({ environmentUid, collectionUid })); + resolve(); + } + else { return reject(new Error('Environment not found')); } } - - dispatch(_selectEnvironment({ environmentUid, collectionUid })); - resolve(); }); }; @@ -1141,3 +1144,33 @@ export const saveCollectionSecurityConfig = (collectionUid, securityConfig) => ( .catch(reject); }); }; + + +export const hydrateCollectionsWithUiStateSnapshot = (payload) => (dispatch, getState) => { + const collectionSnapshotData = payload; + return new Promise((resolve, reject) => { + const state = getState(); + try { + if(!collectionSnapshotData) resolve(); + const { pathname, selectedEnvironment } = collectionSnapshotData; + const collection = findCollectionByPathname(state.collections.collections, pathname); + const collectionCopy = cloneDeep(collection); + const collectionUid = collectionCopy?.uid; + + // update selected environment + if (selectedEnvironment) { + const environment = findEnvironmentInCollectionByName(collectionCopy, selectedEnvironment); + if (environment) { + dispatch(_selectEnvironment({ environmentUid: environment?.uid, collectionUid })); + } + } + + // todo: add any other redux state that you want to save + + resolve(); + } + catch(error) { + reject(error); + } + }); + }; \ No newline at end of file diff --git a/packages/bruno-app/src/utils/collections/index.js b/packages/bruno-app/src/utils/collections/index.js index ea8712be5..ddb98f531 100644 --- a/packages/bruno-app/src/utils/collections/index.js +++ b/packages/bruno-app/src/utils/collections/index.js @@ -132,6 +132,10 @@ export const findEnvironmentInCollection = (collection, envUid) => { return find(collection.environments, (e) => e.uid === envUid); }; +export const findEnvironmentInCollectionByName = (collection, name) => { + return find(collection.environments, (e) => e.name === name); +}; + export const moveCollectionItem = (collection, draggedItem, targetItem) => { let draggedItemParent = findParentItemInCollection(collection, draggedItem.uid); diff --git a/packages/bruno-electron/src/app/watcher.js b/packages/bruno-electron/src/app/watcher.js index b93b01a55..82d116d81 100644 --- a/packages/bruno-electron/src/app/watcher.js +++ b/packages/bruno-electron/src/app/watcher.js @@ -12,6 +12,7 @@ const { decryptString } = require('../utils/encryption'); const { setDotEnvVars } = require('../store/process-env'); const { setBrunoConfig } = require('../store/bruno-config'); const EnvironmentSecretsStore = require('../store/env-secrets'); +const UiStateSnapshot = require('../store/ui-state-snapshot'); const environmentSecretsStore = new EnvironmentSecretsStore(); @@ -421,6 +422,13 @@ const unlinkDir = (win, pathname, collectionUid, collectionPath) => { win.webContents.send('main:collection-tree-updated', 'unlinkDir', directory); }; +const onWatcherSetupComplete = (win, collectionPath) => { + const UiStateSnapshotStore = new UiStateSnapshot(); + const collectionsSnapshotState = UiStateSnapshotStore.getCollections(); + const collectionSnapshotState = collectionsSnapshotState?.find(c => c?.pathname == collectionPath); + win.webContents.send('main:hydrate-app-with-ui-state-snapshot', collectionSnapshotState); +}; + class Watcher { constructor() { this.watchers = {}; @@ -456,6 +464,7 @@ class Watcher { let startedNewWatcher = false; watcher + .on('ready', () => onWatcherSetupComplete(win, watchPath)) .on('add', (pathname) => add(win, pathname, collectionUid, watchPath)) .on('addDir', (pathname) => addDirectory(win, pathname, collectionUid, watchPath)) .on('change', (pathname) => change(win, pathname, collectionUid, watchPath)) diff --git a/packages/bruno-electron/src/ipc/collection.js b/packages/bruno-electron/src/ipc/collection.js index 950902ece..0aa2058c2 100644 --- a/packages/bruno-electron/src/ipc/collection.js +++ b/packages/bruno-electron/src/ipc/collection.js @@ -25,9 +25,11 @@ const { moveRequestUid, deleteRequestUid } = require('../cache/requestUids'); const { deleteCookiesForDomain, getDomainsWithCookies } = require('../utils/cookies'); const EnvironmentSecretsStore = require('../store/env-secrets'); const CollectionSecurityStore = require('../store/collection-security'); +const UiStateSnapshot = require('../store/ui-state-snapshot'); const environmentSecretsStore = new EnvironmentSecretsStore(); const collectionSecurityStore = new CollectionSecurityStore(); +const UiStateSnapshotStore = new UiStateSnapshot(); const envHasSecrets = (environment = {}) => { const secrets = _.filter(environment.variables, (v) => v.secret); @@ -695,6 +697,14 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection return Promise.reject(error); } }); + + ipcMain.handle('renderer:update-ui-state-snapshot', (event, { type, data }) => { + try { + UiStateSnapshotStore.update({ type, data }); + } catch (error) { + throw new Error(error.message); + } + }); }; const registerMainEventHandlers = (mainWindow, watcher, lastOpenedCollections) => { diff --git a/packages/bruno-electron/src/store/ui-state-snapshot.js b/packages/bruno-electron/src/store/ui-state-snapshot.js new file mode 100644 index 000000000..b3d1909b6 --- /dev/null +++ b/packages/bruno-electron/src/store/ui-state-snapshot.js @@ -0,0 +1,60 @@ +const Store = require('electron-store'); + +class UiStateSnapshot { + constructor() { + this.store = new Store({ + name: 'ui-state-snapshot', + clearInvalidConfig: true + }); + } + + getCollections() { + return this.store.get('collections') || []; + } + + saveCollections(collections) { + this.store.set('collections', collections); + } + + getCollectionByPathname({ pathname }) { + let collections = this.getCollections(); + + let collection = collections.find(c => c?.pathname === pathname); + if (!collection) { + collection = { pathname }; + collections.push(collection); + this.saveCollections(collections); + } + + return collection; + } + + setCollectionByPathname({ collection }) { + let collections = this.getCollections(); + + collections = collections.filter(c => c?.pathname !== collection.pathname); + collections.push({ ...collection }); + this.saveCollections(collections); + + return collection; + } + + updateCollectionEnvironment({ collectionPath, environmentName }) { + const collection = this.getCollectionByPathname({ pathname: collectionPath }); + collection.selectedEnvironment = environmentName; + this.setCollectionByPathname({ collection }); + } + + update({ type, data }) { + switch(type) { + case 'COLLECTION_ENVIRONMENT': + const { collectionPath, environmentName } = data; + this.updateCollectionEnvironment({ collectionPath, environmentName }); + break; + default: + break; + } + } +} + +module.exports = UiStateSnapshot; From e2baed6724ae49ea9ded78dc3918f86f3365a36a Mon Sep 17 00:00:00 2001 From: lohit Date: Mon, 30 Sep 2024 17:14:58 +0530 Subject: [PATCH 05/15] fix: interpolate json body for type object -- graphql variables (#3212) --- packages/bruno-electron/src/ipc/network/interpolate-vars.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/bruno-electron/src/ipc/network/interpolate-vars.js b/packages/bruno-electron/src/ipc/network/interpolate-vars.js index 5ea2bf7f4..e60d52428 100644 --- a/packages/bruno-electron/src/ipc/network/interpolate-vars.js +++ b/packages/bruno-electron/src/ipc/network/interpolate-vars.js @@ -68,6 +68,12 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc if (request.data.length) { request.data = _interpolate(request.data); } + } else if (typeof request.data === 'object') { + try { + let parsed = JSON.stringify(request.data); + parsed = _interpolate(parsed); + request.data = JSON.parse(parsed); + } catch (err) {} } } else if (contentType === 'application/x-www-form-urlencoded') { if (typeof request.data === 'object') { From 02a82c5371d347a8148cac3be7b221b46593c4e2 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 <54320162+Pragadesh-45@users.noreply.github.com> Date: Mon, 30 Sep 2024 17:19:18 +0530 Subject: [PATCH 06/15] refactor: `ReorderTable` component to use `useMemo` for rowsOrder (#3227) --- .../bruno-app/src/components/ReorderTable/index.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/bruno-app/src/components/ReorderTable/index.js b/packages/bruno-app/src/components/ReorderTable/index.js index 9d8c11088..b5ea369a2 100644 --- a/packages/bruno-app/src/components/ReorderTable/index.js +++ b/packages/bruno-app/src/components/ReorderTable/index.js @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState, useCallback } from 'react'; +import React, { useEffect, useRef, useState, useMemo } from 'react'; import { IconGripVertical, IconMinusVertical } from '@tabler/icons'; /** @@ -13,17 +13,17 @@ import { IconGripVertical, IconMinusVertical } from '@tabler/icons'; const ReorderTable = ({ children, updateReorderedItem }) => { const tbodyRef = useRef(); - const [rowsOrder, setRowsOrder] = useState(React.Children.toArray(children)); const [hoveredRow, setHoveredRow] = useState(null); const [dragStart, setDragStart] = useState(null); + const rowsOrder = useMemo(() => React.Children.toArray(children), [children]); + /** - * useEffect hook to update the rows order and handle row hover states + * useEffect hook to handle row hover states */ useEffect(() => { - setRowsOrder(React.Children.toArray(children)); handleRowHover(null, false); - }, [children, dragStart]); + }, [children]); const handleRowHover = (index, hoverstatus = true) => { setHoveredRow(hoverstatus ? index : null); @@ -48,7 +48,6 @@ const ReorderTable = ({ children, updateReorderedItem }) => { const updatedRowsOrder = [...rowsOrder]; const [movedRow] = updatedRowsOrder.splice(fromIndex, 1); updatedRowsOrder.splice(toIndex, 0, movedRow); - setRowsOrder(updatedRowsOrder); updateReorderedItem({ updateReorderedItem: updatedRowsOrder.map((row) => row.props['data-uid']) From 95e56cd9c950ad6bca80760dcb8ea508764f0a86 Mon Sep 17 00:00:00 2001 From: Sanjai Kumar <84461672+sanjai0py@users.noreply.github.com> Date: Mon, 30 Sep 2024 17:20:46 +0530 Subject: [PATCH 07/15] Added Keybindings tab. (#3204) * Added Keybindings tab. * Minor Refactoring --- .../Preferences/Keybindings/StyledWrapper.js | 46 ++++++++++++++ .../Preferences/Keybindings/index.js | 45 ++++++++++++++ .../src/components/Preferences/index.js | 12 +++- .../bruno-app/src/providers/Hotkeys/index.js | 33 +++++----- .../src/providers/Hotkeys/keyMappings.js | 60 +++++++++++++++++++ 5 files changed, 179 insertions(+), 17 deletions(-) create mode 100644 packages/bruno-app/src/components/Preferences/Keybindings/StyledWrapper.js create mode 100644 packages/bruno-app/src/components/Preferences/Keybindings/index.js create mode 100644 packages/bruno-app/src/providers/Hotkeys/keyMappings.js diff --git a/packages/bruno-app/src/components/Preferences/Keybindings/StyledWrapper.js b/packages/bruno-app/src/components/Preferences/Keybindings/StyledWrapper.js new file mode 100644 index 000000000..e12969388 --- /dev/null +++ b/packages/bruno-app/src/components/Preferences/Keybindings/StyledWrapper.js @@ -0,0 +1,46 @@ +import styled from 'styled-components'; + +const StyledWrapper = styled.div` + table { + width: 100%; + border-collapse: collapse; + + thead, + td { + border: 2px solid ${(props) => props.theme.table.border}; + } + + thead { + color: ${(props) => props.theme.table.thead.color}; + font-size: 1rem; + user-select: none; + } + + td { + padding: 4px 8px; + } + + thead th { + font-weight: 600; + padding: 10px; + text-align: left; + } + } + + .table-container { + max-height: 400px; + overflow-y: scroll; + } + + .key-button { + display: inline-block; + color: ${(props) => props.theme.colors.text.white}; + border-radius: 4px; + padding: 1px 5px; + font-family: monospace; + margin-right: 8px; + border: 1px solid #ccc; + } +`; + +export default StyledWrapper; diff --git a/packages/bruno-app/src/components/Preferences/Keybindings/index.js b/packages/bruno-app/src/components/Preferences/Keybindings/index.js new file mode 100644 index 000000000..d2bc918aa --- /dev/null +++ b/packages/bruno-app/src/components/Preferences/Keybindings/index.js @@ -0,0 +1,45 @@ +import StyledWrapper from './StyledWrapper'; +import React from 'react'; +import { getKeyBindingsForOS } from 'providers/Hotkeys/keyMappings'; +import { isMacOS } from 'utils/common/platform'; + +const Keybindings = ({ close }) => { + const keyMapping = getKeyBindingsForOS(isMacOS() ? 'mac' : 'windows'); + + return ( + +
+ + + + + + + + + {keyMapping ? ( + Object.entries(keyMapping).map(([action, { name, keys }], index) => ( + + + + + )) + ) : ( + + + + )} + +
CommandKeybinding
{name} + {keys.split('+').map((key, i) => ( +
+ {key} +
+ ))} +
No key bindings available
+
+
+ ); +}; + +export default Keybindings; diff --git a/packages/bruno-app/src/components/Preferences/index.js b/packages/bruno-app/src/components/Preferences/index.js index 03b1d9ef8..3635ca5a9 100644 --- a/packages/bruno-app/src/components/Preferences/index.js +++ b/packages/bruno-app/src/components/Preferences/index.js @@ -1,11 +1,14 @@ import Modal from 'components/Modal/index'; import classnames from 'classnames'; import React, { useState } from 'react'; + import Support from './Support'; import General from './General'; import Proxy from './ProxySettings'; +import Display from './Display'; +import Keybindings from './Keybindings'; + import StyledWrapper from './StyledWrapper'; -import Display from './Display/index'; const Preferences = ({ onClose }) => { const [tab, setTab] = useState('general'); @@ -30,6 +33,10 @@ const Preferences = ({ onClose }) => { return ; } + case 'keybindings': { + return ; + } + case 'support': { return ; } @@ -50,6 +57,9 @@ const Preferences = ({ onClose }) => {
setTab('proxy')}> Proxy
+
setTab('keybindings')}> + Keybindings +
setTab('support')}> Support
diff --git a/packages/bruno-app/src/providers/Hotkeys/index.js b/packages/bruno-app/src/providers/Hotkeys/index.js index 5b6bf1c00..41e71b4a2 100644 --- a/packages/bruno-app/src/providers/Hotkeys/index.js +++ b/packages/bruno-app/src/providers/Hotkeys/index.js @@ -10,6 +10,7 @@ import NewRequest from 'components/Sidebar/NewRequest'; import { sendRequest, saveRequest, saveCollectionRoot } from 'providers/ReduxStore/slices/collections/actions'; import { findCollectionByUid, findItemInCollection } from 'utils/collections'; import { closeTabs, switchTab } from 'providers/ReduxStore/slices/tabs'; +import { getKeyBindingsForActionAllOS } from './keyMappings'; export const HotkeysContext = React.createContext(); @@ -43,7 +44,7 @@ export const HotkeysProvider = (props) => { // save hotkey useEffect(() => { - Mousetrap.bind(['command+s', 'ctrl+s'], (e) => { + Mousetrap.bind([...getKeyBindingsForActionAllOS('save')], (e) => { if (isEnvironmentSettingsModalOpen) { console.log('todo: save environment settings'); } else { @@ -68,13 +69,13 @@ export const HotkeysProvider = (props) => { }); return () => { - Mousetrap.unbind(['command+s', 'ctrl+s']); + Mousetrap.unbind([...getKeyBindingsForActionAllOS('save')]); }; }, [activeTabUid, tabs, saveRequest, collections, isEnvironmentSettingsModalOpen]); // send request (ctrl/cmd + enter) useEffect(() => { - Mousetrap.bind(['command+enter', 'ctrl+enter'], (e) => { + Mousetrap.bind([...getKeyBindingsForActionAllOS('sendRequest')], (e) => { const activeTab = find(tabs, (t) => t.uid === activeTabUid); if (activeTab) { const collection = findCollectionByUid(collections, activeTab.collectionUid); @@ -95,13 +96,13 @@ export const HotkeysProvider = (props) => { }); return () => { - Mousetrap.unbind(['command+enter', 'ctrl+enter']); + Mousetrap.unbind([...getKeyBindingsForActionAllOS('sendRequest')]); }; }, [activeTabUid, tabs, saveRequest, collections]); // edit environments (ctrl/cmd + e) useEffect(() => { - Mousetrap.bind(['command+e', 'ctrl+e'], (e) => { + Mousetrap.bind([...getKeyBindingsForActionAllOS('editEnvironment')], (e) => { const activeTab = find(tabs, (t) => t.uid === activeTabUid); if (activeTab) { const collection = findCollectionByUid(collections, activeTab.collectionUid); @@ -115,13 +116,13 @@ export const HotkeysProvider = (props) => { }); return () => { - Mousetrap.unbind(['command+e', 'ctrl+e']); + Mousetrap.unbind([...getKeyBindingsForActionAllOS('editEnvironment')]); }; }, [activeTabUid, tabs, collections, setShowEnvSettingsModal]); // new request (ctrl/cmd + b) useEffect(() => { - Mousetrap.bind(['command+b', 'ctrl+b'], (e) => { + Mousetrap.bind([...getKeyBindingsForActionAllOS('newRequest')], (e) => { const activeTab = find(tabs, (t) => t.uid === activeTabUid); if (activeTab) { const collection = findCollectionByUid(collections, activeTab.collectionUid); @@ -135,13 +136,13 @@ export const HotkeysProvider = (props) => { }); return () => { - Mousetrap.unbind(['command+b', 'ctrl+b']); + Mousetrap.unbind([...getKeyBindingsForActionAllOS('newRequest')]); }; }, [activeTabUid, tabs, collections, setShowNewRequestModal]); // close tab hotkey useEffect(() => { - Mousetrap.bind(['command+w', 'ctrl+w'], (e) => { + Mousetrap.bind([...getKeyBindingsForActionAllOS('closeTab')], (e) => { dispatch( closeTabs({ tabUids: [activeTabUid] @@ -152,13 +153,13 @@ export const HotkeysProvider = (props) => { }); return () => { - Mousetrap.unbind(['command+w', 'ctrl+w']); + Mousetrap.unbind([...getKeyBindingsForActionAllOS('closeTab')]); }; }, [activeTabUid]); // Switch to the previous tab useEffect(() => { - Mousetrap.bind(['command+pageup', 'ctrl+pageup'], (e) => { + Mousetrap.bind([...getKeyBindingsForActionAllOS('switchToPreviousTab')], (e) => { dispatch( switchTab({ direction: 'pageup' @@ -169,13 +170,13 @@ export const HotkeysProvider = (props) => { }); return () => { - Mousetrap.unbind(['command+pageup', 'ctrl+pageup']); + Mousetrap.unbind([...getKeyBindingsForActionAllOS('switchToPreviousTab')]); }; }, [dispatch]); // Switch to the next tab useEffect(() => { - Mousetrap.bind(['command+pagedown', 'ctrl+pagedown'], (e) => { + Mousetrap.bind([...getKeyBindingsForActionAllOS('switchToNextTab')], (e) => { dispatch( switchTab({ direction: 'pagedown' @@ -186,13 +187,13 @@ export const HotkeysProvider = (props) => { }); return () => { - Mousetrap.unbind(['command+pagedown', 'ctrl+pagedown']); + Mousetrap.unbind([...getKeyBindingsForActionAllOS('switchToNextTab')]); }; }, [dispatch]); // Close all tabs useEffect(() => { - Mousetrap.bind(['command+shift+w', 'ctrl+shift+w'], (e) => { + Mousetrap.bind([...getKeyBindingsForActionAllOS('closeAllTabs')], (e) => { const activeTab = find(tabs, (t) => t.uid === activeTabUid); if (activeTab) { const collection = findCollectionByUid(collections, activeTab.collectionUid); @@ -211,7 +212,7 @@ export const HotkeysProvider = (props) => { }); return () => { - Mousetrap.unbind(['command+shift+w', 'ctrl+shift+w']); + Mousetrap.unbind([...getKeyBindingsForActionAllOS('closeAllTabs')]); }; }, [activeTabUid, tabs, collections, dispatch]); diff --git a/packages/bruno-app/src/providers/Hotkeys/keyMappings.js b/packages/bruno-app/src/providers/Hotkeys/keyMappings.js new file mode 100644 index 000000000..05ad4531b --- /dev/null +++ b/packages/bruno-app/src/providers/Hotkeys/keyMappings.js @@ -0,0 +1,60 @@ +const KeyMapping = { + save: { mac: 'command+s', windows: 'ctrl+s', name: 'Save' }, + sendRequest: { mac: 'command+enter', windows: 'ctrl+enter', name: 'Send Request' }, + editEnvironment: { mac: 'command+e', windows: 'ctrl+e', name: 'Edit Environment' }, + newRequest: { mac: 'command+b', windows: 'ctrl+b', name: 'New Request' }, + closeTab: { mac: 'command+w', windows: 'ctrl+w', name: 'Close Tab' }, + openPreferences: { mac: 'command+,', windows: 'ctrl+,', name: 'Open Preferences' }, + minimizeWindow: { + mac: 'command+Shift+Q', + windows: 'control+Shift+Q', + name: 'Minimize Window' + }, + switchToPreviousTab: { + mac: 'command+pageup', + windows: 'ctrl+pageup', + name: 'Switch to Previous Tab' + }, + switchToNextTab: { + mac: 'command+pagedown', + windows: 'ctrl+pagedown', + name: 'Switch to Next Tab' + }, + closeAllTabs: { mac: 'command+shift+w', windows: 'ctrl+shift+w', name: 'Close All Tabs' } +}; + +/** + * Retrieves the key bindings for a specific operating system. + * + * @param {string} os - The operating system (e.g., 'mac', 'windows'). + * @returns {Object} An object containing the key bindings for the specified OS. + */ +export const getKeyBindingsForOS = (os) => { + const keyBindings = {}; + for (const [action, { name, ...keys }] of Object.entries(KeyMapping)) { + if (keys[os]) { + keyBindings[action] = { + keys: keys[os], + name + }; + } + } + return keyBindings; +}; + +/** + * Retrieves the key bindings for a specific action across all operating systems. + * + * @param {string} action - The action for which to retrieve key bindings. + * @returns {Object|null} An object containing the key bindings for macOS, Windows, or null if the action is not found. + */ +export const getKeyBindingsForActionAllOS = (action) => { + const actionBindings = KeyMapping[action]; + + if (!actionBindings) { + console.warn(`Action "${action}" not found in KeyMapping.`); + return null; + } + + return [actionBindings.mac, actionBindings.windows]; +}; From 4797119657c4a315088494f85a3a93b2c48526b7 Mon Sep 17 00:00:00 2001 From: lohit Date: Tue, 1 Oct 2024 18:24:03 +0530 Subject: [PATCH 08/15] fix: interpolate form-urlencoded and multipart formdata values individually (#3237) * fix: interpolate form-urlencoded and multipart values individually * feat: cli updates --- packages/bruno-cli/src/runner/interpolate-vars.js | 12 ++++++------ .../src/ipc/network/interpolate-vars.js | 12 ++++++------ .../collection/echo/echo form-url-encoded.bru | 13 ++++++++----- .../bruno-tests/collection/echo/echo multipart.bru | 6 +++++- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/packages/bruno-cli/src/runner/interpolate-vars.js b/packages/bruno-cli/src/runner/interpolate-vars.js index 0253c10cd..2b727e671 100644 --- a/packages/bruno-cli/src/runner/interpolate-vars.js +++ b/packages/bruno-cli/src/runner/interpolate-vars.js @@ -74,17 +74,17 @@ const interpolateVars = (request, envVars = {}, runtimeVariables = {}, processEn } else if (contentType === 'application/x-www-form-urlencoded') { if (typeof request.data === 'object') { try { - let parsed = JSON.stringify(request.data); - parsed = _interpolate(parsed); - request.data = JSON.parse(parsed); + forOwn(request?.data, (value, key) => { + request.data[key] = _interpolate(value); + }); } catch (err) {} } } else if (contentType === 'multipart/form-data') { if (typeof request.data === 'object' && !(request?.data instanceof FormData)) { try { - let parsed = JSON.stringify(request.data); - parsed = _interpolate(parsed); - request.data = JSON.parse(parsed); + forOwn(request?.data, (value, key) => { + request.data[key] = _interpolate(value); + }); } catch (err) {} } } else { diff --git a/packages/bruno-electron/src/ipc/network/interpolate-vars.js b/packages/bruno-electron/src/ipc/network/interpolate-vars.js index e60d52428..99b0191cd 100644 --- a/packages/bruno-electron/src/ipc/network/interpolate-vars.js +++ b/packages/bruno-electron/src/ipc/network/interpolate-vars.js @@ -78,17 +78,17 @@ const interpolateVars = (request, envVariables = {}, runtimeVariables = {}, proc } else if (contentType === 'application/x-www-form-urlencoded') { if (typeof request.data === 'object') { try { - let parsed = JSON.stringify(request.data); - parsed = _interpolate(parsed); - request.data = JSON.parse(parsed); + forOwn(request?.data, (value, key) => { + request.data[key] = _interpolate(value); + }); } catch (err) {} } } else if (contentType === 'multipart/form-data') { if (typeof request.data === 'object' && !(request.data instanceof FormData)) { try { - let parsed = JSON.stringify(request.data); - parsed = _interpolate(parsed); - request.data = JSON.parse(parsed); + forOwn(request?.data, (value, key) => { + request.data[key] = _interpolate(value); + }); } catch (err) {} } } else { diff --git a/packages/bruno-tests/collection/echo/echo form-url-encoded.bru b/packages/bruno-tests/collection/echo/echo form-url-encoded.bru index a0d2f0afb..7c0ce77eb 100644 --- a/packages/bruno-tests/collection/echo/echo form-url-encoded.bru +++ b/packages/bruno-tests/collection/echo/echo form-url-encoded.bru @@ -12,12 +12,15 @@ post { body:form-urlencoded { form-data-key: {{form-data-key}} -} - -script:pre-request { - bru.setVar('form-data-key', 'form-data-value'); + form-data-stringified-object: {{form-data-stringified-object}} } assert { - res.body: eq form-data-key=form-data-value + res.body: eq form-data-key=form-data-value&form-data-stringified-object=%7B%22foo%22%3A123%7D +} + +script:pre-request { + let obj = JSON.stringify({foo:123}); + bru.setVar('form-data-key', 'form-data-value'); + bru.setVar('form-data-stringified-object', obj); } diff --git a/packages/bruno-tests/collection/echo/echo multipart.bru b/packages/bruno-tests/collection/echo/echo multipart.bru index b8fd8abf7..1edb2ca8a 100644 --- a/packages/bruno-tests/collection/echo/echo multipart.bru +++ b/packages/bruno-tests/collection/echo/echo multipart.bru @@ -11,14 +11,18 @@ post { } body:multipart-form { - foo: {{form-data-key}} + form-data-key: {{form-data-key}} + form-data-stringified-object: {{form-data-stringified-object}} file: @file(bruno.png) } assert { res.body: contains form-data-value + res.body: contains {"foo":123} } script:pre-request { + let obj = JSON.stringify({foo:123}); bru.setVar('form-data-key', 'form-data-value'); + bru.setVar('form-data-stringified-object', obj); } From 96e58f2f40a3973bfa56fc88432adfe905b71612 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Tue, 1 Oct 2024 20:35:26 +0530 Subject: [PATCH 09/15] release: v1.32.0 --- packages/bruno-app/src/components/Sidebar/index.js | 2 +- packages/bruno-app/src/providers/App/useTelemetry.js | 2 +- packages/bruno-electron/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/bruno-app/src/components/Sidebar/index.js b/packages/bruno-app/src/components/Sidebar/index.js index 2423bce68..fe02a8ae2 100644 --- a/packages/bruno-app/src/components/Sidebar/index.js +++ b/packages/bruno-app/src/components/Sidebar/index.js @@ -185,7 +185,7 @@ const Sidebar = () => { Star */} -
v1.31.0
+
v1.32.0
diff --git a/packages/bruno-app/src/providers/App/useTelemetry.js b/packages/bruno-app/src/providers/App/useTelemetry.js index 279b96a2c..0e709abcb 100644 --- a/packages/bruno-app/src/providers/App/useTelemetry.js +++ b/packages/bruno-app/src/providers/App/useTelemetry.js @@ -60,7 +60,7 @@ const trackStart = () => { event: 'start', properties: { os: platformLib.os.family, - version: '1.31.0' + version: '1.32.0' } }); }; diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json index b2b382754..d71156a4a 100644 --- a/packages/bruno-electron/package.json +++ b/packages/bruno-electron/package.json @@ -1,5 +1,5 @@ { - "version": "v1.31.0", + "version": "v1.32.0", "name": "bruno", "description": "Opensource API Client for Exploring and Testing APIs", "homepage": "https://www.usebruno.com", From 6bc8acd1e1f51be7e36193e44e7c9433892dc813 Mon Sep 17 00:00:00 2001 From: lohit Date: Tue, 1 Oct 2024 23:45:05 +0530 Subject: [PATCH 10/15] feat: bru fns update (#3231) --- .../src/components/CodeEditor/index.js | 1 + packages/bruno-js/src/bru.js | 8 +++++++ .../bruno-js/src/sandbox/quickjs/shims/bru.js | 24 +++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/packages/bruno-app/src/components/CodeEditor/index.js b/packages/bruno-app/src/components/CodeEditor/index.js index 5998cf10a..ea63602df 100644 --- a/packages/bruno-app/src/components/CodeEditor/index.js +++ b/packages/bruno-app/src/components/CodeEditor/index.js @@ -69,6 +69,7 @@ if (!SERVER_RENDERED) { 'bru.getVar(key)', 'bru.setVar(key,value)', 'bru.deleteVar(key)', + 'bru.deleteAllVars()', 'bru.setNextRequest(requestName)', 'req.disableParsingResponseJson()', 'bru.getRequestVar(key)', diff --git a/packages/bruno-js/src/bru.js b/packages/bruno-js/src/bru.js index 7f24cea14..30f016e9f 100644 --- a/packages/bruno-js/src/bru.js +++ b/packages/bruno-js/src/bru.js @@ -97,6 +97,14 @@ class Bru { delete this.runtimeVariables[key]; } + deleteAllVars() { + for (let key in this.runtimeVariables) { + if (this.runtimeVariables.hasOwnProperty(key)) { + delete this.runtimeVariables[key]; + } + } + } + getCollectionVar(key) { return this._interpolate(this.collectionVariables[key]); } diff --git a/packages/bruno-js/src/sandbox/quickjs/shims/bru.js b/packages/bruno-js/src/sandbox/quickjs/shims/bru.js index f045b134b..0e489265c 100644 --- a/packages/bruno-js/src/sandbox/quickjs/shims/bru.js +++ b/packages/bruno-js/src/sandbox/quickjs/shims/bru.js @@ -21,6 +21,12 @@ const addBruShimToContext = (vm, bru) => { vm.setProp(bruObject, 'getProcessEnv', getProcessEnv); getProcessEnv.dispose(); + let hasEnvVar = vm.newFunction('hasEnvVar', function (key) { + return marshallToVm(bru.hasEnvVar(vm.dump(key)), vm); + }); + vm.setProp(bruObject, 'hasEnvVar', hasEnvVar); + hasEnvVar.dispose(); + let getEnvVar = vm.newFunction('getEnvVar', function (key) { return marshallToVm(bru.getEnvVar(vm.dump(key)), vm); }); @@ -33,6 +39,12 @@ const addBruShimToContext = (vm, bru) => { vm.setProp(bruObject, 'setEnvVar', setEnvVar); setEnvVar.dispose(); + let hasVar = vm.newFunction('hasVar', function (key) { + return marshallToVm(bru.hasVar(vm.dump(key)), vm); + }); + vm.setProp(bruObject, 'hasVar', hasVar); + hasVar.dispose(); + let getVar = vm.newFunction('getVar', function (key) { return marshallToVm(bru.getVar(vm.dump(key)), vm); }); @@ -45,6 +57,18 @@ const addBruShimToContext = (vm, bru) => { vm.setProp(bruObject, 'setVar', setVar); setVar.dispose(); + let deleteVar = vm.newFunction('deleteVar', function (key) { + bru.deleteVar(vm.dump(key)); + }); + vm.setProp(bruObject, 'deleteVar', deleteVar); + deleteVar.dispose(); + + let deleteAllVars = vm.newFunction('deleteAllVars', function () { + bru.deleteAllVars(); + }); + vm.setProp(bruObject, 'deleteAllVars', deleteAllVars); + deleteAllVars.dispose(); + let setNextRequest = vm.newFunction('setNextRequest', function (nextRequest) { bru.setNextRequest(vm.dump(nextRequest)); }); From 93f8d916c444a38e94a650d61a27e307f749acb2 Mon Sep 17 00:00:00 2001 From: dwolter-emarsys <42273062+dwolter-emarsys@users.noreply.github.com> Date: Thu, 3 Oct 2024 13:53:40 -0400 Subject: [PATCH 11/15] INTERNAL | correcting WSSE logic (#3252) --- .../bruno-cli/src/runner/prepare-request.js | 10 +++++----- .../src/ipc/network/prepare-request.js | 20 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/bruno-cli/src/runner/prepare-request.js b/packages/bruno-cli/src/runner/prepare-request.js index d6688a1ff..bc2b22886 100644 --- a/packages/bruno-cli/src/runner/prepare-request.js +++ b/packages/bruno-cli/src/runner/prepare-request.js @@ -76,17 +76,17 @@ const prepareRequest = (request, collectionRoot) => { const password = get(request, 'auth.wsse.password', ''); const ts = new Date().toISOString(); - const nonce = crypto.randomBytes(16).toString('base64'); + const nonce = crypto.randomBytes(16).toString('hex'); - // Create the password digest using SHA-256 - const hash = crypto.createHash('sha256'); + // Create the password digest using SHA-1 as required for WSSE + const hash = crypto.createHash('sha1'); hash.update(nonce + ts + password); - const digest = hash.digest('base64'); + const digest = Buffer.from(hash.digest('hex').toString('utf8')).toString('base64'); // Construct the WSSE header axiosRequest.headers[ 'X-WSSE' - ] = `UsernameToken Username="${username}", PasswordDigest="${digest}", Created="${ts}", Nonce="${nonce}"`; + ] = `UsernameToken Username="${username}", PasswordDigest="${digest}", Nonce="${nonce}", Created="${ts}"`; } } diff --git a/packages/bruno-electron/src/ipc/network/prepare-request.js b/packages/bruno-electron/src/ipc/network/prepare-request.js index 0bac42af9..93cbed419 100644 --- a/packages/bruno-electron/src/ipc/network/prepare-request.js +++ b/packages/bruno-electron/src/ipc/network/prepare-request.js @@ -224,17 +224,17 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => { const password = get(request, 'auth.wsse.password', ''); const ts = new Date().toISOString(); - const nonce = crypto.randomBytes(16).toString('base64'); + const nonce = crypto.randomBytes(16).toString('hex'); - // Create the password digest using SHA-256 - const hash = crypto.createHash('sha256'); + // Create the password digest using SHA-1 as required for WSSE + const hash = crypto.createHash('sha1'); hash.update(nonce + ts + password); - const digest = hash.digest('base64'); + const digest = Buffer.from(hash.digest('hex').toString('utf8')).toString('base64'); // Construct the WSSE header axiosRequest.headers[ 'X-WSSE' - ] = `UsernameToken Username="${username}", PasswordDigest="${digest}", Created="${ts}", Nonce="${nonce}"`; + ] = `UsernameToken Username="${username}", PasswordDigest="${digest}", Nonce="${nonce}", Created="${ts}"`; break; case 'apikey': const apiKeyAuth = get(collectionAuth, 'apikey'); @@ -318,17 +318,17 @@ const setAuthHeaders = (axiosRequest, request, collectionRoot) => { const password = get(request, 'auth.wsse.password', ''); const ts = new Date().toISOString(); - const nonce = crypto.randomBytes(16).toString('base64'); + const nonce = crypto.randomBytes(16).toString('hex'); - // Create the password digest using SHA-256 - const hash = crypto.createHash('sha256'); + // Create the password digest using SHA-1 as required for WSSE + const hash = crypto.createHash('sha1'); hash.update(nonce + ts + password); - const digest = hash.digest('base64'); + const digest = Buffer.from(hash.digest('hex').toString('utf8')).toString('base64'); // Construct the WSSE header axiosRequest.headers[ 'X-WSSE' - ] = `UsernameToken Username="${username}", PasswordDigest="${digest}", Created="${ts}", Nonce="${nonce}"`; + ] = `UsernameToken Username="${username}", PasswordDigest="${digest}", Nonce="${nonce}", Created="${ts}"`; break; case 'apikey': const apiKeyAuth = get(request, 'auth.apikey'); From 7a5b309664c3b2279cd89b30e437cb72c71351b1 Mon Sep 17 00:00:00 2001 From: Sanjai Kumar <84461672+sanjai0py@users.noreply.github.com> Date: Thu, 3 Oct 2024 23:24:08 +0530 Subject: [PATCH 12/15] refactor: Update color variable in Keybindings component (#3251) --- .../src/components/Preferences/Keybindings/StyledWrapper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bruno-app/src/components/Preferences/Keybindings/StyledWrapper.js b/packages/bruno-app/src/components/Preferences/Keybindings/StyledWrapper.js index e12969388..1a1fe7f01 100644 --- a/packages/bruno-app/src/components/Preferences/Keybindings/StyledWrapper.js +++ b/packages/bruno-app/src/components/Preferences/Keybindings/StyledWrapper.js @@ -34,7 +34,7 @@ const StyledWrapper = styled.div` .key-button { display: inline-block; - color: ${(props) => props.theme.colors.text.white}; + color: ${(props) => props.theme.table.input.color}; border-radius: 4px; padding: 1px 5px; font-family: monospace; From 5c5e3d18fc328ff0f53247623f594759a2db19d8 Mon Sep 17 00:00:00 2001 From: Pragadesh-45 <54320162+Pragadesh-45@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:53:35 +0530 Subject: [PATCH 13/15] add logic to check for key existence in post response (#3249) --- packages/bruno-js/src/runtime/vars-runtime.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/bruno-js/src/runtime/vars-runtime.js b/packages/bruno-js/src/runtime/vars-runtime.js index 1ed806000..94e45f46e 100644 --- a/packages/bruno-js/src/runtime/vars-runtime.js +++ b/packages/bruno-js/src/runtime/vars-runtime.js @@ -50,7 +50,9 @@ class VarsRuntime { _.each(enabledVars, (v) => { try { const value = evaluateJsExpressionBasedOnRuntime(v.value, context, this.runtime); - bru.setVar(v.name, value); + if (v.name) { + bru.setVar(v.name, value); + } } catch (error) { errors.set(v.name, error); } From ce8ebb0c1acd2e50b5869d90650cf222969994ed Mon Sep 17 00:00:00 2001 From: lohit Date: Fri, 4 Oct 2024 16:55:49 +0530 Subject: [PATCH 14/15] fix: no env select issue (#3247) --- .../src/providers/App/useIpcEvents.js | 4 +-- .../ReduxStore/slices/collections/actions.js | 26 ++++++++++--------- packages/bruno-electron/src/ipc/collection.js | 6 ++--- .../src/store/ui-state-snapshot.js | 4 +-- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/packages/bruno-app/src/providers/App/useIpcEvents.js b/packages/bruno-app/src/providers/App/useIpcEvents.js index b885ad74d..c8e022b67 100644 --- a/packages/bruno-app/src/providers/App/useIpcEvents.js +++ b/packages/bruno-app/src/providers/App/useIpcEvents.js @@ -19,7 +19,7 @@ import { runRequestEvent, scriptEnvironmentUpdateEvent } from 'providers/ReduxStore/slices/collections'; -import { collectionAddEnvFileEvent, openCollectionEvent, hydrateCollectionsWithUiStateSnapshot } from 'providers/ReduxStore/slices/collections/actions'; +import { collectionAddEnvFileEvent, openCollectionEvent, hydrateCollectionWithUiStateSnapshot } from 'providers/ReduxStore/slices/collections/actions'; import toast from 'react-hot-toast'; import { useDispatch } from 'react-redux'; import { isElectron } from 'utils/common/platform'; @@ -150,7 +150,7 @@ const useIpcEvents = () => { }); const removeSnapshotHydrationListener = ipcRenderer.on('main:hydrate-app-with-ui-state-snapshot', (val) => { - dispatch(hydrateCollectionsWithUiStateSnapshot(val)); + dispatch(hydrateCollectionWithUiStateSnapshot(val)); }) return () => { 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 e582b0f1f..79635241e 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/actions.js @@ -971,17 +971,19 @@ export const selectEnvironment = (environmentUid, collectionUid) => (dispatch, g } const collectionCopy = cloneDeep(collection); - if (environmentUid) { - const environment = findEnvironmentInCollection(collectionCopy, environmentUid); - if (environment) { - ipcRenderer.invoke('renderer:update-ui-state-snapshot', { type: 'COLLECTION_ENVIRONMENT', data: { collectionPath: collection?.pathname, environmentName: environment?.name } }) - dispatch(_selectEnvironment({ environmentUid, collectionUid })); - resolve(); - } - else { - return reject(new Error('Environment not found')); - } - } + + const environmentName = environmentUid + ? findEnvironmentInCollection(collectionCopy, environmentUid)?.name + : null; + + if (environmentUid && !environmentName) { + return reject(new Error('Environment not found')); + } + + ipcRenderer.invoke('renderer:update-ui-state-snapshot', { type: 'COLLECTION_ENVIRONMENT', data: { collectionPath: collection?.pathname, environmentName }}); + + dispatch(_selectEnvironment({ environmentUid, collectionUid })); + resolve(); }); }; @@ -1146,7 +1148,7 @@ export const saveCollectionSecurityConfig = (collectionUid, securityConfig) => ( }; -export const hydrateCollectionsWithUiStateSnapshot = (payload) => (dispatch, getState) => { +export const hydrateCollectionWithUiStateSnapshot = (payload) => (dispatch, getState) => { const collectionSnapshotData = payload; return new Promise((resolve, reject) => { const state = getState(); diff --git a/packages/bruno-electron/src/ipc/collection.js b/packages/bruno-electron/src/ipc/collection.js index 0aa2058c2..0421060dd 100644 --- a/packages/bruno-electron/src/ipc/collection.js +++ b/packages/bruno-electron/src/ipc/collection.js @@ -25,11 +25,11 @@ const { moveRequestUid, deleteRequestUid } = require('../cache/requestUids'); const { deleteCookiesForDomain, getDomainsWithCookies } = require('../utils/cookies'); const EnvironmentSecretsStore = require('../store/env-secrets'); const CollectionSecurityStore = require('../store/collection-security'); -const UiStateSnapshot = require('../store/ui-state-snapshot'); +const UiStateSnapshotStore = require('../store/ui-state-snapshot'); const environmentSecretsStore = new EnvironmentSecretsStore(); const collectionSecurityStore = new CollectionSecurityStore(); -const UiStateSnapshotStore = new UiStateSnapshot(); +const uiStateSnapshotStore = new UiStateSnapshotStore(); const envHasSecrets = (environment = {}) => { const secrets = _.filter(environment.variables, (v) => v.secret); @@ -700,7 +700,7 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection ipcMain.handle('renderer:update-ui-state-snapshot', (event, { type, data }) => { try { - UiStateSnapshotStore.update({ type, data }); + uiStateSnapshotStore.update({ type, data }); } catch (error) { throw new Error(error.message); } diff --git a/packages/bruno-electron/src/store/ui-state-snapshot.js b/packages/bruno-electron/src/store/ui-state-snapshot.js index b3d1909b6..a130c36de 100644 --- a/packages/bruno-electron/src/store/ui-state-snapshot.js +++ b/packages/bruno-electron/src/store/ui-state-snapshot.js @@ -1,6 +1,6 @@ const Store = require('electron-store'); -class UiStateSnapshot { +class UiStateSnapshotStore { constructor() { this.store = new Store({ name: 'ui-state-snapshot', @@ -57,4 +57,4 @@ class UiStateSnapshot { } } -module.exports = UiStateSnapshot; +module.exports = UiStateSnapshotStore; From 4e8e2e87dc421167da78e9c338530b5cae1caa8b Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Fri, 4 Oct 2024 19:50:45 +0530 Subject: [PATCH 15/15] release: v1.32.1 --- packages/bruno-app/src/components/Sidebar/index.js | 2 +- packages/bruno-app/src/providers/App/useTelemetry.js | 2 +- packages/bruno-electron/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/bruno-app/src/components/Sidebar/index.js b/packages/bruno-app/src/components/Sidebar/index.js index fe02a8ae2..09fd4c5fa 100644 --- a/packages/bruno-app/src/components/Sidebar/index.js +++ b/packages/bruno-app/src/components/Sidebar/index.js @@ -185,7 +185,7 @@ const Sidebar = () => { Star */} -
v1.32.0
+
v1.32.1
diff --git a/packages/bruno-app/src/providers/App/useTelemetry.js b/packages/bruno-app/src/providers/App/useTelemetry.js index 0e709abcb..1087e8508 100644 --- a/packages/bruno-app/src/providers/App/useTelemetry.js +++ b/packages/bruno-app/src/providers/App/useTelemetry.js @@ -60,7 +60,7 @@ const trackStart = () => { event: 'start', properties: { os: platformLib.os.family, - version: '1.32.0' + version: '1.32.1' } }); }; diff --git a/packages/bruno-electron/package.json b/packages/bruno-electron/package.json index d71156a4a..8e2084828 100644 --- a/packages/bruno-electron/package.json +++ b/packages/bruno-electron/package.json @@ -1,5 +1,5 @@ { - "version": "v1.32.0", + "version": "v1.32.1", "name": "bruno", "description": "Opensource API Client for Exploring and Testing APIs", "homepage": "https://www.usebruno.com",