feat: add disclaimer on first launch

fix: check store hydration before loading pages
fix: check user store before loading pages
This commit is contained in:
Kentai Radiquum 2024-08-11 16:49:39 +05:00
parent a64e4f2036
commit 2c8460c6b0
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
4 changed files with 92 additions and 14 deletions

View file

@ -2,7 +2,6 @@
## Важное ## Важное
- [ ] Уведомление о том что мы не связаны с аниксарт при первом открытии
- [ ] Кнопка сброса всех настроек - [ ] Кнопка сброса всех настроек
- [ ] Список изменений при входе - [ ] Список изменений при входе

View file

@ -1,20 +1,74 @@
"use client"; "use client";
import { useUserStore } from "./store/auth"; import { useUserStore } from "./store/auth";
import { usePreferencesStore } from "./store/preferences";
import { Navbar } from "./components/Navbar/Navbar"; import { Navbar } from "./components/Navbar/Navbar";
import { Inter } from "next/font/google"; import { Inter } from "next/font/google";
import { useEffect } from "react"; import { useEffect, useState } from "react";
import { Button, Modal } from "flowbite-react";
import { Spinner } from "./components/Spinner/Spinner";
const inter = Inter({ subsets: ["latin"] }); const inter = Inter({ subsets: ["latin"] });
export const App = (props) => { export const App = (props) => {
const preferencesStore = usePreferencesStore();
const userStore = useUserStore((state) => state); const userStore = useUserStore((state) => state);
useEffect(() => { useEffect(() => {
userStore.checkAuth(); userStore.checkAuth();
}, []); }, []);
if (!preferencesStore._hasHydrated && !userStore._hasHydrated) {
return (
<body
className={`${inter.className} overflow-x-hidden dark:bg-[#0d1117] dark:text-white h-screen flex justify-center items-center`}
>
<Spinner />
</body>
);
}
if (userStore.state === "loading") {
return (
<body
className={`${inter.className} overflow-x-hidden dark:bg-[#0d1117] dark:text-white h-screen flex justify-center items-center`}
>
<Spinner />
</body>
);
}
return ( return (
<body className={`${inter.className} overflow-x-hidden dark:bg-[#0d1117] dark:text-white`}> <body
className={`${inter.className} overflow-x-hidden dark:bg-[#0d1117] dark:text-white`}
>
<Navbar /> <Navbar />
{props.children} {props.children}
<Modal show={preferencesStore.params.isFirstLaunch}>
<Modal.Header>Внимание</Modal.Header>
<Modal.Body>
<p>
Данный сайт не связан с разработчиками приложения Anixart, это
неофициальная имплементация веб клиента для этого приложения.
<br />
<br />
Используя данный веб-сайт вы принимаете что мы не несём
ответственности за ваш аккаунт.
<br />
<br />
На сайте могут присутствовать ошибки и не доработки, а так-же
отсутствующий функционал.
</p>
</Modal.Body>
<Modal.Footer>
<Button
color={"blue"}
onClick={() => {
preferencesStore.setParams({ isFirstLaunch: false });
}}
>
Принимаю
</Button>
</Modal.Footer>
</Modal>
</body> </body>
); );
}; };

View file

@ -3,26 +3,40 @@ import { create } from "zustand";
import { getJWT, removeJWT, fetchDataViaGet } from "#/api/utils"; import { getJWT, removeJWT, fetchDataViaGet } from "#/api/utils";
interface userState { interface userState {
isAuth: boolean _hasHydrated: boolean;
user: Object | null isAuth: boolean;
token: string | null user: Object | null;
state: string, token: string | null;
login: (user: Object, token: string) => void state: string;
logout: () => void login: (user: Object, token: string) => void;
checkAuth: () => void logout: () => void;
checkAuth: () => void;
} }
export const useUserStore = create<userState>((set, get) => ({ export const useUserStore = create<userState>((set, get) => ({
_hasHydrated: false,
isAuth: false, isAuth: false,
user: null, user: null,
token: null, token: null,
state: "loading", state: "loading",
login: (user: Object, token: string) => { login: (user: Object, token: string) => {
set({ isAuth: true, user: user, token: token, state: "finished" }); set({
isAuth: true,
user: user,
token: token,
state: "finished",
_hasHydrated: true,
});
}, },
logout: () => { logout: () => {
set({ isAuth: false, user: null, token: null, state: "finished" }); set({
isAuth: false,
user: null,
token: null,
state: "finished",
_hasHydrated: true,
});
removeJWT(); removeJWT();
}, },
checkAuth: () => { checkAuth: () => {
@ -37,8 +51,8 @@ export const useUserStore = create<userState>((set, get) => ({
} else { } else {
get().logout(); get().logout();
} }
} };
_checkAuth() _checkAuth();
} else { } else {
get().logout(); get().logout();
} }

View file

@ -3,6 +3,7 @@ import { create } from "zustand";
import { persist } from "zustand/middleware"; import { persist } from "zustand/middleware";
interface preferencesState { interface preferencesState {
_hasHydrated: boolean;
flags: { flags: {
// saveSearchHistory: boolean; // saveSearchHistory: boolean;
saveWatchHistory: boolean; saveWatchHistory: boolean;
@ -16,6 +17,7 @@ interface preferencesState {
// accent: string; // accent: string;
// } // }
}; };
setHasHydrated: (state: boolean) => void;
setFlags: (flags: preferencesState["flags"]) => void; setFlags: (flags: preferencesState["flags"]) => void;
setParams: (params: preferencesState["params"]) => void; setParams: (params: preferencesState["params"]) => void;
} }
@ -23,6 +25,7 @@ interface preferencesState {
export const usePreferencesStore = create<preferencesState>()( export const usePreferencesStore = create<preferencesState>()(
persist( persist(
(set, get) => ({ (set, get) => ({
_hasHydrated: false,
flags: { flags: {
// saveSearchHistory: true, // saveSearchHistory: true,
saveWatchHistory: true, saveWatchHistory: true,
@ -31,6 +34,11 @@ export const usePreferencesStore = create<preferencesState>()(
params: { params: {
isFirstLaunch: true, isFirstLaunch: true,
}, },
setHasHydrated: (state) => {
set({
_hasHydrated: state,
});
},
setFlags(flags) { setFlags(flags) {
set({ flags }); set({ flags });
}, },
@ -40,6 +48,9 @@ export const usePreferencesStore = create<preferencesState>()(
}), }),
{ {
name: "preferences", name: "preferences",
onRehydrateStorage: (state) => {
return () => state.setHasHydrated(true);
},
} }
) )
); );