Refactor state

This commit is contained in:
2025-11-18 23:21:30 +03:00
Unverified
parent c6c60e6404
commit dc4536cabc
43 changed files with 720 additions and 866 deletions
@@ -2,14 +2,16 @@ import { PRODUCT_NAME } from "@/core/config";
import useProfile from "@/pages/chat/hooks/useProfile";
import defaultAvatar from "@/images/default-avatar.png";
import { useState } from "react";
import { useAppState } from "@/pages/chat/state";
import { useUserStore } from "@/state/user";
import { useProfileStore } from "@/state/profile";
import { MinimizedCallBar } from "@/pages/chat/ui/right/calls/MinimizedCallBar";
import styles from "@/pages/chat/css/left-panel.module.scss";
import logoIcon from "@/images/logo.svg";
export function ChatHeader({ headerRef }: { headerRef?: React.RefObject<HTMLElement | null> }) {
const { profileData } = useProfile();
const { setProfileDialog, user } = useAppState();
const { user } = useUserStore();
const { setProfileDialog } = useProfileStore();
const [profilePictureUrl, setProfilePictureUrl] = useState(profileData?.profile_picture || defaultAvatar);
function handleProfileClick() {
@@ -1,4 +1,4 @@
import { useAppState } from "@/pages/chat/state";
import { useUserStore } from "@/state/user";
import { useRef, useState } from "react";
import { SettingsDialog } from "./settings/SettingsDialog";
import { UsernameSearch } from "./UsernameSearch";
@@ -9,7 +9,7 @@ import styles from "@/pages/chat/css/left-panel.module.scss";
function BottomAppBar({ bottomAppBarRef }: { bottomAppBarRef?: React.RefObject<MDUIBottomAppBar | null> }) {
const [settingsOpen, onSettingsOpenChange] = useState(false);
const { logout } = useAppState();
const { logout } = useUserStore();
return (
<>
@@ -1,5 +1,6 @@
import { useState, useEffect, useCallback, useMemo } from "react";
import { useAppState } from "@/pages/chat/state";
import { useUserStore } from "@/state/user";
import { useChatStore } from "@/state/chat";
import { useDM, type DMUser } from "@/pages/chat/hooks/useDM";
import { fetchMessages } from "@/core/api/messaging";
import { fetchUserPublicKey } from "@/core/api/dm";
@@ -42,7 +43,8 @@ const PUBLIC_CHAT: PublicChat = {
};
export function UnifiedChatsList() {
const { user, switchToPublicChat, switchToDM, chat } = useAppState();
const { user } = useUserStore();
const { switchToPublicChat, switchToDM, activeTab } = useChatStore();
const { dmUsers, isLoadingUsers, loadUsers } = useDM();
const [lastMessages, setLastMessages] = useState<Record<string, Message | undefined>>({});
@@ -61,11 +63,11 @@ export function UnifiedChatsList() {
}, [user.authToken]);
useEffect(() => {
if (chat.activeTab === "chats") {
if (activeTab === "chats") {
loadUsers();
loadLastMessages();
}
}, [chat.activeTab, loadUsers, loadLastMessages]);
}, [activeTab, loadUsers, loadLastMessages]);
const allChats = useMemo<ChatItem[]>(() => {
return [
@@ -155,7 +157,7 @@ export function UnifiedChatsList() {
async function handleDMClick(dmConversation: DMConversation) {
if (!dmConversation.publicKey) {
const authToken = useAppState.getState().user.authToken;
const authToken = useUserStore.getState().user.authToken;
if (!authToken) return;
const publicKey = await fetchUserPublicKey(dmConversation.id, authToken);
@@ -1,5 +1,6 @@
import { useState, useEffect, useRef } from "react";
import { useAppState } from "@/pages/chat/state";
import { useUserStore } from "@/state/user";
import { useChatStore } from "@/state/chat";
import { searchUsers, fetchUserPublicKey } from "@/core/api/dm";
import { StatusBadge } from "@/core/components/StatusBadge";
import type { User } from "@/core/types";
@@ -23,7 +24,8 @@ export interface UsernameSearchProps {
}
export function UsernameSearch({ containerRef, headerRef, bottomAppBarRef }: UsernameSearchProps) {
const { user, switchToDM, chat } = useAppState();
const { user } = useUserStore();
const { switchToDM, activeDm } = useChatStore();
const [searchQuery, setSearchQuery] = useState("");
const [searchResults, setSearchResults] = useState<SearchUser[]>([]);
const [isSearching, setIsSearching] = useState(false);
@@ -68,7 +70,7 @@ export function UsernameSearch({ containerRef, headerRef, bottomAppBarRef }: Use
// Subscribe to online status for all search results
useEffect(() => {
const activeDmUserId = chat.activeDm?.userId;
const activeDmUserId = activeDm?.userId;
const switchingToUserId = switchingToUserIdRef.current;
const currentSearchResultIds = new Set(searchResults.map(u => u.id));
const previousSearchResultIds = new Set(previousSearchResultIdsRef.current);
@@ -101,12 +103,12 @@ export function UsernameSearch({ containerRef, headerRef, bottomAppBarRef }: Use
// Clear the ref if the user is now the active DM (state has updated)
const finalSwitchingToUserId = switchingToUserIdRef.current;
const finalActiveDmUserId = chat.activeDm?.userId;
const finalActiveDmUserId = activeDm?.userId;
if (finalSwitchingToUserId && finalSwitchingToUserId === finalActiveDmUserId) {
switchingToUserIdRef.current = null;
}
};
}, [searchResults, chat.activeDm?.userId]);
}, [searchResults, activeDm?.userId]);
async function handleUserClick(searchUser: SearchUser) {
@@ -1,5 +1,5 @@
import { MaterialList, MaterialListItem } from "@/utils/material";
import { useAppState } from "@/pages/chat/state";
import { useUserStore } from "@/state/user";
import { deleteAccount } from "@/core/api/account";
import { confirm } from "mdui/functions/confirm";
import styles from "@/pages/chat/css/settings-dialog.module.scss";
@@ -9,7 +9,7 @@ interface AccountPanelProps {
}
export function AccountPanel({ onClose }: AccountPanelProps) {
const { user, logout } = useAppState();
const { user, logout } = useUserStore();
const authToken = user?.authToken;
async function handleDeleteAccount() {
@@ -1,13 +1,13 @@
import { useState } from "react";
import { StyledDialog } from "@/core/components/StyledDialog";
import type { DialogProps } from "@/core/types";
import { useAppState } from "@/pages/chat/state";
import { useUserStore } from "@/state/user";
import { changePassword } from "@/core/api/account";
import { MaterialButton, MaterialIconButton, MaterialSwitch, MaterialTextField } from "@/utils/material";
import styles from "@/pages/chat/css/changePasswordDialog.module.scss";
export default function ChangePasswordDialog({ isOpen, onOpenChange }: DialogProps) {
const { user } = useAppState();
const { user } = useUserStore();
const [current, setCurrent] = useState("");
const [next, setNext] = useState("");
@@ -1,13 +1,13 @@
import { useState, useEffect } from "react";
import { useImmer } from "use-immer";
import { MaterialList, MaterialListItem, MaterialButton, MaterialCircularProgress } from "@/utils/material";
import { useAppState } from "@/pages/chat/state";
import { useUserStore } from "@/state/user";
import { listDevices, revokeDevice, logoutAllOtherDevices, type DeviceInfo } from "@/core/api/account/devices";
import { confirm } from "mdui/functions/confirm";
import styles from "@/pages/chat/css/settings-dialog.module.scss";
export function DevicesPanel() {
const { user } = useAppState();
const { user } = useUserStore();
const authToken = user?.authToken ?? null;
const [devices, updateDevices] = useImmer<DeviceInfo[]>([]);
const [devicesLoading, setDevicesLoading] = useState(false);
@@ -1,13 +1,13 @@
import { useState, useRef } from "react";
import { MaterialList, MaterialListItem, MaterialSwitch, type MDUISwitch } from "@/utils/material";
import { useAppState } from "@/pages/chat/state";
import { useUserStore } from "@/state/user";
import { initialize, subscribe, unsubscribe, isSupported } from "@/core/push-notifications/push-notifications";
import { isElectron } from "@/core/electron/electron";
import { unsubscribeFromPush } from "@/core/api/push";
import styles from "@/pages/chat/css/settings-dialog.module.scss";
export function NotificationsPanel() {
const { user } = useAppState();
const { user } = useUserStore();
const authToken = user?.authToken ?? null;
const [pushEnabled, setPushEnabled] = useState(false);
const [loading, setLoading] = useState(false);