From 0f0580888656d3aa2cbc1b9716bd1eb9dccc6c0c Mon Sep 17 00:00:00 2001 From: lohit-bruno Date: Tue, 3 Mar 2026 09:30:21 +0530 Subject: [PATCH] feat(ui): add Cache tab to Preferences --- .../Preferences/Cache/StyledWrapper.js | 13 ++ .../src/components/Preferences/Cache/index.js | 118 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 packages/bruno-app/src/components/Preferences/Cache/StyledWrapper.js create mode 100644 packages/bruno-app/src/components/Preferences/Cache/index.js diff --git a/packages/bruno-app/src/components/Preferences/Cache/StyledWrapper.js b/packages/bruno-app/src/components/Preferences/Cache/StyledWrapper.js new file mode 100644 index 000000000..f19772f57 --- /dev/null +++ b/packages/bruno-app/src/components/Preferences/Cache/StyledWrapper.js @@ -0,0 +1,13 @@ +import styled from 'styled-components'; + +const StyledWrapper = styled.div` + color: ${(props) => props.theme.text}; + + form.bruno-form { + label { + font-size: 0.8125rem; + } + } +`; + +export default StyledWrapper; diff --git a/packages/bruno-app/src/components/Preferences/Cache/index.js b/packages/bruno-app/src/components/Preferences/Cache/index.js new file mode 100644 index 000000000..57e1ae49f --- /dev/null +++ b/packages/bruno-app/src/components/Preferences/Cache/index.js @@ -0,0 +1,118 @@ +import React, { useEffect, useCallback } from 'react'; +import { useFormik } from 'formik'; +import { useSelector, useDispatch } from 'react-redux'; +import { savePreferences } from 'providers/ReduxStore/slices/app'; +import toast from 'react-hot-toast'; +import StyledWrapper from './StyledWrapper'; +import * as Yup from 'yup'; +import debounce from 'lodash/debounce'; +import get from 'lodash/get'; + +const cacheSchema = Yup.object().shape({ + httpHttpsAgents: Yup.object({ + enabled: Yup.boolean() + }) +}); + +const Cache = () => { + const preferences = useSelector((state) => state.app.preferences); + const dispatch = useDispatch(); + + const formik = useFormik({ + initialValues: { + httpHttpsAgents: { + enabled: get(preferences, 'cache.httpHttpsAgents.enabled', true) + } + }, + validationSchema: cacheSchema, + onSubmit: async (values) => { + try { + const newPreferences = await cacheSchema.validate(values, { abortEarly: true }); + handleSave(newPreferences); + } catch (error) { + console.error('Cache preferences validation error:', error.message); + } + } + }); + + const handleSave = useCallback( + (newCachePreferences) => { + dispatch( + savePreferences({ + ...preferences, + cache: newCachePreferences + }) + ).catch(() => toast.error('Failed to update cache preferences')); + }, + [dispatch, preferences] + ); + + const debouncedSave = useCallback( + debounce((values) => { + cacheSchema + .validate(values, { abortEarly: true }) + .then((validatedValues) => handleSave(validatedValues)) + .catch(() => {}); + }, 500), + [handleSave] + ); + + useEffect(() => { + if (formik.dirty && formik.isValid) { + debouncedSave(formik.values); + } + return () => { + debouncedSave.cancel(); + }; + }, [formik.values, formik.dirty, formik.isValid, debouncedSave]); + + const handleAgentCachingChange = (e) => { + formik.handleChange(e); + // Immediately evict all cached agents when caching is disabled + if (!e.target.checked) { + window.ipcRenderer.invoke('renderer:clear-http-https-agent-cache').catch(() => {}); + } + }; + + const handleResetCache = () => { + window.ipcRenderer + .invoke('renderer:clear-http-https-agent-cache') + .then(() => toast.success('Agent cache cleared')) + .catch(() => toast.error('Failed to clear agent cache')); + }; + + return ( + +
+
HTTP and HTTPS Agents Cache
+ +
+ + +
+
+ Reuses TLS sessions and connections across requests for better performance. Disable to create a fresh agent + for every request. +
+ +
+ +
Destroys all cached agents and their connections.
+
+
+
+ ); +}; + +export default Cache;