From 1bf2c8faf937099478dae415ece16734a5912ccd Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Sun, 16 Jun 2024 16:28:19 -0300 Subject: [PATCH] feat: replace context with slice --- src/main/events/auth/signout.ts | 7 +- src/renderer/src/app.tsx | 18 +++++ .../components/sidebar/sidebar-profile.tsx | 5 +- .../src/components/sidebar/sidebar.tsx | 5 +- .../context/user-auth/user-auth.context.tsx | 73 ------------------- .../user-auth/user-auth.context.types.ts | 8 -- src/renderer/src/features/index.ts | 1 + src/renderer/src/features/user-auth-slice.ts | 22 ++++++ src/renderer/src/hooks/use-user-auth.ts | 33 +++++++++ src/renderer/src/pages/user/user-content.tsx | 8 +- src/renderer/src/pages/user/user.tsx | 21 +++--- src/renderer/src/store.ts | 2 + 12 files changed, 93 insertions(+), 110 deletions(-) delete mode 100644 src/renderer/src/context/user-auth/user-auth.context.tsx delete mode 100644 src/renderer/src/context/user-auth/user-auth.context.types.ts create mode 100644 src/renderer/src/features/user-auth-slice.ts create mode 100644 src/renderer/src/hooks/use-user-auth.ts diff --git a/src/main/events/auth/signout.ts b/src/main/events/auth/signout.ts index fc8b9567..3294088a 100644 --- a/src/main/events/auth/signout.ts +++ b/src/main/events/auth/signout.ts @@ -1,17 +1,12 @@ import { userAuthRepository } from "@main/repository"; import { registerEvent } from "../register-event"; import { HydraApi } from "@main/services/hydra-api"; -import { WindowManager } from "@main/services"; const signout = async (_event: Electron.IpcMainInvokeEvent): Promise => { await Promise.all([ userAuthRepository.delete({ id: 1 }), HydraApi.post("/auth/logout"), - ]).finally(() => { - if (WindowManager.mainWindow) { - WindowManager.mainWindow.webContents.send("on-signout"); - } - }); + ]); }; registerEvent("signout", signout); diff --git a/src/renderer/src/app.tsx b/src/renderer/src/app.tsx index 67df3084..7a9770e4 100644 --- a/src/renderer/src/app.tsx +++ b/src/renderer/src/app.tsx @@ -19,6 +19,7 @@ import { toggleDraggingDisabled, closeToast, } from "@renderer/features"; +import { useUserAuth } from "./hooks/use-user-auth"; export interface AppProps { children: React.ReactNode; @@ -67,6 +68,23 @@ export function App() { }; }, [clearDownload, setLastPacket, updateLibrary]); + const { updateUserAuth, clearUserAuth } = useUserAuth(); + + useEffect(() => { + const listeners = [ + window.electron.onSignIn(() => { + updateUserAuth(); + }), + window.electron.onSignOut(() => { + clearUserAuth(); + }), + ]; + + return () => { + listeners.forEach((unsubscribe) => unsubscribe()); + }; + }, []); + const handleSearch = useCallback( (query: string) => { dispatch(setSearch(query)); diff --git a/src/renderer/src/components/sidebar/sidebar-profile.tsx b/src/renderer/src/components/sidebar/sidebar-profile.tsx index d1fc8301..4771e032 100644 --- a/src/renderer/src/components/sidebar/sidebar-profile.tsx +++ b/src/renderer/src/components/sidebar/sidebar-profile.tsx @@ -1,13 +1,12 @@ -import { useContext } from "react"; import { useNavigate } from "react-router-dom"; import { PersonIcon } from "@primer/octicons-react"; -import { userAuthContext } from "@renderer/context/user-auth/user-auth.context"; import * as styles from "./sidebar.css"; +import { useUserAuth } from "@renderer/hooks/use-user-auth"; export function SidebarProfile() { const navigate = useNavigate(); - const { userAuth, isLoading } = useContext(userAuthContext); + const { userAuth, isLoading } = useUserAuth(); const handleClickProfile = () => { navigate(`/user/${userAuth!.id}`); diff --git a/src/renderer/src/components/sidebar/sidebar.tsx b/src/renderer/src/components/sidebar/sidebar.tsx index 1bc254e6..5fb20577 100644 --- a/src/renderer/src/components/sidebar/sidebar.tsx +++ b/src/renderer/src/components/sidebar/sidebar.tsx @@ -14,7 +14,6 @@ import { buildGameDetailsPath } from "@renderer/helpers"; import SteamLogo from "@renderer/assets/steam-logo.svg?react"; import { SidebarProfile } from "./sidebar-profile"; -import { UserAuthContextProvider } from "@renderer/context/user-auth/user-auth.context"; const SIDEBAR_MIN_WIDTH = 200; const SIDEBAR_INITIAL_WIDTH = 250; @@ -155,9 +154,7 @@ export function Sidebar() { maxWidth: sidebarWidth, }} > - - - +
({ - userAuth: null, - isLoading: false, - signout: async () => {}, - updateMe: async () => {}, -}); - -const { Provider } = userAuthContext; -export const { Consumer: UserAuthContextConsumer } = userAuthContext; - -export interface UserAuthContextProps { - children: React.ReactNode; -} - -export function UserAuthContextProvider({ children }: UserAuthContextProps) { - const [userAuth, setUserAuth] = useState(null); - const [isLoading, setIsLoading] = useState(false); - - const updateMe = () => { - setIsLoading(true); - - return window.electron - .getMe() - .then((user) => { - setUserAuth(user); - }) - .finally(() => { - setIsLoading(false); - }); - }; - - useEffect(() => { - updateMe(); - }, []); - - useEffect(() => { - const listeners = [ - window.electron.onSignIn(() => { - updateMe(); - }), - window.electron.onSignOut(() => { - setUserAuth(null); - }), - ]; - - return () => { - listeners.forEach((unsubscribe) => unsubscribe()); - }; - }, []); - - const signout = () => { - return window.electron.signout().finally(() => { - setUserAuth(null); - }); - }; - - return ( - - {children} - - ); -} diff --git a/src/renderer/src/context/user-auth/user-auth.context.types.ts b/src/renderer/src/context/user-auth/user-auth.context.types.ts deleted file mode 100644 index 389da1eb..00000000 --- a/src/renderer/src/context/user-auth/user-auth.context.types.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { UserAuth } from "@types"; - -export interface UserAuthContext { - userAuth: UserAuth | null; - isLoading: boolean; - updateMe: () => Promise; - signout: () => Promise; -} diff --git a/src/renderer/src/features/index.ts b/src/renderer/src/features/index.ts index 12853619..d7b75692 100644 --- a/src/renderer/src/features/index.ts +++ b/src/renderer/src/features/index.ts @@ -4,3 +4,4 @@ export * from "./use-preferences-slice"; export * from "./download-slice"; export * from "./window-slice"; export * from "./toast-slice"; +export * from "./user-auth-slice"; diff --git a/src/renderer/src/features/user-auth-slice.ts b/src/renderer/src/features/user-auth-slice.ts new file mode 100644 index 00000000..0daf3407 --- /dev/null +++ b/src/renderer/src/features/user-auth-slice.ts @@ -0,0 +1,22 @@ +import { PayloadAction, createSlice } from "@reduxjs/toolkit"; +import type { UserAuth } from "@types"; + +export interface UserAuthState { + userAuth: UserAuth | null; +} + +const initialState: UserAuthState = { + userAuth: null, +}; + +export const userAuthSlice = createSlice({ + name: "user-auth", + initialState, + reducers: { + setUserAuth: (state, userAuth: PayloadAction) => { + state.userAuth = userAuth.payload; + }, + }, +}); + +export const { setUserAuth } = userAuthSlice.actions; diff --git a/src/renderer/src/hooks/use-user-auth.ts b/src/renderer/src/hooks/use-user-auth.ts new file mode 100644 index 00000000..29b15931 --- /dev/null +++ b/src/renderer/src/hooks/use-user-auth.ts @@ -0,0 +1,33 @@ +import { useCallback, useState } from "react"; +import { useAppDispatch, useAppSelector } from "./redux"; +import { setUserAuth } from "@renderer/features"; + +export function useUserAuth() { + const dispatch = useAppDispatch(); + + const [isLoading, setIsLoading] = useState(false); + + const { userAuth } = useAppSelector((state) => state.userAuth); + + const signOut = useCallback(async () => { + dispatch(setUserAuth(null)); + return window.electron.signout(); + }, [dispatch]); + + const updateUserAuth = useCallback(async () => { + setIsLoading(true); + + return window.electron + .getMe() + .then((userAuth) => dispatch(setUserAuth(userAuth))) + .finally(() => { + setIsLoading(false); + }); + }, [dispatch]); + + const clearUserAuth = useCallback(async () => { + dispatch(setUserAuth(null)); + }, [dispatch]); + + return { userAuth, isLoading, updateUserAuth, signOut, clearUserAuth }; +} diff --git a/src/renderer/src/pages/user/user-content.tsx b/src/renderer/src/pages/user/user-content.tsx index 89babe73..23b998df 100644 --- a/src/renderer/src/pages/user/user-content.tsx +++ b/src/renderer/src/pages/user/user-content.tsx @@ -2,7 +2,7 @@ import { ProfileGame, UserProfile } from "@types"; import cn from "classnames"; import * as styles from "./user.css"; import { SPACING_UNIT, vars } from "@renderer/theme.css"; -import { useContext, useMemo } from "react"; +import { useMemo } from "react"; import { useTranslation } from "react-i18next"; import SteamLogo from "@renderer/assets/steam-logo.svg?react"; import { useDate } from "@renderer/hooks"; @@ -10,7 +10,7 @@ import { useNavigate } from "react-router-dom"; import { buildGameDetailsPath } from "@renderer/helpers"; import { PersonIcon } from "@primer/octicons-react"; import { Button } from "@renderer/components"; -import { userAuthContext } from "@renderer/context/user-auth/user-auth.context"; +import { useUserAuth } from "@renderer/hooks/use-user-auth"; const MAX_MINUTES_TO_SHOW_IN_PLAYTIME = 120; export interface ProfileContentProps { @@ -20,7 +20,7 @@ export interface ProfileContentProps { export const UserContent = ({ userProfile }: ProfileContentProps) => { const { t, i18n } = useTranslation("user_profile"); - const { userAuth, signout } = useContext(userAuthContext); + const { userAuth, signOut } = useUserAuth(); const navigate = useNavigate(); @@ -54,7 +54,7 @@ export const UserContent = ({ userProfile }: ProfileContentProps) => { }; const handleSignout = async () => { - await signout(); + await signOut(); navigate("/"); }; diff --git a/src/renderer/src/pages/user/user.tsx b/src/renderer/src/pages/user/user.tsx index 6ff48474..01bc2831 100644 --- a/src/renderer/src/pages/user/user.tsx +++ b/src/renderer/src/pages/user/user.tsx @@ -8,7 +8,6 @@ import { UserContent } from "./user-content"; import { SkeletonTheme } from "react-loading-skeleton"; import { vars } from "@renderer/theme.css"; import * as styles from "./user.css"; -import { UserAuthContextProvider } from "@renderer/context/user-auth/user-auth.context"; export const User = () => { const { username } = useParams(); @@ -26,16 +25,14 @@ export const User = () => { }, [dispatch, username]); return ( - - -
- {userProfile ? ( - - ) : ( - - )} -
-
-
+ +
+ {userProfile ? ( + + ) : ( + + )} +
+
); }; diff --git a/src/renderer/src/store.ts b/src/renderer/src/store.ts index a321ee4f..589fa17f 100644 --- a/src/renderer/src/store.ts +++ b/src/renderer/src/store.ts @@ -6,6 +6,7 @@ import { searchSlice, userPreferencesSlice, toastSlice, + userAuthSlice, } from "@renderer/features"; export const store = configureStore({ @@ -16,6 +17,7 @@ export const store = configureStore({ userPreferences: userPreferencesSlice.reducer, download: downloadSlice.reducer, toast: toastSlice.reducer, + userAuth: userAuthSlice.reducer, }, });