mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-28 05:12:33 +00:00
* ran prettier * Refactor ESLint configuration to use ES module syntax and enhance TypeScript support - Converted CommonJS `require` statements to ES module `import` syntax for better compatibility with modern JavaScript. - Added new paths to ignore in ESLint configuration to exclude additional directories. - Updated TypeScript file patterns to be more specific, improving linting accuracy. - Adjusted React hooks rules to allow certain patterns, enhancing flexibility in component design. These changes improve the maintainability and clarity of the ESLint configuration, aligning it with current best practices. * Refactor ESLint configuration to use ES module syntax and enhance TypeScript support - Converted CommonJS `require` statements to ES module `import` syntax for better compatibility with modern JavaScript. - Added new paths to ignore in ESLint configuration to exclude additional directories. - Updated TypeScript file patterns to be more specific, improving linting accuracy. - Introduced new React hooks rules and adjusted existing rules for better adherence to best practices. - Made minor adjustments to import statements across various files for consistency and clarity. These changes improve the overall linting setup and ensure better code quality across the project. * Refactor import statements across multiple files for consistency - Updated import statements to use TypeScript's `type` syntax for type imports, enhancing clarity and consistency across the codebase. - Consolidated imports from the same module into single statements, improving readability and maintainability. These changes streamline the code structure and align with best practices for TypeScript imports. * Refactor import statements in memory manager for improved clarity - Updated import statements to consolidate type imports and enhance readability. - Removed redundant imports, streamlining the code structure in the memory manager file. These changes align with best practices for TypeScript imports and improve maintainability. * Add Husky for pre-commit and pre-push hooks - Introduced Husky to manage Git hooks, enhancing the development workflow. - Added pre-commit and pre-push scripts to enforce code formatting and linting checks before commits and pushes. - Updated package.json to include Husky as a dependency and added a prepare script for setup. These changes improve code quality and ensure adherence to formatting and linting standards during the development process. * Refactor import statements for improved clarity and consistency - Updated import statements across multiple files to consolidate type imports and enhance readability. - Adjusted the order of imports for better organization and alignment with best practices in TypeScript. These changes streamline the code structure and improve maintainability throughout the project. * ran formatter * Refactor import statements and improve code formatting across multiple files - Consolidated and reordered import statements for better clarity and consistency in `SkillsGrid.tsx`, `SkillProvider.tsx`, and `index.ts`. - Enhanced readability by adjusting formatting and removing redundant lines. - These changes align with best practices for TypeScript imports and improve overall maintainability of the codebase. * Refactor and optimize code in multiple components - Removed redundant properties from the `STATUS_DISPLAY` object in `SkillsGrid.tsx` to streamline status handling. - Consolidated import statements in `SettingsModal.tsx` for improved organization. - Simplified state management and error handling in `BillingPanel.tsx`, enhancing performance and readability. - Added `REHYDRATE` import to `index.ts` for better state persistence management. These changes improve code clarity, maintainability, and align with best practices in TypeScript development. * Consolidate import statements in SettingsModal.tsx for improved organization * Add Prettier and ESLint checks to typecheck workflow - Integrated a Prettier formatting check to ensure code style consistency. - Added an ESLint step to enforce code quality and catch potential issues. - These enhancements improve the development workflow by automating formatting and linting checks during the typecheck process. * Add activeSkillDescription state to ConnectionsPanel and ConnectStep - Introduced activeSkillDescription state in both ConnectionsPanel and ConnectStep components to store and manage skill descriptions. - Updated the SkillSetupModal to accept skillDescription as a prop, enhancing the modal's functionality and data handling. These changes improve the user experience by providing more detailed information about skills during the connection setup process. * Enhance pre-push hook to include TypeScript compile check - Added a TypeScript compile check to the pre-push script, ensuring that code compiles successfully before pushing. - Updated error handling to include compile errors alongside formatting and linting issues, providing clearer feedback to developers. These changes improve the reliability of the codebase by preventing non-compiling code from being pushed. * Update GitHub workflows for pull request handling and publishing logic - Modified the package-and-publish workflow to support pull request events, ensuring proper handling of branches. - Adjusted the SHOULD_PUBLISH environment variable to differentiate between pull requests and main branch events. - Updated the pr-protection workflow to focus solely on the main branch, removing references to the master branch. These changes enhance the CI/CD process by refining branch handling and improving clarity in workflow conditions.
6.6 KiB
6.6 KiB
State Management
The application uses Redux Toolkit with Redux-Persist for robust state management.
Store Configuration
File: store/index.ts
// Combines all slices with persistence
const persistConfig = {
key: 'root',
storage,
whitelist: ['auth', 'telegram'], // Persisted slices
};
Redux State Structure
RootState = {
auth: {
token: string | null, // JWT (persisted)
isOnboardedByUser: Record<string, boolean>, // Per-user flag (persisted)
},
socket: {
byUser: Record<
string,
{
// Per user ID
status: 'connecting' | 'connected' | 'disconnected';
socketId: string | null;
}
>,
},
user: { profile: User | null, loading: boolean, error: string | null },
telegram: {
byUser: Record<string, TelegramState>, // Per Telegram user (persisted)
},
};
Slices
Auth Slice (store/authSlice.ts)
Manages JWT token and per-user onboarding status.
State:
interface AuthState {
token: string | null;
isOnboardedByUser: Record<string, boolean>;
}
Actions:
setToken(token: string)- Store JWT after loginclearToken()- Remove token on logoutsetOnboarded({ userId, isOnboarded })- Mark user as onboarded
Selectors (store/authSelectors.ts):
selectToken- Get current JWTselectIsOnboarded(userId)- Check if user completed onboarding
Socket Slice (store/socketSlice.ts)
Tracks Socket.io connection status per user.
State:
interface SocketState {
byUser: Record<
string,
{ status: 'connecting' | 'connected' | 'disconnected'; socketId: string | null }
>;
}
Actions:
setSocketStatus({ userId, status })- Update connection statussetSocketId({ userId, socketId })- Store socket IDclearSocketState(userId)- Clear user's socket state
Selectors (store/socketSelectors.ts):
selectSocketStatus(userId)- Get connection statusselectIsSocketConnected(userId)- Boolean connected check
User Slice (store/userSlice.ts)
Stores user profile data.
State:
interface UserState {
profile: User | null;
loading: boolean;
error: string | null;
}
Actions:
setUser(user)- Store user profilesetUserLoading(loading)- Set loading statesetUserError(error)- Set error stateclearUser()- Clear profile on logout
Telegram Slice (store/telegram/)
Complex nested state management for Telegram integration.
Files:
index.ts- Slice exports (actions, thunks)types.ts- Entity and state interfacesreducers.ts- Synchronous reducersextraReducers.ts- Async thunk handlersthunks.ts- Async operations
State Structure:
telegram.byUser[telegramUserId] = {
connectionStatus: "disconnected" | "connecting" | "connected" | "error",
authStatus: "not_authenticated" | "authenticating" | "authenticated" | "error",
currentUser: TelegramUser | null,
sessionString: string | null, // Stored here, NOT localStorage
chats: Record<string, TelegramChat>,
chatsOrder: string[],
messages: Record<chatId, Record<msgId, TelegramMessage>>,
threads: Record<chatId, TelegramThread[]>
}
Reducers:
setCurrentUser- Store authenticated Telegram usersetSessionString- Store MTProto session (for persistence)setConnectionStatus- Update connection statesetAuthStatus- Update authentication stateaddChat/updateChat- Manage chat listaddMessage/updateMessage- Manage message historysetThreads- Store thread data
Thunks (store/telegram/thunks.ts):
initializeTelegram(userId)- Initialize MTProto clientconnectTelegram(userId)- Establish Telegram connectionfetchChats(userId)- Load chat listfetchMessages({ userId, chatId })- Load message historydisconnectTelegram(userId)- Clean disconnect
Selectors (store/telegramSelectors.ts):
selectTelegramState(userId)- Get full Telegram stateselectTelegramConnectionStatus(userId)- Get connection statusselectTelegramAuthStatus(userId)- Get auth statusselectTelegramChats(userId)- Get chat listselectTelegramMessages(userId, chatId)- Get messages for chat
Typed Hooks
File: store/hooks.ts
// Use these instead of plain useDispatch/useSelector
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
Persistence Configuration
What's Persisted
auth.token- JWT for authenticationauth.isOnboardedByUser- Per-user onboarding statustelegram.byUser- Telegram state (sessions, chats, etc.)
What's NOT Persisted
socket- Connection state (reconnects on app start)user.loading/user.error- Transient UI states- Telegram loading/error states
Storage Backend
Redux-Persist uses localStorage adapter by default. This is the ONLY acceptable use of localStorage in the application.
Usage Examples
Reading State
import { useAppSelector } from '../store/hooks';
function MyComponent() {
const token = useAppSelector(state => state.auth.token);
const isConnected = useAppSelector(state => state.socket.byUser[userId]?.status === 'connected');
const chats = useAppSelector(state => state.telegram.byUser[userId]?.chats);
}
Dispatching Actions
import { clearToken, setToken } from '../store/authSlice';
import { useAppDispatch } from '../store/hooks';
import { initializeTelegram } from '../store/telegram/thunks';
function MyComponent() {
const dispatch = useAppDispatch();
// Sync action
const handleLogin = (token: string) => {
dispatch(setToken(token));
};
// Async thunk
const handleConnect = async () => {
await dispatch(initializeTelegram(userId)).unwrap();
};
}
Using Selectors
import { selectIsOnboarded } from '../store/authSelectors';
import { useAppSelector } from '../store/hooks';
import { selectTelegramConnectionStatus } from '../store/telegramSelectors';
function MyComponent({ userId }) {
const isOnboarded = useAppSelector(state => selectIsOnboarded(state, userId));
const connectionStatus = useAppSelector(state => selectTelegramConnectionStatus(state, userId));
}
Best Practices
- Always use typed hooks -
useAppDispatchanduseAppSelector - Use selectors for derived state - Memoized and testable
- Keep thunks in separate files - Better organization
- Per-user state scoping - Key state by user ID
- Avoid localStorage - Use Redux-Persist instead
Previous: Architecture Overview | Next: Services Layer