feat: ui-state-snapshot (#3215)

* wip: save env

* feat: updates

* feat: updates
This commit is contained in:
lohit 2024-09-30 16:51:49 +05:30 committed by GitHub
parent f35b715c6f
commit d448599a53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 126 additions and 5 deletions

View File

@ -19,7 +19,7 @@ import {
runRequestEvent, runRequestEvent,
scriptEnvironmentUpdateEvent scriptEnvironmentUpdateEvent
} from 'providers/ReduxStore/slices/collections'; } 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 toast from 'react-hot-toast';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { isElectron } from 'utils/common/platform'; import { isElectron } from 'utils/common/platform';
@ -149,6 +149,10 @@ const useIpcEvents = () => {
dispatch(updateCookies(val)); dispatch(updateCookies(val));
}); });
const removeSnapshotHydrationListener = ipcRenderer.on('main:hydrate-app-with-ui-state-snapshot', (val) => {
dispatch(hydrateCollectionsWithUiStateSnapshot(val));
})
return () => { return () => {
removeCollectionTreeUpdateListener(); removeCollectionTreeUpdateListener();
removeOpenCollectionListener(); removeOpenCollectionListener();
@ -165,6 +169,7 @@ const useIpcEvents = () => {
removePreferencesUpdatesListener(); removePreferencesUpdatesListener();
removeCookieUpdateListener(); removeCookieUpdateListener();
removeSystemProxyEnvUpdatesListener(); removeSystemProxyEnvUpdatesListener();
removeSnapshotHydrationListener();
}; };
}, [isElectron]); }, [isElectron]);
}; };

View File

@ -44,6 +44,7 @@ import { parsePathParams, parseQueryParams, splitOnFirst } from 'utils/url/index
import { sendCollectionOauth2Request as _sendCollectionOauth2Request } from 'utils/network/index'; import { sendCollectionOauth2Request as _sendCollectionOauth2Request } from 'utils/network/index';
import { name } from 'file-loader'; import { name } from 'file-loader';
import slash from 'utils/common/slash'; import slash from 'utils/common/slash';
import { findCollectionByPathname, findEnvironmentInCollectionByName } from 'utils/collections/index';
export const renameCollection = (newName, collectionUid) => (dispatch, getState) => { export const renameCollection = (newName, collectionUid) => (dispatch, getState) => {
const state = getState(); const state = getState();
@ -972,13 +973,15 @@ export const selectEnvironment = (environmentUid, collectionUid) => (dispatch, g
const collectionCopy = cloneDeep(collection); const collectionCopy = cloneDeep(collection);
if (environmentUid) { if (environmentUid) {
const environment = findEnvironmentInCollection(collectionCopy, 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')); return reject(new Error('Environment not found'));
} }
} }
dispatch(_selectEnvironment({ environmentUid, collectionUid }));
resolve();
}); });
}; };
@ -1141,3 +1144,33 @@ export const saveCollectionSecurityConfig = (collectionUid, securityConfig) => (
.catch(reject); .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);
}
});
};

View File

@ -132,6 +132,10 @@ export const findEnvironmentInCollection = (collection, envUid) => {
return find(collection.environments, (e) => e.uid === 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) => { export const moveCollectionItem = (collection, draggedItem, targetItem) => {
let draggedItemParent = findParentItemInCollection(collection, draggedItem.uid); let draggedItemParent = findParentItemInCollection(collection, draggedItem.uid);

View File

@ -12,6 +12,7 @@ const { decryptString } = require('../utils/encryption');
const { setDotEnvVars } = require('../store/process-env'); const { setDotEnvVars } = require('../store/process-env');
const { setBrunoConfig } = require('../store/bruno-config'); const { setBrunoConfig } = require('../store/bruno-config');
const EnvironmentSecretsStore = require('../store/env-secrets'); const EnvironmentSecretsStore = require('../store/env-secrets');
const UiStateSnapshot = require('../store/ui-state-snapshot');
const environmentSecretsStore = new EnvironmentSecretsStore(); const environmentSecretsStore = new EnvironmentSecretsStore();
@ -421,6 +422,13 @@ const unlinkDir = (win, pathname, collectionUid, collectionPath) => {
win.webContents.send('main:collection-tree-updated', 'unlinkDir', directory); 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 { class Watcher {
constructor() { constructor() {
this.watchers = {}; this.watchers = {};
@ -456,6 +464,7 @@ class Watcher {
let startedNewWatcher = false; let startedNewWatcher = false;
watcher watcher
.on('ready', () => onWatcherSetupComplete(win, watchPath))
.on('add', (pathname) => add(win, pathname, collectionUid, watchPath)) .on('add', (pathname) => add(win, pathname, collectionUid, watchPath))
.on('addDir', (pathname) => addDirectory(win, pathname, collectionUid, watchPath)) .on('addDir', (pathname) => addDirectory(win, pathname, collectionUid, watchPath))
.on('change', (pathname) => change(win, pathname, collectionUid, watchPath)) .on('change', (pathname) => change(win, pathname, collectionUid, watchPath))

View File

@ -25,9 +25,11 @@ const { moveRequestUid, deleteRequestUid } = require('../cache/requestUids');
const { deleteCookiesForDomain, getDomainsWithCookies } = require('../utils/cookies'); const { deleteCookiesForDomain, getDomainsWithCookies } = require('../utils/cookies');
const EnvironmentSecretsStore = require('../store/env-secrets'); const EnvironmentSecretsStore = require('../store/env-secrets');
const CollectionSecurityStore = require('../store/collection-security'); const CollectionSecurityStore = require('../store/collection-security');
const UiStateSnapshot = require('../store/ui-state-snapshot');
const environmentSecretsStore = new EnvironmentSecretsStore(); const environmentSecretsStore = new EnvironmentSecretsStore();
const collectionSecurityStore = new CollectionSecurityStore(); const collectionSecurityStore = new CollectionSecurityStore();
const UiStateSnapshotStore = new UiStateSnapshot();
const envHasSecrets = (environment = {}) => { const envHasSecrets = (environment = {}) => {
const secrets = _.filter(environment.variables, (v) => v.secret); const secrets = _.filter(environment.variables, (v) => v.secret);
@ -695,6 +697,14 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection
return Promise.reject(error); 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) => { const registerMainEventHandlers = (mainWindow, watcher, lastOpenedCollections) => {

View File

@ -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;