From 289625c851fb3002351e50050687c0904ad1d8ba Mon Sep 17 00:00:00 2001 From: Qweme Dev <99718350+qweme32@users.noreply.github.com> Date: Fri, 6 Oct 2023 17:53:05 +0300 Subject: [PATCH 1/4] Added a setting that allows you to change the font of the code --- .../components/CodeEditor/StyledWrapper.js | 1 + .../src/components/CodeEditor/index.js | 1 + .../Preferences/Font/StyledWrapper.js | 7 ++++ .../src/components/Preferences/Font/index.js | 33 +++++++++++++++++++ .../src/components/Preferences/index.js | 8 +++++ .../RequestPane/GraphQLVariables/index.js | 3 ++ .../RequestPane/RequestBody/index.js | 3 ++ .../components/RequestPane/Script/index.js | 4 +++ .../src/components/RequestPane/Tests/index.js | 3 ++ .../ResponsePane/QueryResult/index.js | 4 ++- .../GenerateCodeItem/CodeView/index.js | 4 ++- 11 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 packages/bruno-app/src/components/Preferences/Font/StyledWrapper.js create mode 100644 packages/bruno-app/src/components/Preferences/Font/index.js diff --git a/packages/bruno-app/src/components/CodeEditor/StyledWrapper.js b/packages/bruno-app/src/components/CodeEditor/StyledWrapper.js index 09de00ddc2..9853280a16 100644 --- a/packages/bruno-app/src/components/CodeEditor/StyledWrapper.js +++ b/packages/bruno-app/src/components/CodeEditor/StyledWrapper.js @@ -4,6 +4,7 @@ const StyledWrapper = styled.div` div.CodeMirror { background: ${(props) => props.theme.codemirror.bg}; border: solid 1px ${(props) => props.theme.codemirror.border}; + font-family: ${(props) => props.font ? props.font : "default"}; } .CodeMirror-overlayscroll-horizontal div, diff --git a/packages/bruno-app/src/components/CodeEditor/index.js b/packages/bruno-app/src/components/CodeEditor/index.js index 96d5bb48a8..6ad999e6ba 100644 --- a/packages/bruno-app/src/components/CodeEditor/index.js +++ b/packages/bruno-app/src/components/CodeEditor/index.js @@ -121,6 +121,7 @@ export default class CodeEditor extends React.Component { { this._node = node; }} diff --git a/packages/bruno-app/src/components/Preferences/Font/StyledWrapper.js b/packages/bruno-app/src/components/Preferences/Font/StyledWrapper.js new file mode 100644 index 0000000000..d45eda5b68 --- /dev/null +++ b/packages/bruno-app/src/components/Preferences/Font/StyledWrapper.js @@ -0,0 +1,7 @@ +import styled from 'styled-components'; + +const StyledWrapper = styled.div` + color: ${(props) => props.theme.text}; +`; + +export default StyledWrapper; diff --git a/packages/bruno-app/src/components/Preferences/Font/index.js b/packages/bruno-app/src/components/Preferences/Font/index.js new file mode 100644 index 0000000000..4694aaf698 --- /dev/null +++ b/packages/bruno-app/src/components/Preferences/Font/index.js @@ -0,0 +1,33 @@ +import React, { useState } from 'react'; +import { usePreferences } from 'providers/Preferences'; +import StyledWrapper from './StyledWrapper'; + +const Font = () => { + const { preferences, setPreferences } = usePreferences(); + + const [codeFont, setCodeFont] = useState(preferences.codeFont); + + const handleInputChange = (event) => { + const updatedPreferences = { + ...preferences, + codeFont: event.target.value + }; + + setPreferences(updatedPreferences) + .then(() => { + setCodeFont(event.target.value); + }) + .catch((err) => { + console.error(err); + }); + }; + + return ( + +

Font in code area

+ +
+ ); +}; + +export default Font; diff --git a/packages/bruno-app/src/components/Preferences/index.js b/packages/bruno-app/src/components/Preferences/index.js index 455a6748fb..a48f5e66e8 100644 --- a/packages/bruno-app/src/components/Preferences/index.js +++ b/packages/bruno-app/src/components/Preferences/index.js @@ -3,6 +3,7 @@ import classnames from 'classnames'; import React, { useState } from 'react'; import Support from './Support'; import General from './General'; +import Font from './Font'; import Theme from './Theme'; import StyledWrapper from './StyledWrapper'; @@ -28,6 +29,10 @@ const Preferences = ({ onClose }) => { case 'support': { return ; } + + case 'font': { + return ; + } } }; @@ -41,6 +46,9 @@ const Preferences = ({ onClose }) => {
setTab('theme')}> Theme
+
setTab('font')}> + Font +
setTab('support')}> Support
diff --git a/packages/bruno-app/src/components/RequestPane/GraphQLVariables/index.js b/packages/bruno-app/src/components/RequestPane/GraphQLVariables/index.js index 59b1320447..0e213442bd 100644 --- a/packages/bruno-app/src/components/RequestPane/GraphQLVariables/index.js +++ b/packages/bruno-app/src/components/RequestPane/GraphQLVariables/index.js @@ -4,12 +4,14 @@ import CodeEditor from 'components/CodeEditor'; import { updateRequestGraphqlVariables } from 'providers/ReduxStore/slices/collections'; import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import { useTheme } from 'providers/Theme'; +import { usePreferences } from 'providers/Preferences'; import StyledWrapper from './StyledWrapper'; const GraphQLVariables = ({ variables, item, collection }) => { const dispatch = useDispatch(); const { storedTheme } = useTheme(); + const { preferences } = usePreferences(); const onEdit = (value) => { dispatch( @@ -30,6 +32,7 @@ const GraphQLVariables = ({ variables, item, collection }) => { collection={collection} value={variables || ''} theme={storedTheme} + font={preferences.codeFont} onEdit={onEdit} mode="javascript" onRun={onRun} diff --git a/packages/bruno-app/src/components/RequestPane/RequestBody/index.js b/packages/bruno-app/src/components/RequestPane/RequestBody/index.js index 7ac178f795..fa004d1dcd 100644 --- a/packages/bruno-app/src/components/RequestPane/RequestBody/index.js +++ b/packages/bruno-app/src/components/RequestPane/RequestBody/index.js @@ -5,6 +5,7 @@ import FormUrlEncodedParams from 'components/RequestPane/FormUrlEncodedParams'; import MultipartFormParams from 'components/RequestPane/MultipartFormParams'; import { useDispatch } from 'react-redux'; import { useTheme } from 'providers/Theme'; +import { usePreferences } from 'providers/Preferences'; import { updateRequestBody } from 'providers/ReduxStore/slices/collections'; import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import StyledWrapper from './StyledWrapper'; @@ -14,6 +15,7 @@ const RequestBody = ({ item, collection }) => { const body = item.draft ? get(item, 'draft.request.body') : get(item, 'request.body'); const bodyMode = item.draft ? get(item, 'draft.request.body.mode') : get(item, 'request.body.mode'); const { storedTheme } = useTheme(); + const { preferences } = usePreferences(); const onEdit = (value) => { dispatch( @@ -46,6 +48,7 @@ const RequestBody = ({ item, collection }) => { { @@ -13,6 +14,7 @@ const Script = ({ item, collection }) => { const responseScript = item.draft ? get(item, 'draft.request.script.res') : get(item, 'request.script.res'); const { storedTheme } = useTheme(); + const { preferences } = usePreferences(); const onRequestScriptEdit = (value) => { dispatch( @@ -45,6 +47,7 @@ const Script = ({ item, collection }) => { collection={collection} value={requestScript || ''} theme={storedTheme} + font={preferences.codeFont} onEdit={onRequestScriptEdit} mode="javascript" onRun={onRun} @@ -57,6 +60,7 @@ const Script = ({ item, collection }) => { collection={collection} value={responseScript || ''} theme={storedTheme} + font={preferences.codeFont} onEdit={onResponseScriptEdit} mode="javascript" onRun={onRun} diff --git a/packages/bruno-app/src/components/RequestPane/Tests/index.js b/packages/bruno-app/src/components/RequestPane/Tests/index.js index 351afd3d32..dce6547f68 100644 --- a/packages/bruno-app/src/components/RequestPane/Tests/index.js +++ b/packages/bruno-app/src/components/RequestPane/Tests/index.js @@ -5,6 +5,7 @@ import CodeEditor from 'components/CodeEditor'; import { updateRequestTests } from 'providers/ReduxStore/slices/collections'; import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import { useTheme } from 'providers/Theme'; +import { usePreferences } from 'providers/Preferences'; import StyledWrapper from './StyledWrapper'; const Tests = ({ item, collection }) => { @@ -12,6 +13,7 @@ const Tests = ({ item, collection }) => { const tests = item.draft ? get(item, 'draft.request.tests') : get(item, 'request.tests'); const { storedTheme } = useTheme(); + const { preferences } = usePreferences(); const onEdit = (value) => { dispatch( @@ -32,6 +34,7 @@ const Tests = ({ item, collection }) => { collection={collection} value={tests || ''} theme={storedTheme} + font={preferences.codeFont} onEdit={onEdit} mode="javascript" onRun={onRun} diff --git a/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js b/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js index 5729e0b2dd..28a1a0af52 100644 --- a/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js +++ b/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js @@ -1,6 +1,7 @@ import React from 'react'; import CodeEditor from 'components/CodeEditor'; import { useTheme } from 'providers/Theme'; +import { usePreferences } from 'providers/Preferences'; import { useDispatch } from 'react-redux'; import { sendRequest } from 'providers/ReduxStore/slices/collections/actions'; import classnames from 'classnames'; @@ -13,6 +14,7 @@ import { useMemo } from 'react'; const QueryResult = ({ item, collection, data, width, disableRunEventListener, headers }) => { const { storedTheme } = useTheme(); + const { preferences } = usePreferences(); const [tab, setTab] = useState('preview'); const dispatch = useDispatch(); const contentType = getContentType(headers); @@ -99,7 +101,7 @@ const QueryResult = ({ item, collection, data, width, disableRunEventListener, h ); } - return ; + return ; }, [tab, collection, storedTheme, onRun, value, mode]); return ( diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/CodeView/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/CodeView/index.js index 79d636dafb..f3223bab4d 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/CodeView/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/CodeView/index.js @@ -1,10 +1,12 @@ import CodeEditor from 'components/CodeEditor/index'; import { HTTPSnippet } from 'httpsnippet'; import { useTheme } from 'providers/Theme/index'; +import { usePreferences } from 'providers/Preferences/index'; import { buildHarRequest } from 'utils/codegenerator/har'; const CodeView = ({ language, item }) => { const { storedTheme } = useTheme(); + const { preferences } = usePreferences(); const { target, client, language: lang } = language; let snippet = ''; @@ -15,7 +17,7 @@ const CodeView = ({ language, item }) => { snippet = 'Error generating code snippet'; } - return ; + return ; }; export default CodeView; From 1a366893ec6cee0f0cecba0eaf67294a5e6191e1 Mon Sep 17 00:00:00 2001 From: Qweme Dev <99718350+qweme32@users.noreply.github.com> Date: Sun, 8 Oct 2023 21:53:29 +0300 Subject: [PATCH 2/4] Fix styles for theme --- .../Preferences/Font/StyledWrapper.js | 20 +++++++++++++++++++ .../src/components/Preferences/Font/index.js | 4 +++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/bruno-app/src/components/Preferences/Font/StyledWrapper.js b/packages/bruno-app/src/components/Preferences/Font/StyledWrapper.js index d45eda5b68..5bd4e46932 100644 --- a/packages/bruno-app/src/components/Preferences/Font/StyledWrapper.js +++ b/packages/bruno-app/src/components/Preferences/Font/StyledWrapper.js @@ -2,6 +2,26 @@ import styled from 'styled-components'; const StyledWrapper = styled.div` color: ${(props) => props.theme.text}; + div.input-container { + background-color: ${(props) => props.theme.modal.input.bg}; + height: 2.3rem; + } + div.input-container { + border: solid 1px ${(props) => props.theme.modal.input.border}; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + + input { + background-color: ${(props) => props.theme.modal.input.bg}; + outline: none; + box-shadow: none; + + &:focus { + outline: none !important; + box-shadow: none !important; + } + } + } `; export default StyledWrapper; diff --git a/packages/bruno-app/src/components/Preferences/Font/index.js b/packages/bruno-app/src/components/Preferences/Font/index.js index 4694aaf698..4505b5958a 100644 --- a/packages/bruno-app/src/components/Preferences/Font/index.js +++ b/packages/bruno-app/src/components/Preferences/Font/index.js @@ -25,7 +25,9 @@ const Font = () => { return (

Font in code area

- +
+ +
); }; From 7bf049a1f0994546291b0972cdeb85ff077309f5 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sun, 15 Oct 2023 15:59:57 +0530 Subject: [PATCH 3/4] feat: use electron-store for saving preferences --- .../Preferences/Font/StyledWrapper.js | 20 ---- .../src/components/Preferences/Font/index.js | 56 ++++++++---- .../components/Preferences/General/index.js | 51 +++++++---- .../src/components/Preferences/index.js | 6 +- .../RequestPane/GraphQLVariables/index.js | 8 +- .../RequestPane/RequestBody/index.js | 7 +- .../components/RequestPane/Script/index.js | 9 +- .../src/components/RequestPane/Tests/index.js | 7 +- .../ResponsePane/QueryResult/index.js | 18 +++- .../GenerateCodeItem/CodeView/index.js | 15 ++- packages/bruno-app/src/pages/_app.js | 9 +- packages/bruno-app/src/providers/App/index.js | 4 +- ...eCollectionTreeSync.js => useIpcEvents.js} | 91 ++++++++++--------- .../src/providers/Preferences/index.js | 77 ---------------- .../src/providers/ReduxStore/slices/app.js | 34 ++++++- .../ReduxStore/slices/collections/index.js | 1 - packages/bruno-electron/src/index.js | 6 +- packages/bruno-electron/src/ipc/collection.js | 22 +---- .../bruno-electron/src/ipc/preferences.js | 35 +++++++ .../bruno-electron/src/store/preferences.js | 73 +++++++++++---- .../bruno-electron/src/store/window-state.js | 1 - 21 files changed, 291 insertions(+), 259 deletions(-) rename packages/bruno-app/src/providers/App/{useCollectionTreeSync.js => useIpcEvents.js} (57%) delete mode 100644 packages/bruno-app/src/providers/Preferences/index.js create mode 100644 packages/bruno-electron/src/ipc/preferences.js diff --git a/packages/bruno-app/src/components/Preferences/Font/StyledWrapper.js b/packages/bruno-app/src/components/Preferences/Font/StyledWrapper.js index 5bd4e46932..d45eda5b68 100644 --- a/packages/bruno-app/src/components/Preferences/Font/StyledWrapper.js +++ b/packages/bruno-app/src/components/Preferences/Font/StyledWrapper.js @@ -2,26 +2,6 @@ import styled from 'styled-components'; const StyledWrapper = styled.div` color: ${(props) => props.theme.text}; - div.input-container { - background-color: ${(props) => props.theme.modal.input.bg}; - height: 2.3rem; - } - div.input-container { - border: solid 1px ${(props) => props.theme.modal.input.border}; - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; - - input { - background-color: ${(props) => props.theme.modal.input.bg}; - outline: none; - box-shadow: none; - - &:focus { - outline: none !important; - box-shadow: none !important; - } - } - } `; export default StyledWrapper; diff --git a/packages/bruno-app/src/components/Preferences/Font/index.js b/packages/bruno-app/src/components/Preferences/Font/index.js index 4505b5958a..bae23e7232 100644 --- a/packages/bruno-app/src/components/Preferences/Font/index.js +++ b/packages/bruno-app/src/components/Preferences/Font/index.js @@ -1,32 +1,52 @@ import React, { useState } from 'react'; -import { usePreferences } from 'providers/Preferences'; +import get from 'lodash/get'; +import { useSelector, useDispatch } from 'react-redux'; +import { savePreferences } from 'providers/ReduxStore/slices/app'; import StyledWrapper from './StyledWrapper'; -const Font = () => { - const { preferences, setPreferences } = usePreferences(); +const Font = ({ close }) => { + const dispatch = useDispatch(); + const preferences = useSelector((state) => state.app.preferences); - const [codeFont, setCodeFont] = useState(preferences.codeFont); + const [codeFont, setCodeFont] = useState(get(preferences, 'font.codeFont', 'default')); const handleInputChange = (event) => { - const updatedPreferences = { - ...preferences, - codeFont: event.target.value - }; + setCodeFont(event.target.value); + }; - setPreferences(updatedPreferences) - .then(() => { - setCodeFont(event.target.value); + const handleSave = () => { + dispatch( + savePreferences({ + ...preferences, + font: { + codeFont + } }) - .catch((err) => { - console.error(err); - }); + ).then(() => { + close(); + }); }; - return ( + return ( -

Font in code area

-
- + +
+ +
+ +
+
); diff --git a/packages/bruno-app/src/components/Preferences/General/index.js b/packages/bruno-app/src/components/Preferences/General/index.js index 637c483e5f..a622dd6b6e 100644 --- a/packages/bruno-app/src/components/Preferences/General/index.js +++ b/packages/bruno-app/src/components/Preferences/General/index.js @@ -1,35 +1,46 @@ import React, { useState } from 'react'; -import { usePreferences } from 'providers/Preferences'; +import { useSelector, useDispatch } from 'react-redux'; +import { savePreferences } from 'providers/ReduxStore/slices/app'; import StyledWrapper from './StyledWrapper'; -const General = () => { - const { preferences, setPreferences } = usePreferences(); +const General = ({ close }) => { + const preferences = useSelector((state) => state.app.preferences); + const dispatch = useDispatch(); const [sslVerification, setSslVerification] = useState(preferences.request.sslVerification); - const handleCheckboxChange = () => { - const updatedPreferences = { - ...preferences, - request: { - ...preferences.request, - sslVerification: !sslVerification - } - }; - - setPreferences(updatedPreferences) - .then(() => { - setSslVerification(!sslVerification); + const handleSave = () => { + dispatch( + savePreferences({ + ...preferences, + request: { + sslVerification + } }) - .catch((err) => { - console.error(err); - }); + ).then(() => { + close(); + }); }; return (
- - SSL Certificate Verification + setSslVerification(!sslVerification)} + className="mr-3 mousetrap" + /> + +
+ +
+
); diff --git a/packages/bruno-app/src/components/Preferences/index.js b/packages/bruno-app/src/components/Preferences/index.js index a48f5e66e8..217b3c57a0 100644 --- a/packages/bruno-app/src/components/Preferences/index.js +++ b/packages/bruno-app/src/components/Preferences/index.js @@ -19,11 +19,11 @@ const Preferences = ({ onClose }) => { const getTabPanel = (tab) => { switch (tab) { case 'general': { - return ; + return ; } case 'theme': { - return ; + return ; } case 'support': { @@ -31,7 +31,7 @@ const Preferences = ({ onClose }) => { } case 'font': { - return ; + return ; } } }; diff --git a/packages/bruno-app/src/components/RequestPane/GraphQLVariables/index.js b/packages/bruno-app/src/components/RequestPane/GraphQLVariables/index.js index 0e213442bd..0d913d97f8 100644 --- a/packages/bruno-app/src/components/RequestPane/GraphQLVariables/index.js +++ b/packages/bruno-app/src/components/RequestPane/GraphQLVariables/index.js @@ -1,17 +1,17 @@ import React from 'react'; -import { useDispatch } from 'react-redux'; +import get from 'lodash/get'; +import { useDispatch, useSelector } from 'react-redux'; import CodeEditor from 'components/CodeEditor'; import { updateRequestGraphqlVariables } from 'providers/ReduxStore/slices/collections'; import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import { useTheme } from 'providers/Theme'; -import { usePreferences } from 'providers/Preferences'; import StyledWrapper from './StyledWrapper'; const GraphQLVariables = ({ variables, item, collection }) => { const dispatch = useDispatch(); const { storedTheme } = useTheme(); - const { preferences } = usePreferences(); + const preferences = useSelector((state) => state.app.preferences); const onEdit = (value) => { dispatch( @@ -32,7 +32,7 @@ const GraphQLVariables = ({ variables, item, collection }) => { collection={collection} value={variables || ''} theme={storedTheme} - font={preferences.codeFont} + font={get(preferences, 'font.codeFont', 'default')} onEdit={onEdit} mode="javascript" onRun={onRun} diff --git a/packages/bruno-app/src/components/RequestPane/RequestBody/index.js b/packages/bruno-app/src/components/RequestPane/RequestBody/index.js index 70ab1e8404..9daaf37f14 100644 --- a/packages/bruno-app/src/components/RequestPane/RequestBody/index.js +++ b/packages/bruno-app/src/components/RequestPane/RequestBody/index.js @@ -3,9 +3,8 @@ import get from 'lodash/get'; import CodeEditor from 'components/CodeEditor'; import FormUrlEncodedParams from 'components/RequestPane/FormUrlEncodedParams'; import MultipartFormParams from 'components/RequestPane/MultipartFormParams'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { useTheme } from 'providers/Theme'; -import { usePreferences } from 'providers/Preferences'; import { updateRequestBody } from 'providers/ReduxStore/slices/collections'; import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import StyledWrapper from './StyledWrapper'; @@ -15,7 +14,7 @@ const RequestBody = ({ item, collection }) => { const body = item.draft ? get(item, 'draft.request.body') : get(item, 'request.body'); const bodyMode = item.draft ? get(item, 'draft.request.body.mode') : get(item, 'request.body.mode'); const { storedTheme } = useTheme(); - const { preferences } = usePreferences(); + const preferences = useSelector((state) => state.app.preferences); const onEdit = (value) => { dispatch( @@ -50,7 +49,7 @@ const RequestBody = ({ item, collection }) => { { @@ -14,7 +13,7 @@ const Script = ({ item, collection }) => { const responseScript = item.draft ? get(item, 'draft.request.script.res') : get(item, 'request.script.res'); const { storedTheme } = useTheme(); - const { preferences } = usePreferences(); + const preferences = useSelector((state) => state.app.preferences); const onRequestScriptEdit = (value) => { dispatch( @@ -47,7 +46,7 @@ const Script = ({ item, collection }) => { collection={collection} value={requestScript || ''} theme={storedTheme} - font={preferences.codeFont} + font={get(preferences, 'font.codeFont', 'default')} onEdit={onRequestScriptEdit} mode="javascript" onRun={onRun} @@ -60,7 +59,7 @@ const Script = ({ item, collection }) => { collection={collection} value={responseScript || ''} theme={storedTheme} - font={preferences.codeFont} + font={get(preferences, 'font.codeFont', 'default')} onEdit={onResponseScriptEdit} mode="javascript" onRun={onRun} diff --git a/packages/bruno-app/src/components/RequestPane/Tests/index.js b/packages/bruno-app/src/components/RequestPane/Tests/index.js index dce6547f68..66645509aa 100644 --- a/packages/bruno-app/src/components/RequestPane/Tests/index.js +++ b/packages/bruno-app/src/components/RequestPane/Tests/index.js @@ -1,11 +1,10 @@ import React from 'react'; import get from 'lodash/get'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import CodeEditor from 'components/CodeEditor'; import { updateRequestTests } from 'providers/ReduxStore/slices/collections'; import { sendRequest, saveRequest } from 'providers/ReduxStore/slices/collections/actions'; import { useTheme } from 'providers/Theme'; -import { usePreferences } from 'providers/Preferences'; import StyledWrapper from './StyledWrapper'; const Tests = ({ item, collection }) => { @@ -13,7 +12,7 @@ const Tests = ({ item, collection }) => { const tests = item.draft ? get(item, 'draft.request.tests') : get(item, 'request.tests'); const { storedTheme } = useTheme(); - const { preferences } = usePreferences(); + const preferences = useSelector((state) => state.app.preferences); const onEdit = (value) => { dispatch( @@ -34,7 +33,7 @@ const Tests = ({ item, collection }) => { collection={collection} value={tests || ''} theme={storedTheme} - font={preferences.codeFont} + font={get(preferences, 'font.codeFont', 'default')} onEdit={onEdit} mode="javascript" onRun={onRun} diff --git a/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js b/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js index fc271e7433..bb29abd3ab 100644 --- a/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js +++ b/packages/bruno-app/src/components/ResponsePane/QueryResult/index.js @@ -1,8 +1,8 @@ import React from 'react'; +import get from 'lodash/get'; import CodeEditor from 'components/CodeEditor'; import { useTheme } from 'providers/Theme'; -import { usePreferences } from 'providers/Preferences'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { sendRequest } from 'providers/ReduxStore/slices/collections/actions'; import classnames from 'classnames'; import { getContentType, safeStringifyJSON, safeParseXML } from 'utils/common'; @@ -14,7 +14,7 @@ import { useMemo } from 'react'; const QueryResult = ({ item, collection, data, width, disableRunEventListener, headers, error }) => { const { storedTheme } = useTheme(); - const { preferences } = usePreferences(); + const preferences = useSelector((state) => state.app.preferences); const [tab, setTab] = useState('preview'); const dispatch = useDispatch(); const contentType = getContentType(headers); @@ -113,7 +113,17 @@ const QueryResult = ({ item, collection, data, width, disableRunEventListener, h return image; } - return ; + return ( + + ); }, [tab, collection, storedTheme, onRun, value, mode]); return ( diff --git a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/CodeView/index.js b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/CodeView/index.js index f3223bab4d..64c229ae41 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/CodeView/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/Collection/CollectionItem/GenerateCodeItem/CodeView/index.js @@ -1,12 +1,13 @@ import CodeEditor from 'components/CodeEditor/index'; +import get from 'lodash/get'; import { HTTPSnippet } from 'httpsnippet'; import { useTheme } from 'providers/Theme/index'; -import { usePreferences } from 'providers/Preferences/index'; import { buildHarRequest } from 'utils/codegenerator/har'; +import { useSelector } from 'react-redux'; const CodeView = ({ language, item }) => { const { storedTheme } = useTheme(); - const { preferences } = usePreferences(); + const preferences = useSelector((state) => state.app.preferences); const { target, client, language: lang } = language; let snippet = ''; @@ -17,7 +18,15 @@ const CodeView = ({ language, item }) => { snippet = 'Error generating code snippet'; } - return ; + return ( + + ); }; export default CodeView; diff --git a/packages/bruno-app/src/pages/_app.js b/packages/bruno-app/src/pages/_app.js index 6761290490..0b2f9c3a48 100644 --- a/packages/bruno-app/src/pages/_app.js +++ b/packages/bruno-app/src/pages/_app.js @@ -3,7 +3,6 @@ import { Provider } from 'react-redux'; import { AppProvider } from 'providers/App'; import { ToastProvider } from 'providers/Toaster'; import { HotkeysProvider } from 'providers/Hotkeys'; -import { PreferencesProvider } from 'providers/Preferences'; import ReduxStore from 'providers/ReduxStore'; import ThemeProvider from 'providers/Theme/index'; @@ -50,11 +49,9 @@ function MyApp({ Component, pageProps }) { - - - - - + + + diff --git a/packages/bruno-app/src/providers/App/index.js b/packages/bruno-app/src/providers/App/index.js index 041bf6e9db..2fbd17e759 100644 --- a/packages/bruno-app/src/providers/App/index.js +++ b/packages/bruno-app/src/providers/App/index.js @@ -1,6 +1,6 @@ import React, { useEffect } from 'react'; import useTelemetry from './useTelemetry'; -import useCollectionTreeSync from './useCollectionTreeSync'; +import useIpcEvents from './useIpcEvents'; import useCollectionNextAction from './useCollectionNextAction'; import { useDispatch } from 'react-redux'; import { refreshScreenWidth } from 'providers/ReduxStore/slices/app'; @@ -10,7 +10,7 @@ export const AppContext = React.createContext(); export const AppProvider = (props) => { useTelemetry(); - useCollectionTreeSync(); + useIpcEvents(); useCollectionNextAction(); const dispatch = useDispatch(); diff --git a/packages/bruno-app/src/providers/App/useCollectionTreeSync.js b/packages/bruno-app/src/providers/App/useIpcEvents.js similarity index 57% rename from packages/bruno-app/src/providers/App/useCollectionTreeSync.js rename to packages/bruno-app/src/providers/App/useIpcEvents.js index caf057d5b8..8e87b1cf9d 100644 --- a/packages/bruno-app/src/providers/App/useCollectionTreeSync.js +++ b/packages/bruno-app/src/providers/App/useIpcEvents.js @@ -14,11 +14,12 @@ import { runFolderEvent, brunoConfigUpdateEvent } from 'providers/ReduxStore/slices/collections'; +import { updatePreferences } from 'providers/ReduxStore/slices/app'; import toast from 'react-hot-toast'; import { openCollectionEvent, collectionAddEnvFileEvent } from 'providers/ReduxStore/slices/collections/actions'; import { isElectron } from 'utils/common/platform'; -const useCollectionTreeSync = () => { +const useIpcEvents = () => { const dispatch = useDispatch(); useEffect(() => { @@ -28,10 +29,6 @@ const useCollectionTreeSync = () => { const { ipcRenderer } = window; - const _openCollection = (pathname, uid, brunoConfig) => { - dispatch(openCollectionEvent(uid, pathname, brunoConfig)); - }; - const _collectionTreeUpdated = (type, val) => { if (window.__IS_DEV__) { console.log(type); @@ -82,69 +79,73 @@ const useCollectionTreeSync = () => { } }; - const _collectionAlreadyOpened = (pathname) => { + ipcRenderer.invoke('renderer:ready'); + const removeCollectionTreeUpdateListener = ipcRenderer.on('main:collection-tree-updated', _collectionTreeUpdated); + + const removeOpenCollectionListener = ipcRenderer.on('main:collection-opened', (pathname, uid, brunoConfig) => { + dispatch(openCollectionEvent(uid, pathname, brunoConfig)); + }); + + const removeCollectionAlreadyOpenedListener = ipcRenderer.on('main:collection-already-opened', (pathname) => { toast.success('Collection is already opened'); - }; + }); - const _displayError = (error) => { + const removeDisplayErrorListener = ipcRenderer.on('main:display-error', (error) => { if (typeof error === 'string') { return toast.error(error || 'Something went wrong!'); } if (typeof message === 'object') { return toast.error(error.message || 'Something went wrong!'); } - }; + }); - const _scriptEnvironmentUpdate = (val) => { + const removeScriptEnvUpdateListener = ipcRenderer.on('main:script-environment-update', (val) => { dispatch(scriptEnvironmentUpdateEvent(val)); - }; - - const _processEnvUpdate = (val) => { - dispatch(processEnvUpdateEvent(val)); - }; + }); - const _collectionRenamed = (val) => { + const removeCollectionRenamedListener = ipcRenderer.on('main:collection-renamed', (val) => { dispatch(collectionRenamedEvent(val)); - }; + }); - const _runFolderEvent = (val) => { + const removeRunFolderEventListener = ipcRenderer.on('main:run-folder-event', (val) => { dispatch(runFolderEvent(val)); - }; + }); - const _runRequestEvent = (val) => { + const removeRunRequestEventListener = ipcRenderer.on('main:run-request-event', (val) => { dispatch(runRequestEvent(val)); - }; + }); - ipcRenderer.invoke('renderer:ready'); + const removeProcessEnvUpdatesListener = ipcRenderer.on('main:process-env-update', (val) => { + dispatch(processEnvUpdateEvent(val)); + }); - const removeListener1 = ipcRenderer.on('main:collection-opened', _openCollection); - const removeListener2 = ipcRenderer.on('main:collection-tree-updated', _collectionTreeUpdated); - const removeListener3 = ipcRenderer.on('main:collection-already-opened', _collectionAlreadyOpened); - const removeListener4 = ipcRenderer.on('main:display-error', _displayError); - const removeListener5 = ipcRenderer.on('main:script-environment-update', _scriptEnvironmentUpdate); - const removeListener6 = ipcRenderer.on('main:collection-renamed', _collectionRenamed); - const removeListener7 = ipcRenderer.on('main:run-folder-event', _runFolderEvent); - const removeListener8 = ipcRenderer.on('main:run-request-event', _runRequestEvent); - const removeListener9 = ipcRenderer.on('main:process-env-update', _processEnvUpdate); - const removeListener10 = ipcRenderer.on('main:console-log', (val) => { + const removeConsoleLogListener = ipcRenderer.on('main:console-log', (val) => { console[val.type](...val.args); }); - const removeListener11 = ipcRenderer.on('main:bruno-config-update', (val) => dispatch(brunoConfigUpdateEvent(val))); + + const removeConfigUpdatesListener = ipcRenderer.on('main:bruno-config-update', (val) => + dispatch(brunoConfigUpdateEvent(val)) + ); + + const removePreferencesUpdatesListener = ipcRenderer.on('main:load-preferences', (val) => { + dispatch(updatePreferences(val)); + }); return () => { - removeListener1(); - removeListener2(); - removeListener3(); - removeListener4(); - removeListener5(); - removeListener6(); - removeListener7(); - removeListener8(); - removeListener9(); - removeListener10(); - removeListener11(); + removeCollectionTreeUpdateListener(); + removeOpenCollectionListener(); + removeCollectionAlreadyOpenedListener(); + removeDisplayErrorListener(); + removeScriptEnvUpdateListener(); + removeCollectionRenamedListener(); + removeRunFolderEventListener(); + removeRunRequestEventListener(); + removeProcessEnvUpdatesListener(); + removeConsoleLogListener(); + removeConfigUpdatesListener(); + removePreferencesUpdatesListener(); }; }, [isElectron]); }; -export default useCollectionTreeSync; +export default useIpcEvents; diff --git a/packages/bruno-app/src/providers/Preferences/index.js b/packages/bruno-app/src/providers/Preferences/index.js deleted file mode 100644 index 9b03450046..0000000000 --- a/packages/bruno-app/src/providers/Preferences/index.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Preferences Provider - * - * This provider is responsible for managing the user's preferences in the app. - * The preferences are stored in the browser local storage. - * - * On start, an IPC event is published to the main process to set the preferences in the electron process. - */ - -import { useEffect, createContext, useContext } from 'react'; -import * as Yup from 'yup'; -import useLocalStorage from 'hooks/useLocalStorage/index'; -import toast from 'react-hot-toast'; - -const defaultPreferences = { - request: { - sslVerification: true - } -}; - -const preferencesSchema = Yup.object().shape({ - request: Yup.object().shape({ - sslVerification: Yup.boolean() - }) -}); - -export const PreferencesContext = createContext(); -export const PreferencesProvider = (props) => { - const [preferences, setPreferences] = useLocalStorage('bruno.preferences', defaultPreferences); - const { ipcRenderer } = window; - - useEffect(() => { - ipcRenderer.invoke('renderer:set-preferences', preferences).catch((err) => { - toast.error(err.message || 'Preferences sync error'); - }); - }, [preferences, toast]); - - const validatedSetPreferences = (newPreferences) => { - return new Promise((resolve, reject) => { - preferencesSchema - .validate(newPreferences, { abortEarly: true }) - .then((validatedPreferences) => { - setPreferences(validatedPreferences); - resolve(validatedPreferences); - }) - .catch((error) => { - let errMsg = error.message || 'Preferences validation error'; - toast.error(errMsg); - reject(error); - }); - }); - }; - - // todo: setPreferences must validate the preferences object against a schema - const value = { - preferences, - setPreferences: validatedSetPreferences - }; - - return ( - - <>{props.children} - - ); -}; - -export const usePreferences = () => { - const context = useContext(PreferencesContext); - - if (context === undefined) { - throw new Error(`usePreferences must be used within a PreferencesProvider`); - } - - return context; -}; - -export default PreferencesProvider; diff --git a/packages/bruno-app/src/providers/ReduxStore/slices/app.js b/packages/bruno-app/src/providers/ReduxStore/slices/app.js index f1e9b91177..c3a3aa5a87 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/app.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/app.js @@ -1,11 +1,20 @@ import { createSlice } from '@reduxjs/toolkit'; +import toast from 'react-hot-toast'; const initialState = { isDragging: false, idbConnectionReady: false, leftSidebarWidth: 222, screenWidth: 500, - showHomePage: false + showHomePage: false, + preferences: { + request: { + sslVerification: true + }, + font: { + codeFont: 'default' + } + } }; export const appSlice = createSlice({ @@ -29,6 +38,9 @@ export const appSlice = createSlice({ }, hideHomePage: (state) => { state.showHomePage = false; + }, + updatePreferences: (state, action) => { + state.preferences = action.payload; } } }); @@ -39,7 +51,25 @@ export const { updateLeftSidebarWidth, updateIsDragging, showHomePage, - hideHomePage + hideHomePage, + updatePreferences } = appSlice.actions; +export const savePreferences = (preferences) => (dispatch, getState) => { + return new Promise((resolve, reject) => { + const { ipcRenderer } = window; + + ipcRenderer + .invoke('renderer:save-preferences', preferences) + .then(() => toast.success('Preferences saved successfully')) + .then(() => dispatch(updatePreferences(preferences))) + .then(resolve) + .catch((err) => { + toast.error('An error occurred while saving preferences'); + console.error(err); + reject(err); + }); + }); +}; + export default appSlice.reducer; 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 c5cb71f837..c60b3e68c0 100644 --- a/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js +++ b/packages/bruno-app/src/providers/ReduxStore/slices/collections/index.js @@ -1057,7 +1057,6 @@ export const collectionsSlice = createSlice({ if (collection) { collection.root = file.data; } - console.log('collectionAddFileEvent', file); return; } diff --git a/packages/bruno-electron/src/index.js b/packages/bruno-electron/src/index.js index 1acaa7adc1..2199122dc5 100644 --- a/packages/bruno-electron/src/index.js +++ b/packages/bruno-electron/src/index.js @@ -8,6 +8,7 @@ const menuTemplate = require('./app/menu-template'); const LastOpenedCollections = require('./store/last-opened-collections'); const registerNetworkIpc = require('./ipc/network'); const registerCollectionsIpc = require('./ipc/collection'); +const registerPreferencesIpc = require('./ipc/preferences'); const Watcher = require('./app/watcher'); const { loadWindowState, saveWindowState } = require('./utils/window'); @@ -39,8 +40,8 @@ app.on('ready', async () => { y, width, height, - minWidth:1000, - minHeight:640, + minWidth: 1000, + minHeight: 640, webPreferences: { nodeIntegration: true, contextIsolation: true, @@ -76,6 +77,7 @@ app.on('ready', async () => { // register all ipc handlers registerNetworkIpc(mainWindow, watcher, lastOpenedCollections); registerCollectionsIpc(mainWindow, watcher, lastOpenedCollections); + registerPreferencesIpc(mainWindow, watcher, lastOpenedCollections); }); // Quit the app once all windows are closed diff --git a/packages/bruno-electron/src/ipc/collection.js b/packages/bruno-electron/src/ipc/collection.js index 944a04f01d..3b1212009a 100644 --- a/packages/bruno-electron/src/ipc/collection.js +++ b/packages/bruno-electron/src/ipc/collection.js @@ -15,10 +15,9 @@ const { sanitizeDirectoryName } = require('../utils/filesystem'); const { stringifyJson } = require('../utils/common'); -const { openCollectionDialog, openCollection } = require('../app/collections'); +const { openCollectionDialog } = require('../app/collections'); const { generateUidBasedOnHash } = require('../utils/common'); const { moveRequestUid, deleteRequestUid } = require('../cache/requestUids'); -const { setPreferences } = require('../store/preferences'); const EnvironmentSecretsStore = require('../store/env-secrets'); const environmentSecretsStore = new EnvironmentSecretsStore(); @@ -469,25 +468,6 @@ const registerRendererEventHandlers = (mainWindow, watcher, lastOpenedCollection } }); - ipcMain.handle('renderer:ready', async (event) => { - // reload last opened collections - const lastOpened = lastOpenedCollections.getAll(); - - if (lastOpened && lastOpened.length) { - for (let collectionPath of lastOpened) { - if (isDirectory(collectionPath)) { - openCollection(mainWindow, watcher, collectionPath, { - dontSendDisplayErrors: true - }); - } - } - } - }); - - ipcMain.handle('renderer:set-preferences', async (event, preferences) => { - setPreferences(preferences); - }); - ipcMain.handle('renderer:update-bruno-config', async (event, brunoConfig, collectionPath, collectionUid) => { try { const brunoConfigPath = path.join(collectionPath, 'bruno.json'); diff --git a/packages/bruno-electron/src/ipc/preferences.js b/packages/bruno-electron/src/ipc/preferences.js new file mode 100644 index 0000000000..f93ec5e6fc --- /dev/null +++ b/packages/bruno-electron/src/ipc/preferences.js @@ -0,0 +1,35 @@ +const { ipcMain } = require('electron'); +const { getPreferences, savePreferences } = require('../store/preferences'); +const { isDirectory } = require('../utils/filesystem'); +const { openCollection } = require('../app/collections'); + +const registerPreferencesIpc = (mainWindow, watcher, lastOpenedCollections) => { + ipcMain.handle('renderer:ready', async (event) => { + // load preferences + const preferences = getPreferences(); + mainWindow.webContents.send('main:load-preferences', preferences); + + // reload last opened collections + const lastOpened = lastOpenedCollections.getAll(); + + if (lastOpened && lastOpened.length) { + for (let collectionPath of lastOpened) { + if (isDirectory(collectionPath)) { + openCollection(mainWindow, watcher, collectionPath, { + dontSendDisplayErrors: true + }); + } + } + } + }); + + ipcMain.handle('renderer:save-preferences', async (event, preferences) => { + try { + await savePreferences(preferences); + } catch (error) { + return Promise.reject(error); + } + }); +}; + +module.exports = registerPreferencesIpc; diff --git a/packages/bruno-electron/src/store/preferences.js b/packages/bruno-electron/src/store/preferences.js index f1b86b0f36..869895cd83 100644 --- a/packages/bruno-electron/src/store/preferences.js +++ b/packages/bruno-electron/src/store/preferences.js @@ -1,26 +1,65 @@ -/** - * The preferences are stored in the browser local storage. - * When the app is started, an IPC message is published from the renderer process to set the preferences. - * The electron process uses this module to get the preferences. - * - * { - * request: { - * sslVerification: boolean - * } - * } - */ - -let preferences = {}; +const Yup = require('yup'); +const Store = require('electron-store'); + +const defaultPreferences = { + request: { + sslVerification: true + }, + font: { + codeFont: 'default' + } +}; + +const preferencesSchema = Yup.object().shape({ + request: Yup.object().shape({ + sslVerification: Yup.boolean() + }), + font: Yup.object().shape({ + codeFont: Yup.string().nullable() + }) +}); + +class PreferencesStore { + constructor() { + this.store = new Store({ + name: 'preferences', + clearInvalidConfig: true + }); + } + + getPreferences() { + return { + defaultPreferences, + ...this.store.get('preferences') + }; + } + + savePreferences(newPreferences) { + return this.store.set('preferences', newPreferences); + } +} + +const preferencesStore = new PreferencesStore(); const getPreferences = () => { - return preferences; + return preferencesStore.getPreferences(); }; -const setPreferences = (newPreferences) => { - preferences = newPreferences; +const savePreferences = async (newPreferences) => { + return new Promise((resolve, reject) => { + preferencesSchema + .validate(newPreferences, { abortEarly: true }) + .then((validatedPreferences) => { + preferencesStore.savePreferences(validatedPreferences); + resolve(); + }) + .catch((error) => { + reject(error); + }); + }); }; module.exports = { getPreferences, - setPreferences + savePreferences }; diff --git a/packages/bruno-electron/src/store/window-state.js b/packages/bruno-electron/src/store/window-state.js index bb0a61b647..90bf7b8cb2 100644 --- a/packages/bruno-electron/src/store/window-state.js +++ b/packages/bruno-electron/src/store/window-state.js @@ -1,4 +1,3 @@ -const _ = require('lodash'); const Store = require('electron-store'); const DEFAULT_WINDOW_WIDTH = 1280; From 4230bf8e41fc9badc35dfdfa9338376343355482 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Sun, 15 Oct 2023 16:03:13 +0530 Subject: [PATCH 4/4] chore: purge pageComponents --- .../{pageComponents/Index => pages/Bruno}/StyledWrapper.js | 0 .../src/{pageComponents/Index => pages/Bruno}/index.js | 1 - packages/bruno-app/src/pages/index.js | 4 ++-- 3 files changed, 2 insertions(+), 3 deletions(-) rename packages/bruno-app/src/{pageComponents/Index => pages/Bruno}/StyledWrapper.js (100%) rename packages/bruno-app/src/{pageComponents/Index => pages/Bruno}/index.js (97%) diff --git a/packages/bruno-app/src/pageComponents/Index/StyledWrapper.js b/packages/bruno-app/src/pages/Bruno/StyledWrapper.js similarity index 100% rename from packages/bruno-app/src/pageComponents/Index/StyledWrapper.js rename to packages/bruno-app/src/pages/Bruno/StyledWrapper.js diff --git a/packages/bruno-app/src/pageComponents/Index/index.js b/packages/bruno-app/src/pages/Bruno/index.js similarity index 97% rename from packages/bruno-app/src/pageComponents/Index/index.js rename to packages/bruno-app/src/pages/Bruno/index.js index 480ea08f33..9f4de24347 100644 --- a/packages/bruno-app/src/pageComponents/Index/index.js +++ b/packages/bruno-app/src/pages/Bruno/index.js @@ -9,7 +9,6 @@ import StyledWrapper from './StyledWrapper'; import 'codemirror/theme/material.css'; import 'codemirror/theme/monokai.css'; import 'codemirror/addon/scroll/simplescrollbars.css'; -import Documentation from 'components/Documentation'; const SERVER_RENDERED = typeof navigator === 'undefined' || global['PREVENT_CODEMIRROR_RENDER'] === true; if (!SERVER_RENDERED) { diff --git a/packages/bruno-app/src/pages/index.js b/packages/bruno-app/src/pages/index.js index 8c1a8ae5e7..1567ef2c4f 100644 --- a/packages/bruno-app/src/pages/index.js +++ b/packages/bruno-app/src/pages/index.js @@ -1,5 +1,5 @@ import Head from 'next/head'; -import IndexPage from 'pageComponents/Index'; +import Bruno from './Bruno'; import GlobalStyle from '../globalStyles'; export default function Home() { @@ -13,7 +13,7 @@ export default function Home() {
- +
);