mirror of
https://github.com/usebruno/bruno.git
synced 2026-07-03 09:28:33 +00:00
Compare commits
5 Commits
bugfix/inc
...
v2.12.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
068900866c | ||
|
|
fa5ac0d460 | ||
|
|
c8da13bd9b | ||
|
|
86727c8525 | ||
|
|
901b6daaea |
@@ -193,7 +193,7 @@ const EnvironmentSelector = ({ collection }) => {
|
||||
|
||||
{/* Modals - Rendered outside dropdown to avoid conflicts */}
|
||||
{showGlobalSettings && (
|
||||
<GlobalEnvironmentSettings globalEnvironments={globalEnvironments} onClose={handleCloseSettings} />
|
||||
<GlobalEnvironmentSettings globalEnvironments={globalEnvironments} collection={collection} onClose={handleCloseSettings} />
|
||||
)}
|
||||
|
||||
{showCollectionSettings && <EnvironmentSettings collection={collection} onClose={handleCloseSettings} />}
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useRef, useEffect } from 'react';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import { IconTrash, IconAlertCircle } from '@tabler/icons';
|
||||
import { useTheme } from 'providers/Theme';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import MultiLineEditor from 'components/MultiLineEditor/index';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
import { uuid } from 'utils/common';
|
||||
@@ -12,11 +12,18 @@ import { variableNameRegex } from 'utils/common/regex';
|
||||
import toast from 'react-hot-toast';
|
||||
import { saveGlobalEnvironment } from 'providers/ReduxStore/slices/global-environments';
|
||||
import { Tooltip } from 'react-tooltip';
|
||||
import { getGlobalEnvironmentVariables } from 'utils/collections';
|
||||
|
||||
const EnvironmentVariables = ({ environment, setIsModified, originalEnvironmentVariables }) => {
|
||||
const EnvironmentVariables = ({ environment, setIsModified, originalEnvironmentVariables, collection }) => {
|
||||
const dispatch = useDispatch();
|
||||
const { storedTheme } = useTheme();
|
||||
const addButtonRef = useRef(null);
|
||||
const { globalEnvironments, activeGlobalEnvironmentUid } = useSelector(state => state.globalEnvironments);
|
||||
|
||||
let _collection = cloneDeep(collection);
|
||||
|
||||
const globalEnvironmentVariables = getGlobalEnvironmentVariables({ globalEnvironments, activeGlobalEnvironmentUid });
|
||||
_collection.globalEnvironmentVariables = globalEnvironmentVariables;
|
||||
|
||||
const formik = useFormik({
|
||||
enableReinitialize: true,
|
||||
@@ -93,7 +100,7 @@ const EnvironmentVariables = ({ environment, setIsModified, originalEnvironmentV
|
||||
|
||||
useEffect(() => {
|
||||
if (formik.dirty) {
|
||||
// Smooth scrolling to the changed parameter is temporarily disabled
|
||||
// Smooth scrolling to the changed parameter is temporarily disabled
|
||||
// due to UX issues when editing the first row in a long list of environment variables.
|
||||
// addButtonRef.current?.scrollIntoView({ behavior: 'smooth' });
|
||||
}
|
||||
@@ -149,7 +156,7 @@ const EnvironmentVariables = ({ environment, setIsModified, originalEnvironmentV
|
||||
<div className="overflow-hidden grow w-full relative">
|
||||
<MultiLineEditor
|
||||
theme={storedTheme}
|
||||
collection={{}}
|
||||
collection={_collection}
|
||||
name={`${index}.value`}
|
||||
value={variable.value}
|
||||
isSecret={variable.secret}
|
||||
|
||||
@@ -5,7 +5,7 @@ import DeleteEnvironment from '../../DeleteEnvironment';
|
||||
import RenameEnvironment from '../../RenameEnvironment';
|
||||
import EnvironmentVariables from './EnvironmentVariables';
|
||||
|
||||
const EnvironmentDetails = ({ environment, setIsModified }) => {
|
||||
const EnvironmentDetails = ({ environment, setIsModified, collection }) => {
|
||||
const [openEditModal, setOpenEditModal] = useState(false);
|
||||
const [openDeleteModal, setOpenDeleteModal] = useState(false);
|
||||
const [openCopyModal, setOpenCopyModal] = useState(false);
|
||||
@@ -37,7 +37,7 @@ const EnvironmentDetails = ({ environment, setIsModified }) => {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<EnvironmentVariables environment={environment} setIsModified={setIsModified} />
|
||||
<EnvironmentVariables environment={environment} setIsModified={setIsModified} collection={collection} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -10,7 +10,7 @@ import ImportEnvironment from '../ImportEnvironment';
|
||||
import { isEqual } from 'lodash';
|
||||
import ToolHint from 'components/ToolHint/index';
|
||||
|
||||
const EnvironmentList = ({ environments, activeEnvironmentUid, selectedEnvironment, setSelectedEnvironment, isModified, setIsModified }) => {
|
||||
const EnvironmentList = ({ environments, activeEnvironmentUid, selectedEnvironment, setSelectedEnvironment, isModified, setIsModified, collection }) => {
|
||||
const [openCreateModal, setOpenCreateModal] = useState(false);
|
||||
const [openImportModal, setOpenImportModal] = useState(false);
|
||||
const [openManageSecretsModal, setOpenManageSecretsModal] = useState(false);
|
||||
@@ -143,6 +143,7 @@ const EnvironmentList = ({ environments, activeEnvironmentUid, selectedEnvironme
|
||||
environment={selectedEnvironment}
|
||||
setIsModified={setIsModified}
|
||||
originalEnvironmentVariables={originalEnvironmentVariables}
|
||||
collection={collection}
|
||||
/>
|
||||
</div>
|
||||
</StyledWrapper>
|
||||
|
||||
@@ -39,7 +39,7 @@ const DefaultTab = ({ setTab }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const EnvironmentSettings = ({ globalEnvironments, onClose }) => {
|
||||
const EnvironmentSettings = ({ globalEnvironments, collection, onClose }) => {
|
||||
const [isModified, setIsModified] = useState(false);
|
||||
const environments = globalEnvironments;
|
||||
const [selectedEnvironment, setSelectedEnvironment] = useState(null);
|
||||
@@ -68,6 +68,7 @@ const EnvironmentSettings = ({ globalEnvironments, onClose }) => {
|
||||
setSelectedEnvironment={setSelectedEnvironment}
|
||||
isModified={isModified}
|
||||
setIsModified={setIsModified}
|
||||
collection={collection}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
@@ -73,7 +73,8 @@ const GlobalSearchModal = ({ isOpen, onClose }) => {
|
||||
const itemPathLower = itemPath.toLowerCase();
|
||||
|
||||
if (isItemARequest(item)) {
|
||||
const nameMatch = searchTerms.every(term => item.name.toLowerCase().includes(term));
|
||||
// add an optional check for the item name to prevent a crash if it doesn’t exist.
|
||||
const nameMatch = searchTerms.every(term => (item.name || '').toLowerCase().includes(term));
|
||||
const urlMatch = searchTerms.every(term => (item.request?.url || '').toLowerCase().includes(term));
|
||||
const pathMatch = enablePathMatch && searchTerms.every(term => itemPathLower.includes(term));
|
||||
|
||||
|
||||
@@ -77,11 +77,12 @@ async function onboardUser(mainWindow, lastOpenedCollections) {
|
||||
}
|
||||
|
||||
if (process.env.DISABLE_SAMPLE_COLLECTION_IMPORT !== 'true') {
|
||||
// Onboarding was added later;
|
||||
// if a collection already exists, user is old → skip onboarding
|
||||
// Check if user already has collections (indicates they're an existing user)
|
||||
// Onboarding was added in a later version, so for existing users we should skip it
|
||||
// to avoid creating sample collections
|
||||
const collections = await lastOpenedCollections.getAll();
|
||||
if (collections.length > 0) {
|
||||
preferencesUtil.markAsLaunched();
|
||||
await preferencesUtil.markAsLaunched();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -89,11 +90,11 @@ async function onboardUser(mainWindow, lastOpenedCollections) {
|
||||
await importSampleCollection(collectionLocation, mainWindow, lastOpenedCollections);
|
||||
}
|
||||
|
||||
preferencesUtil.markAsLaunched();
|
||||
await preferencesUtil.markAsLaunched();
|
||||
} catch (error) {
|
||||
console.error('Failed to handle onboarding:', error);
|
||||
// Still mark as launched to prevent retry on next startup
|
||||
preferencesUtil.markAsLaunched();
|
||||
await preferencesUtil.markAsLaunched();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const isDev = require('electron-is-dev');
|
||||
const os = require('os');
|
||||
|
||||
if (isDev) {
|
||||
if(!fs.existsSync(path.join(__dirname, '../../bruno-js/src/sandbox/bundle-browser-rollup.js'))) {
|
||||
@@ -21,6 +22,14 @@ if (isDev && process.env.ELECTRON_USER_DATA_PATH) {
|
||||
app.setPath('userData', process.env.ELECTRON_USER_DATA_PATH);
|
||||
}
|
||||
|
||||
// Command line switches
|
||||
if (os.platform() === 'linux') {
|
||||
// Use portal version 4 that supports current_folder option
|
||||
// to address https://github.com/usebruno/bruno/issues/5471
|
||||
// Runtime sets the default version to 3, refs https://github.com/electron/electron/pull/44426
|
||||
app.commandLine.appendSwitch('xdg-portal-required-version', '4');
|
||||
}
|
||||
|
||||
const menuTemplate = require('./app/menu-template');
|
||||
const { openCollection } = require('./app/collections');
|
||||
const LastOpenedCollections = require('./store/last-opened-collections');
|
||||
|
||||
@@ -34,6 +34,8 @@ const { cookiesStore } = require('../../store/cookies');
|
||||
const registerGrpcEventHandlers = require('./grpc-event-handlers');
|
||||
const { getCertsAndProxyConfig } = require('./cert-utils');
|
||||
|
||||
const ERROR_OCCURRED_WHILE_EXECUTING_REQUEST = 'Error occurred while executing the request!';
|
||||
|
||||
const saveCookies = (url, headers) => {
|
||||
if (preferencesUtil.shouldStoreCookies()) {
|
||||
let setCookieHeaders = [];
|
||||
@@ -674,7 +676,7 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
// timeline prop won't be accessible in the usual way in the renderer process if we reject the promise
|
||||
return {
|
||||
statusText: error.statusText,
|
||||
error: error.message || 'Error occured while executing the request!',
|
||||
error: error.message || ERROR_OCCURRED_WHILE_EXECUTING_REQUEST,
|
||||
timeline: error.timeline
|
||||
}
|
||||
}
|
||||
@@ -853,7 +855,7 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
// timeline prop won't be accessible in the usual way in the renderer process if we reject the promise
|
||||
return {
|
||||
status: error?.status,
|
||||
error: error?.message || 'Error occured while executing the request!',
|
||||
error: error?.message || ERROR_OCCURRED_WHILE_EXECUTING_REQUEST,
|
||||
timeline: error?.timeline
|
||||
};
|
||||
}
|
||||
@@ -1497,7 +1499,7 @@ const executeRequestOnFailHandler = async (request, error) => {
|
||||
} catch (handlerError) {
|
||||
console.error('Error executing onFail handler', handlerError);
|
||||
// @TODO: This is a temporary solution to display the error message in the response pane. Revisit and handle properly.
|
||||
error.message = `1. Request failed: ${error.message || 'Error occured while executing the request!'}\n2. Error executing onFail handler: ${handlerError.message || 'Unknown error'}`;
|
||||
error.message = `1. Request failed: ${error.message || ERROR_OCCURRED_WHILE_EXECUTING_REQUEST}\n2. Error executing onFail handler: ${handlerError.message || 'Unknown error'}`;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -186,10 +186,15 @@ const preferencesUtil = {
|
||||
hasLaunchedBefore: () => {
|
||||
return get(getPreferences(), 'onboarding.hasLaunchedBefore', false);
|
||||
},
|
||||
markAsLaunched: () => {
|
||||
markAsLaunched: async () => {
|
||||
const preferences = getPreferences();
|
||||
preferences.onboarding.hasLaunchedBefore = true;
|
||||
preferencesStore.savePreferences(preferences);
|
||||
|
||||
try {
|
||||
await savePreferences(preferences);
|
||||
} catch (err) {
|
||||
console.error('Failed to save preferences in markAsLaunched:', err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user