diff --git a/src/App.jsx b/src/App.jsx
index eb3237f..5024680 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -33,6 +33,7 @@ import { TasksSettingsProvider } from './contexts/TasksSettingsContext';
import { WebSocketProvider, useWebSocketContext } from './contexts/WebSocketContext';
import ProtectedRoute from './components/ProtectedRoute';
import { useVersionCheck } from './hooks/useVersionCheck';
+import useLocalStorage from './hooks/useLocalStorage';
import { api, authenticatedFetch } from './utils/api';
@@ -54,22 +55,10 @@ function AppContent() {
const [isInputFocused, setIsInputFocused] = useState(false);
const [showSettings, setShowSettings] = useState(false);
const [showQuickSettings, setShowQuickSettings] = useState(false);
- const [autoExpandTools, setAutoExpandTools] = useState(() => {
- const saved = localStorage.getItem('autoExpandTools');
- return saved !== null ? JSON.parse(saved) : false;
- });
- const [showRawParameters, setShowRawParameters] = useState(() => {
- const saved = localStorage.getItem('showRawParameters');
- return saved !== null ? JSON.parse(saved) : false;
- });
- const [autoScrollToBottom, setAutoScrollToBottom] = useState(() => {
- const saved = localStorage.getItem('autoScrollToBottom');
- return saved !== null ? JSON.parse(saved) : true;
- });
- const [sendByCtrlEnter, setSendByCtrlEnter] = useState(() => {
- const saved = localStorage.getItem('sendByCtrlEnter');
- return saved !== null ? JSON.parse(saved) : false;
- });
+ const [autoExpandTools, setAutoExpandTools] = useLocalStorage('autoExpandTools', false);
+ const [showRawParameters, setShowRawParameters] = useLocalStorage('showRawParameters', false);
+ const [autoScrollToBottom, setAutoScrollToBottom] = useLocalStorage('autoScrollToBottom', true);
+ const [sendByCtrlEnter, setSendByCtrlEnter] = useLocalStorage('sendByCtrlEnter', false);
// Session Protection System: Track sessions with active conversations to prevent
// automatic project updates from interrupting ongoing chats. When a user sends
// a message, the session is marked as "active" and project updates are paused
@@ -491,9 +480,10 @@ function AppContent() {
return (
{/* Backdrop */}
-
setShowVersionModal(false)}
+ aria-label="Close version upgrade modal"
/>
{/* Modal */}
@@ -604,7 +594,7 @@ function AppContent() {
-
{
e.stopPropagation();
@@ -615,6 +605,7 @@ function AppContent() {
e.stopPropagation();
setSidebarOpen(false);
}}
+ aria-label="Close sidebar"
/>
{
- setAutoExpandTools(value);
- localStorage.setItem('autoExpandTools', JSON.stringify(value));
- }}
+ onAutoExpandChange={setAutoExpandTools}
showRawParameters={showRawParameters}
- onShowRawParametersChange={(value) => {
- setShowRawParameters(value);
- localStorage.setItem('showRawParameters', JSON.stringify(value));
- }}
+ onShowRawParametersChange={setShowRawParameters}
autoScrollToBottom={autoScrollToBottom}
- onAutoScrollChange={(value) => {
- setAutoScrollToBottom(value);
- localStorage.setItem('autoScrollToBottom', JSON.stringify(value));
- }}
+ onAutoScrollChange={setAutoScrollToBottom}
sendByCtrlEnter={sendByCtrlEnter}
- onSendByCtrlEnterChange={(value) => {
- setSendByCtrlEnter(value);
- localStorage.setItem('sendByCtrlEnter', JSON.stringify(value));
- }}
+ onSendByCtrlEnterChange={setSendByCtrlEnter}
isMobile={isMobile}
/>
)}
diff --git a/src/hooks/useLocalStorage.jsx b/src/hooks/useLocalStorage.jsx
new file mode 100644
index 0000000..2a42df9
--- /dev/null
+++ b/src/hooks/useLocalStorage.jsx
@@ -0,0 +1,41 @@
+import { useState } from 'react';
+
+/**
+ * Custom hook to persist state in localStorage.
+ *
+ * @param {string} key The key to use for localStorage.
+ * @param {any} initialValue The initial value to use if nothing is in localStorage.
+ * @returns {[any, Function]} A tuple containing the stored value and a setter function.
+ */
+function useLocalStorage(key, initialValue) {
+ const [storedValue, setStoredValue] = useState(() => {
+ if (typeof window === 'undefined') {
+ return initialValue;
+ }
+ try {
+ const item = window.localStorage.getItem(key);
+ return item ? JSON.parse(item) : initialValue;
+ } catch (error) {
+ console.log(error);
+ return initialValue;
+ }
+ });
+
+ const setValue = (value) => {
+ if (typeof window === 'undefined') {
+ return;
+ }
+ try {
+ const valueToStore =
+ value instanceof Function ? value(storedValue) : value;
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
+ setStoredValue(valueToStore);
+ } catch (error) {
+ console.log(error);
+ }
+ };
+
+ return [storedValue, setValue];
+}
+
+export default useLocalStorage;