chore: adjust initial states

This commit is contained in:
Steven 2023-09-10 23:44:06 +08:00
parent 3ad0832516
commit b6d1ded668
12 changed files with 143 additions and 222 deletions

View file

@ -8,6 +8,7 @@
},
"packageManager": "pnpm@8.7.0",
"dependencies": {
"@bufbuild/protobuf": "^1.3.1",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@mui/joy": "5.0.0-beta.2",

View file

@ -5,6 +5,9 @@ settings:
excludeLinksFromLockfile: false
dependencies:
'@bufbuild/protobuf':
specifier: ^1.3.1
version: 1.3.1
'@emotion/react':
specifier: ^11.11.1
version: 11.11.1(@types/react@18.2.21)(react@18.2.0)
@ -407,6 +410,10 @@ packages:
'@babel/helper-validator-identifier': 7.22.5
to-fast-properties: 2.0.0
/@bufbuild/protobuf@1.3.1:
resolution: {integrity: sha512-BUyJWutgP2S8K/1NphOJokuwDckXS4qI2T1pGZAlkFdZchWae3jm6fCdkcGbLlM1QLOcNFFePd+7Feo4BYGrJQ==}
dev: false
/@emotion/babel-plugin@11.11.0:
resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==}
dependencies:

View file

@ -1,20 +1,44 @@
import { useColorScheme } from "@mui/joy";
import { Suspense, useEffect } from "react";
import { Toaster } from "react-hot-toast";
import { Suspense, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { RouterProvider } from "react-router-dom";
import { Outlet } from "react-router-dom";
import storage from "./helpers/storage";
import { getSystemColorScheme } from "./helpers/utils";
import Loading from "./pages/Loading";
import router from "./router";
import { useGlobalStore } from "./store/module";
import { initialGlobalState, initialUserState, useGlobalStore } from "./store/module";
import { useUserV1Store } from "./store/v1";
const App = () => {
const { i18n } = useTranslation();
const globalStore = useGlobalStore();
const { mode, setMode } = useColorScheme();
const userV1Store = useUserV1Store();
const [loading, setLoading] = useState(true);
const { appearance, locale, systemStatus } = globalStore.state;
useEffect(() => {
const initialState = async () => {
try {
await initialGlobalState();
} catch (error) {
// do nothing
}
try {
const user = await initialUserState();
if (user) {
await userV1Store.getOrFetchUserByUsername(user.username);
}
} catch (error) {
// do nothing.
}
setLoading(false);
};
initialState();
}, []);
useEffect(() => {
const darkMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
const handleColorSchemeChange = (e: MediaQueryListEvent) => {
@ -85,10 +109,11 @@ const App = () => {
}
}, [mode]);
return (
return loading ? (
<Loading />
) : (
<Suspense fallback={<Loading />}>
<RouterProvider router={router} />
<Toaster position="top-right" />
<Outlet />
</Suspense>
);
};

View file

@ -1,12 +1,14 @@
import { CssVarsProvider } from "@mui/joy";
import { createRoot } from "react-dom/client";
import { Toaster } from "react-hot-toast";
import { Provider } from "react-redux";
import App from "./App";
import { RouterProvider } from "react-router-dom";
import "./css/global.css";
import "./css/tailwind.css";
import "./helpers/polyfill";
import "./i18n";
import "./less/code-highlight.less";
import router from "./router";
import store from "./store";
import theme from "./theme";
@ -15,7 +17,8 @@ const root = createRoot(container as HTMLElement);
root.render(
<Provider store={store}>
<CssVarsProvider theme={theme}>
<App />
<RouterProvider router={router} />
<Toaster position="top-right" />
</CssVarsProvider>
</Provider>
);

View file

@ -4,6 +4,7 @@ import ArchivedMemo from "@/components/ArchivedMemo";
import Empty from "@/components/Empty";
import MemoFilter from "@/components/MemoFilter";
import MobileHeader from "@/components/MobileHeader";
import useCurrentUser from "@/hooks/useCurrentUser";
import useLoading from "@/hooks/useLoading";
import { useFilterStore, useMemoStore } from "@/store/module";
import { useTranslate } from "@/utils/i18n";
@ -11,6 +12,7 @@ import "@/less/archived.less";
const Archived = () => {
const t = useTranslate();
const user = useCurrentUser();
const memoStore = useMemoStore();
const loadingState = useLoading();
const [archivedMemos, setArchivedMemos] = useState<Memo[]>([]);
@ -19,6 +21,12 @@ const Archived = () => {
const filter = filterStore.state;
const { text: textQuery } = filter;
useEffect(() => {
if (!user) {
window.location.href = "/auth";
}
}, []);
useEffect(() => {
memoStore
.fetchArchivedMemos()

View file

@ -11,6 +11,7 @@ import showPreviewImageDialog from "@/components/PreviewImageDialog";
import DatePicker from "@/components/kit/DatePicker";
import { DAILY_TIMESTAMP, DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
import { convertToMillis, getDateStampByDate, getNormalizedDateString, getTimeStampByDate, isFutureDate } from "@/helpers/datetime";
import useCurrentUser from "@/hooks/useCurrentUser";
import i18n from "@/i18n";
import toImage from "@/labs/html2image";
import { useMemoStore, useUserStore } from "@/store/module";
@ -20,6 +21,7 @@ const DailyReview = () => {
const t = useTranslate();
const memoStore = useMemoStore();
const userStore = useUserStore();
const user = useCurrentUser();
const { localSetting } = userStore.state.user as User;
const [currentDateStamp, setCurrentDateStamp] = useState(getDateStampByDate(getNormalizedDateString()));
const [showDatePicker, toggleShowDatePicker] = useToggle(false);
@ -37,6 +39,12 @@ const DailyReview = () => {
})
.sort((a, b) => getTimeStampByDate(a.displayTs) - getTimeStampByDate(b.displayTs));
useEffect(() => {
if (!user) {
window.location.href = "/auth";
}
}, []);
useEffect(() => {
let offset = 0;
const fetchMoreMemos = async () => {

View file

@ -1,34 +1,29 @@
import { useEffect } from "react";
import { toast } from "react-hot-toast";
import HomeSidebar from "@/components/HomeSidebar";
import MemoEditor from "@/components/MemoEditor";
import MemoFilter from "@/components/MemoFilter";
import MemoList from "@/components/MemoList";
import MobileHeader from "@/components/MobileHeader";
import useCurrentUser from "@/hooks/useCurrentUser";
import { useGlobalStore, useUserStore } from "@/store/module";
import { useUserV1Store } from "@/store/v1";
import { useTranslate } from "@/utils/i18n";
const Home = () => {
const t = useTranslate();
const globalStore = useGlobalStore();
const userStore = useUserStore();
const userV1Store = useUserV1Store();
const user = userStore.state.user;
const user = useCurrentUser();
useEffect(() => {
const currentUsername = userStore.getCurrentUsername();
userV1Store.getOrFetchUserByUsername(currentUsername).catch((error) => {
console.error(error);
toast.error(t("message.user-not-found"));
});
}, [userStore.getCurrentUsername()]);
useEffect(() => {
if (user?.setting.locale) {
globalStore.setLocale(user.setting.locale);
if (user) {
return;
}
}, [user?.setting.locale]);
const systemStatus = globalStore.state.systemStatus;
if (systemStatus.disablePublicMemos) {
window.location.href = "/auth";
} else {
window.location.href = "/explore";
}
}, []);
return (
<div className="w-full flex flex-row justify-start items-start">

View file

@ -11,6 +11,7 @@ import ResourceItem from "@/components/ResourceItem";
import ResourceSearchBar from "@/components/ResourceSearchBar";
import Dropdown from "@/components/kit/Dropdown";
import { DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
import useCurrentUser from "@/hooks/useCurrentUser";
import useEvent from "@/hooks/useEvent";
import useLoading from "@/hooks/useLoading";
import { useResourceStore } from "@/store/module";
@ -19,6 +20,7 @@ import { useTranslate } from "@/utils/i18n";
const ResourcesDashboard = () => {
const t = useTranslate();
const loadingState = useLoading();
const user = useCurrentUser();
const resourceStore = useResourceStore();
const resources = resourceStore.state.resources;
const [selectedList, setSelectedList] = useState<Array<ResourceId>>([]);
@ -27,6 +29,12 @@ const ResourcesDashboard = () => {
const [dragActive, setDragActive] = useState(false);
const [isComplete, setIsComplete] = useState<boolean>(false);
useEffect(() => {
if (!user) {
window.location.href = "/auth";
}
}, []);
useEffect(() => {
resourceStore
.fetchResourceListWithLimit(DEFAULT_MEMO_LIMIT)

View file

@ -1,5 +1,6 @@
import { Option, Select } from "@mui/joy";
import { useState } from "react";
import { isEqual } from "lodash-es";
import { useEffect, useState } from "react";
import BetaBadge from "@/components/BetaBadge";
import Icon from "@/components/Icon";
import MobileHeader from "@/components/MobileHeader";
@ -9,7 +10,7 @@ import PreferencesSection from "@/components/Settings/PreferencesSection";
import SSOSection from "@/components/Settings/SSOSection";
import StorageSection from "@/components/Settings/StorageSection";
import SystemSection from "@/components/Settings/SystemSection";
import { useUserStore } from "@/store/module";
import useCurrentUser from "@/hooks/useCurrentUser";
import { useTranslate } from "@/utils/i18n";
import "@/less/setting.less";
@ -21,12 +22,17 @@ interface State {
const Setting = () => {
const t = useTranslate();
const userStore = useUserStore();
const user = userStore.state.user;
const user = useCurrentUser();
const [state, setState] = useState<State>({
selectedSection: "my-account",
});
const isHost = user?.role === "HOST";
const isHost = isEqual(user.role, "HOST");
useEffect(() => {
if (!user) {
window.location.href = "/auth";
}
}, []);
const handleSectionSelectorItemClick = (settingSection: SettingSection) => {
setState({

View file

@ -1,12 +1,11 @@
import { lazy } from "react";
import { createBrowserRouter, redirect } from "react-router-dom";
import { isNullorUndefined } from "@/helpers/utils";
import { createBrowserRouter } from "react-router-dom";
import App from "@/App";
import Archived from "@/pages/Archived";
import DailyReview from "@/pages/DailyReview";
import ResourcesDashboard from "@/pages/ResourcesDashboard";
import Setting from "@/pages/Setting";
import store from "@/store";
import { initialGlobalState, initialUserState } from "@/store/module";
import { initialGlobalState } from "@/store/module";
const Root = lazy(() => import("@/layouts/Root"));
const Auth = lazy(() => import("@/pages/Auth"));
@ -35,210 +34,70 @@ const initialGlobalStateLoader = (() => {
})();
const router = createBrowserRouter([
{
path: "/auth",
element: <Auth />,
loader: async () => {
await initialGlobalStateLoader();
return null;
},
},
{
path: "/auth/callback",
element: <AuthCallback />,
},
{
path: "/",
element: <Root />,
element: <App />,
children: [
{
path: "",
element: <Home />,
path: "/auth",
element: <Auth />,
loader: async () => {
await initialGlobalStateLoader();
try {
await initialUserState();
} catch (error) {
// do nth
}
const { user } = store.getState().user;
const { systemStatus } = store.getState().global;
// if user is authenticated, then show home
if (!isNullorUndefined(user)) {
return null;
}
// if user is anonymous, then redirect to auth if disabled public memos, else redirect to explore
if (systemStatus.disablePublicMemos) {
return redirect("/auth");
}
return redirect("/explore");
},
},
{
path: "explore",
element: <Explore />,
loader: async () => {
await initialGlobalStateLoader();
try {
await initialUserState();
} catch (error) {
// do nth
}
const { user } = store.getState().user;
const { systemStatus } = store.getState().global;
if (isNullorUndefined(user) && systemStatus.disablePublicMemos) {
return redirect("/auth");
}
return null;
},
},
{
path: "review",
element: <DailyReview />,
loader: async () => {
await initialGlobalStateLoader();
try {
await initialUserState();
} catch (error) {
// do nth
}
const { user } = store.getState().user;
if (isNullorUndefined(user)) {
return redirect("/auth");
}
return null;
},
path: "/auth/callback",
element: <AuthCallback />,
},
{
path: "resources",
element: <ResourcesDashboard />,
loader: async () => {
await initialGlobalStateLoader();
try {
await initialUserState();
} catch (error) {
// do nth
}
const { user } = store.getState().user;
if (isNullorUndefined(user)) {
return redirect("/auth");
}
return null;
},
path: "/",
element: <Root />,
children: [
{
path: "",
element: <Home />,
},
{
path: "explore",
element: <Explore />,
},
{
path: "review",
element: <DailyReview />,
},
{
path: "resources",
element: <ResourcesDashboard />,
},
{
path: "archived",
element: <Archived />,
},
{
path: "setting",
element: <Setting />,
},
],
},
{
path: "archived",
element: <Archived />,
loader: async () => {
await initialGlobalStateLoader();
try {
await initialUserState();
} catch (error) {
// do nth
}
const { user } = store.getState().user;
if (isNullorUndefined(user)) {
return redirect("/auth");
}
return null;
},
path: "/m/:memoId",
element: <MemoDetail />,
},
{
path: "setting",
element: <Setting />,
loader: async () => {
await initialGlobalStateLoader();
try {
await initialUserState();
} catch (error) {
// do nth
}
const { user } = store.getState().user;
if (isNullorUndefined(user)) {
return redirect("/auth");
}
return null;
},
path: "/m/:memoId/embed",
element: <EmbedMemo />,
},
{
path: "/u/:username",
element: <UserProfile />,
},
{
path: "*",
element: <NotFound />,
},
],
},
{
path: "/m/:memoId",
element: <MemoDetail />,
loader: async () => {
await initialGlobalStateLoader();
try {
await initialUserState();
} catch (error) {
// do nth
}
const { user } = store.getState().user;
const { systemStatus } = store.getState().global;
if (isNullorUndefined(user) && systemStatus.disablePublicMemos) {
return redirect("/auth");
}
return null;
},
},
{
path: "/m/:memoId/embed",
element: <EmbedMemo />,
loader: async () => {
await initialGlobalStateLoader();
try {
await initialUserState();
} catch (error) {
// do nth
}
return null;
},
},
{
path: "/u/:username",
element: <UserProfile />,
loader: async () => {
await initialGlobalStateLoader();
try {
await initialUserState();
} catch (error) {
// do nth
}
return null;
},
},
{
path: "*",
element: <NotFound />,
loader: async () => {
await initialGlobalStateLoader();
return null;
},
},
]);
export default router;

View file

@ -68,6 +68,7 @@ export const initialUserState = async () => {
if (user.setting.appearance) {
store.dispatch(setAppearance(user.setting.appearance));
}
return user;
}
};

View file

@ -39,7 +39,7 @@ const useUserV1Store = create<UserV1Store>()((set, get) => ({
},
getUserByUsername: (username: string) => {
const userMap = get().userMapByUsername;
return userMap[username] as User;
return userMap[username];
},
updateUser: async (user: Partial<User>, updateMask: string[]) => {
const {