2023-12-06 18:24:43 +00:00
|
|
|
import "@/setup/pwa";
|
2023-03-19 17:01:08 +00:00
|
|
|
import "core-js/stable";
|
2023-11-19 19:03:35 +00:00
|
|
|
import "./stores/__old/imports";
|
|
|
|
import "@/setup/ga";
|
2023-11-26 15:04:23 +00:00
|
|
|
import "@/assets/css/index.css";
|
2023-11-19 19:03:35 +00:00
|
|
|
|
2023-12-24 01:58:07 +00:00
|
|
|
import { StrictMode, Suspense, useCallback } from "react";
|
2023-09-01 13:37:03 +00:00
|
|
|
import type { ReactNode } from "react";
|
2023-12-23 05:24:43 +00:00
|
|
|
import { createRoot } from "react-dom/client";
|
2023-10-14 17:28:27 +00:00
|
|
|
import { HelmetProvider } from "react-helmet-async";
|
2023-11-26 15:04:23 +00:00
|
|
|
import { useTranslation } from "react-i18next";
|
2023-02-19 15:05:19 +00:00
|
|
|
import { BrowserRouter, HashRouter } from "react-router-dom";
|
2023-11-05 16:56:56 +00:00
|
|
|
import { useAsync } from "react-use";
|
2023-01-07 20:36:18 +00:00
|
|
|
|
2023-11-26 15:04:23 +00:00
|
|
|
import { Button } from "@/components/buttons/Button";
|
2023-11-24 16:11:00 +00:00
|
|
|
import { Icon, Icons } from "@/components/Icon";
|
|
|
|
import { Loading } from "@/components/layout/Loading";
|
2023-12-12 23:56:15 +00:00
|
|
|
import { useAuth } from "@/hooks/auth/useAuth";
|
2023-11-05 16:56:56 +00:00
|
|
|
import { useAuthRestore } from "@/hooks/auth/useAuthRestore";
|
2023-11-24 16:11:00 +00:00
|
|
|
import { useBackendUrl } from "@/hooks/auth/useBackendUrl";
|
2023-10-24 18:34:54 +00:00
|
|
|
import { ErrorBoundary } from "@/pages/errors/ErrorBoundary";
|
2023-11-05 16:56:56 +00:00
|
|
|
import { MigrationPart } from "@/pages/parts/migrations/MigrationPart";
|
2023-11-24 16:11:00 +00:00
|
|
|
import { LargeTextPart } from "@/pages/parts/util/LargeTextPart";
|
2023-01-07 20:36:18 +00:00
|
|
|
import App from "@/setup/App";
|
2023-10-21 20:14:54 +00:00
|
|
|
import { conf } from "@/setup/config";
|
2023-11-24 16:11:00 +00:00
|
|
|
import { useAuthStore } from "@/stores/auth";
|
2023-11-19 19:03:35 +00:00
|
|
|
import { BookmarkSyncer } from "@/stores/bookmarks/BookmarkSyncer";
|
2024-01-03 19:06:08 +00:00
|
|
|
import { changeAppLanguage, useLanguageStore } from "@/stores/language";
|
2023-11-19 19:47:20 +00:00
|
|
|
import { ProgressSyncer } from "@/stores/progress/ProgressSyncer";
|
2023-11-24 16:11:00 +00:00
|
|
|
import { SettingsSyncer } from "@/stores/subtitles/SettingsSyncer";
|
2023-12-09 16:37:51 +00:00
|
|
|
import { ThemeProvider } from "@/stores/theme";
|
2023-12-19 19:41:56 +00:00
|
|
|
import { TurnstileProvider } from "@/stores/turnstile";
|
2023-10-31 18:07:47 +00:00
|
|
|
|
2023-01-25 20:44:15 +00:00
|
|
|
import { initializeChromecast } from "./setup/chromecast";
|
2023-10-31 18:07:47 +00:00
|
|
|
import { initializeOldStores } from "./stores/__old/migrations";
|
2022-12-29 17:25:57 +00:00
|
|
|
|
|
|
|
// initialize
|
2023-01-25 20:44:15 +00:00
|
|
|
initializeChromecast();
|
2021-07-13 22:31:37 +00:00
|
|
|
|
2023-11-18 14:12:31 +00:00
|
|
|
function LoadingScreen(props: { type: "user" | "lazy" }) {
|
2023-11-26 15:04:23 +00:00
|
|
|
const mapping = {
|
|
|
|
user: "screens.loadingUser",
|
|
|
|
lazy: "screens.loadingApp",
|
|
|
|
};
|
|
|
|
const { t } = useTranslation();
|
2023-11-24 16:11:00 +00:00
|
|
|
return (
|
2023-11-26 15:04:23 +00:00
|
|
|
<LargeTextPart iconSlot={<Loading />}>
|
|
|
|
{t(mapping[props.type] ?? "unknown.translation")}
|
|
|
|
</LargeTextPart>
|
2023-11-24 16:11:00 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function ErrorScreen(props: {
|
|
|
|
children: ReactNode;
|
|
|
|
showResetButton?: boolean;
|
2023-12-12 23:56:15 +00:00
|
|
|
showLogoutButton?: boolean;
|
2023-11-24 16:11:00 +00:00
|
|
|
}) {
|
2023-11-26 15:04:23 +00:00
|
|
|
const { t } = useTranslation();
|
2023-12-12 23:56:15 +00:00
|
|
|
const { logout } = useAuth();
|
2023-11-24 16:11:00 +00:00
|
|
|
const setBackendUrl = useAuthStore((s) => s.setBackendUrl);
|
|
|
|
const resetBackend = useCallback(() => {
|
|
|
|
setBackendUrl(null);
|
|
|
|
// eslint-disable-next-line no-restricted-globals
|
|
|
|
location.reload();
|
|
|
|
}, [setBackendUrl]);
|
2023-12-12 23:56:15 +00:00
|
|
|
const logoutFromBackend = useCallback(() => {
|
|
|
|
logout().then(() => {
|
|
|
|
// eslint-disable-next-line no-restricted-globals
|
|
|
|
location.reload();
|
|
|
|
});
|
|
|
|
}, [logout]);
|
2023-11-24 16:11:00 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<LargeTextPart
|
|
|
|
iconSlot={
|
|
|
|
<Icon className="text-type-danger text-2xl" icon={Icons.WARNING} />
|
|
|
|
}
|
|
|
|
>
|
|
|
|
{props.children}
|
|
|
|
{props.showResetButton ? (
|
|
|
|
<div className="mt-6">
|
|
|
|
<Button theme="secondary" onClick={resetBackend}>
|
2023-11-26 15:04:23 +00:00
|
|
|
{t("screens.loadingUserError.reset")}
|
2023-11-24 16:11:00 +00:00
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
) : null}
|
2023-12-12 23:56:15 +00:00
|
|
|
{props.showLogoutButton ? (
|
|
|
|
<div className="mt-6">
|
|
|
|
<Button theme="secondary" onClick={logoutFromBackend}>
|
|
|
|
{t("screens.loadingUserError.logout")}
|
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
) : null}
|
2023-11-24 16:11:00 +00:00
|
|
|
</LargeTextPart>
|
|
|
|
);
|
2023-11-18 14:12:31 +00:00
|
|
|
}
|
|
|
|
|
2023-11-05 16:56:56 +00:00
|
|
|
function AuthWrapper() {
|
|
|
|
const status = useAuthRestore();
|
2023-11-24 16:11:00 +00:00
|
|
|
const backendUrl = conf().BACKEND_URL;
|
|
|
|
const userBackendUrl = useBackendUrl();
|
2023-11-26 15:04:23 +00:00
|
|
|
const { t } = useTranslation();
|
2023-11-05 16:56:56 +00:00
|
|
|
|
2023-12-12 23:56:15 +00:00
|
|
|
const isCustomUrl = backendUrl !== userBackendUrl;
|
|
|
|
|
2023-11-18 14:12:31 +00:00
|
|
|
if (status.loading) return <LoadingScreen type="user" />;
|
2023-11-24 16:11:00 +00:00
|
|
|
if (status.error)
|
|
|
|
return (
|
2023-12-12 23:56:15 +00:00
|
|
|
<ErrorScreen
|
|
|
|
showResetButton={isCustomUrl}
|
|
|
|
showLogoutButton={!isCustomUrl}
|
|
|
|
>
|
2023-11-26 15:04:23 +00:00
|
|
|
{t(
|
2023-12-12 23:56:15 +00:00
|
|
|
isCustomUrl
|
2023-11-26 15:04:23 +00:00
|
|
|
? "screens.loadingUserError.textWithReset"
|
2023-12-23 05:24:43 +00:00
|
|
|
: "screens.loadingUserError.text",
|
2023-11-26 15:04:23 +00:00
|
|
|
)}
|
2023-11-24 16:11:00 +00:00
|
|
|
</ErrorScreen>
|
|
|
|
);
|
2023-11-05 16:56:56 +00:00
|
|
|
return <App />;
|
|
|
|
}
|
|
|
|
|
|
|
|
function MigrationRunner() {
|
|
|
|
const status = useAsync(async () => {
|
2024-01-03 19:06:08 +00:00
|
|
|
changeAppLanguage(useLanguageStore.getState().language);
|
2023-11-05 16:56:56 +00:00
|
|
|
await initializeOldStores();
|
|
|
|
}, []);
|
2023-11-26 15:04:23 +00:00
|
|
|
const { t } = useTranslation();
|
2023-11-05 16:56:56 +00:00
|
|
|
|
|
|
|
if (status.loading) return <MigrationPart />;
|
2023-11-24 16:11:00 +00:00
|
|
|
if (status.error)
|
2023-11-26 15:04:23 +00:00
|
|
|
return <ErrorScreen>{t("screens.migration.failed")}</ErrorScreen>;
|
2023-11-05 16:56:56 +00:00
|
|
|
return <AuthWrapper />;
|
|
|
|
}
|
2023-02-11 23:41:55 +00:00
|
|
|
|
2023-02-19 15:05:19 +00:00
|
|
|
function TheRouter(props: { children: ReactNode }) {
|
|
|
|
const normalRouter = conf().NORMAL_ROUTER;
|
2023-02-19 17:03:54 +00:00
|
|
|
|
|
|
|
if (normalRouter) return <BrowserRouter>{props.children}</BrowserRouter>;
|
|
|
|
return <HashRouter>{props.children}</HashRouter>;
|
2023-02-19 15:05:19 +00:00
|
|
|
}
|
|
|
|
|
2023-12-23 05:24:43 +00:00
|
|
|
const container = document.getElementById("root");
|
|
|
|
const root = createRoot(container!);
|
|
|
|
|
|
|
|
root.render(
|
2023-12-24 01:58:07 +00:00
|
|
|
<StrictMode>
|
|
|
|
<ErrorBoundary>
|
|
|
|
<TurnstileProvider />
|
|
|
|
<HelmetProvider>
|
|
|
|
<Suspense fallback={<LoadingScreen type="lazy" />}>
|
|
|
|
<ThemeProvider applyGlobal>
|
|
|
|
<ProgressSyncer />
|
|
|
|
<BookmarkSyncer />
|
|
|
|
<SettingsSyncer />
|
|
|
|
<TheRouter>
|
|
|
|
<MigrationRunner />
|
|
|
|
</TheRouter>
|
|
|
|
</ThemeProvider>
|
|
|
|
</Suspense>
|
|
|
|
</HelmetProvider>
|
|
|
|
</ErrorBoundary>
|
|
|
|
</StrictMode>,
|
2021-07-13 22:31:37 +00:00
|
|
|
);
|