mirror of
https://github.com/sussy-code/smov.git
synced 2026-05-14 05:40:36 +00:00
Start adding migration pages
This commit is contained in:
parent
4b27aa457f
commit
718acfd76a
6 changed files with 265 additions and 0 deletions
|
|
@ -112,6 +112,7 @@
|
||||||
"pagetitle": "{{title}} - sudo-flix",
|
"pagetitle": "{{title}} - sudo-flix",
|
||||||
"register": "Register",
|
"register": "Register",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
|
"migration": "Migration",
|
||||||
"jip": "Jip"
|
"jip": "Jip"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -197,6 +198,27 @@
|
||||||
"show": "Show"
|
"show": "Show"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"migration": {
|
||||||
|
"start": {
|
||||||
|
"title": "Migrate your data",
|
||||||
|
"explainer": "If you wish to migrate or backup your data, you can do so using the options below. This will allow you to keep your data when you switch backend servers.",
|
||||||
|
"options": {
|
||||||
|
"or": "or",
|
||||||
|
"direct": {
|
||||||
|
"description": "This will directly migrate your data to the new server. This is the fastest option. <br /><br />This option allows you to keep your passphrase the same!",
|
||||||
|
"title": "Direct migration",
|
||||||
|
"quality": "Easiest and fastest",
|
||||||
|
"action": "Transfer data"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"description": "This will download your data to your device. You can then upload it to the new server or just keep it for safekeeping.",
|
||||||
|
"title": "Download data",
|
||||||
|
"quality": "More technical",
|
||||||
|
"action": "Download data"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"navigation": {
|
"navigation": {
|
||||||
"banner": {
|
"banner": {
|
||||||
"offline": "Check your internet connection, silly goose! 🦢"
|
"offline": "Check your internet connection, silly goose! 🦢"
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ export enum Icons {
|
||||||
BRUSH = "brush",
|
BRUSH = "brush",
|
||||||
UPLOAD = "upload",
|
UPLOAD = "upload",
|
||||||
WEB = "web",
|
WEB = "web",
|
||||||
|
CLOUD_ARROW_UP = "cloud_arrow_up",
|
||||||
|
FILE_ARROW_DOWN = "file_arrow_down",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IconProps {
|
export interface IconProps {
|
||||||
|
|
@ -153,6 +155,8 @@ const iconList: Record<Icons, string> = {
|
||||||
<path d="M22.0182 15.0781C20.9582 15.403 18.7915 16.0311 16.4781 16.4781C16.0311 18.7915 15.403 20.9581 15.0781 22.0182L15.0702 22.044C18.4002 21.0274 21.0274 18.4002 22.044 15.0702L22.0182 15.0781Z" fill="currentColor"/>
|
<path d="M22.0182 15.0781C20.9582 15.403 18.7915 16.0311 16.4781 16.4781C16.0311 18.7915 15.403 20.9581 15.0781 22.0182L15.0702 22.044C18.4002 21.0274 21.0274 18.4002 22.044 15.0702L22.0182 15.0781Z" fill="currentColor"/>
|
||||||
<path d="M1.6103 13.323C1.64665 13.3277 1.67628 13.3327 1.68611 13.3349C1.69472 13.337 1.70821 13.3406 1.7131 13.3419L1.72391 13.345L1.72973 13.3468L1.73585 13.3487L1.74098 13.3503C1.7381 13.3494 1.67976 13.3348 1.6103 13.323Z" fill="currentColor"/>
|
<path d="M1.6103 13.323C1.64665 13.3277 1.67628 13.3327 1.68611 13.3349C1.69472 13.337 1.70821 13.3406 1.7131 13.3419L1.72391 13.345L1.72973 13.3468L1.73585 13.3487L1.74098 13.3503C1.7381 13.3494 1.67976 13.3348 1.6103 13.323Z" fill="currentColor"/>
|
||||||
</svg>`,
|
</svg>`,
|
||||||
|
cloud_arrow_up: `<svg xmlns="http://www.w3.org/2000/svg" height="1em" width="1em" viewBox="0 0 640 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M144 480C64.5 480 0 415.5 0 336c0-62.8 40.2-116.2 96.2-135.9c-.1-2.7-.2-5.4-.2-8.1c0-88.4 71.6-160 160-160c59.3 0 111 32.2 138.7 80.2C409.9 102 428.3 96 448 96c53 0 96 43 96 96c0 12.2-2.3 23.8-6.4 34.6C596 238.4 640 290.1 640 352c0 70.7-57.3 128-128 128H144zm79-217c-9.4 9.4-9.4 24.6 0 33.9s24.6 9.4 33.9 0l39-39V392c0 13.3 10.7 24 24 24s24-10.7 24-24V257.9l39 39c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-80-80c-9.4-9.4-24.6-9.4-33.9 0l-80 80z" fill="currentColor"/></svg>`,
|
||||||
|
file_arrow_down: `<svg xmlns="http://www.w3.org/2000/svg" height="1em" width="1em" viewBox="0 0 384 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M64 0C28.7 0 0 28.7 0 64V448c0 35.3 28.7 64 64 64H320c35.3 0 64-28.7 64-64V160H256c-17.7 0-32-14.3-32-32V0H64zM256 0V128H384L256 0zM216 232V334.1l31-31c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-72 72c-9.4 9.4-24.6 9.4-33.9 0l-72-72c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l31 31V232c0-13.3 10.7-24 24-24s24 10.7 24 24z" fill="currentColor"/></svg>`,
|
||||||
};
|
};
|
||||||
|
|
||||||
function ChromeCastButton() {
|
function ChromeCastButton() {
|
||||||
|
|
|
||||||
65
src/pages/migration/Migration.tsx
Normal file
65
src/pages/migration/Migration.tsx
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { Icons } from "@/components/Icon";
|
||||||
|
import { Stepper } from "@/components/layout/Stepper";
|
||||||
|
import { CenterContainer } from "@/components/layout/ThinContainer";
|
||||||
|
import { VerticalLine } from "@/components/layout/VerticalLine";
|
||||||
|
import { Heading2, Paragraph } from "@/components/utils/Text";
|
||||||
|
import { MinimalPageLayout } from "@/pages/layouts/MinimalPageLayout";
|
||||||
|
import { Card, CardContent, Link } from "@/pages/migration/utils";
|
||||||
|
import { PageTitle } from "@/pages/parts/util/PageTitle";
|
||||||
|
|
||||||
|
export function MigrationPage() {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MinimalPageLayout>
|
||||||
|
<PageTitle subpage k="global.pages.migration" />
|
||||||
|
<CenterContainer>
|
||||||
|
<Stepper steps={2} current={1} className="mb-12" />
|
||||||
|
<Heading2 className="!mt-0 !text-3xl max-w-[435px]">
|
||||||
|
{t("migration.start.title")}
|
||||||
|
</Heading2>
|
||||||
|
<Paragraph className="max-w-[320px]">
|
||||||
|
{t("migration.start.explainer")}
|
||||||
|
</Paragraph>
|
||||||
|
|
||||||
|
<div className="w-full flex flex-col md:flex-row gap-3">
|
||||||
|
<Card onClick={() => navigate("/migration/direct")}>
|
||||||
|
<CardContent
|
||||||
|
colorClass="!text-onboarding-best"
|
||||||
|
title={t("migration.start.options.direct.title")}
|
||||||
|
subtitle={t("migration.start.options.direct.quality")}
|
||||||
|
description={
|
||||||
|
<Trans i18nKey="migration.start.options.direct.description" />
|
||||||
|
}
|
||||||
|
icon={Icons.CLOUD_ARROW_UP}
|
||||||
|
>
|
||||||
|
<Link>{t("migration.start.options.direct.action")}</Link>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
<div className="hidden md:grid grid-rows-[1fr,auto,1fr] justify-center gap-4">
|
||||||
|
<VerticalLine className="items-end" />
|
||||||
|
<span className="text-xs uppercase font-bold">
|
||||||
|
{t("migration.start.options.or")}
|
||||||
|
</span>
|
||||||
|
<VerticalLine />
|
||||||
|
</div>
|
||||||
|
<Card onClick={() => navigate("/migration/download")}>
|
||||||
|
<CardContent
|
||||||
|
colorClass="!text-migration-good"
|
||||||
|
title={t("migration.start.options.download.title")}
|
||||||
|
subtitle={t("migration.start.options.download.quality")}
|
||||||
|
description={t("migration.start.options.download.description")}
|
||||||
|
icon={Icons.FILE_ARROW_DOWN}
|
||||||
|
>
|
||||||
|
<Link>{t("migration.start.options.download.action")}</Link>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</CenterContainer>
|
||||||
|
</MinimalPageLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
12
src/pages/migration/MigrationDirect.tsx
Normal file
12
src/pages/migration/MigrationDirect.tsx
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { CenterContainer } from "@/components/layout/ThinContainer";
|
||||||
|
import { MinimalPageLayout } from "@/pages/layouts/MinimalPageLayout";
|
||||||
|
import { PageTitle } from "@/pages/parts/util/PageTitle";
|
||||||
|
|
||||||
|
export function MigrationDirectPage() {
|
||||||
|
return (
|
||||||
|
<MinimalPageLayout>
|
||||||
|
<PageTitle subpage k="global.pages.migration" />
|
||||||
|
<CenterContainer>Hi</CenterContainer>
|
||||||
|
</MinimalPageLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
92
src/pages/migration/utils.tsx
Normal file
92
src/pages/migration/utils.tsx
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { Icon, Icons } from "@/components/Icon";
|
||||||
|
import { Heading2, Heading3, Paragraph } from "@/components/utils/Text";
|
||||||
|
|
||||||
|
export function Card(props: {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
className?: string;
|
||||||
|
onClick?: () => void;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
{
|
||||||
|
"bg-onboarding-card duration-300 border border-onboarding-border rounded-lg p-7":
|
||||||
|
true,
|
||||||
|
"hover:bg-onboarding-cardHover transition-colors cursor-pointer":
|
||||||
|
!!props.onClick,
|
||||||
|
},
|
||||||
|
props.className,
|
||||||
|
)}
|
||||||
|
onClick={props.onClick}
|
||||||
|
>
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CardContent(props: {
|
||||||
|
title: ReactNode;
|
||||||
|
description: ReactNode;
|
||||||
|
subtitle: ReactNode;
|
||||||
|
colorClass: string;
|
||||||
|
children?: React.ReactNode;
|
||||||
|
icon: Icons;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="grid grid-rows-[1fr,auto] h-full">
|
||||||
|
<div>
|
||||||
|
<Icon
|
||||||
|
icon={props.icon}
|
||||||
|
className={classNames("text-4xl mb-8 block", props.colorClass)}
|
||||||
|
/>
|
||||||
|
<Heading3
|
||||||
|
className={classNames(
|
||||||
|
"!mt-0 !mb-0 !text-xs uppercase",
|
||||||
|
props.colorClass,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{props.subtitle}
|
||||||
|
</Heading3>
|
||||||
|
<Heading2 className="!mb-0 !mt-1 !text-base">{props.title}</Heading2>
|
||||||
|
<Paragraph className="max-w-[320px] !my-4">
|
||||||
|
{props.description}
|
||||||
|
</Paragraph>
|
||||||
|
</div>
|
||||||
|
<div>{props.children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Link(props: {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
to?: string;
|
||||||
|
href?: string;
|
||||||
|
className?: string;
|
||||||
|
target?: "_blank";
|
||||||
|
}) {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
if (props.to) navigate(props.to);
|
||||||
|
}}
|
||||||
|
href={props.href}
|
||||||
|
target={props.target}
|
||||||
|
className={classNames(
|
||||||
|
"text-onboarding-link cursor-pointer inline-flex gap-2 items-center group hover:opacity-75 transition-opacity",
|
||||||
|
props.className,
|
||||||
|
)}
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
{props.children}
|
||||||
|
<Icon
|
||||||
|
icon={Icons.ARROW_RIGHT}
|
||||||
|
className="group-hover:translate-x-0.5 transition-transform text-xl group-active:translate-x-0"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -22,6 +22,8 @@ import { NotFoundPage } from "@/pages/errors/NotFoundPage";
|
||||||
import { HomePage } from "@/pages/HomePage";
|
import { HomePage } from "@/pages/HomePage";
|
||||||
import { JipPage } from "@/pages/Jip";
|
import { JipPage } from "@/pages/Jip";
|
||||||
import { LoginPage } from "@/pages/Login";
|
import { LoginPage } from "@/pages/Login";
|
||||||
|
import { MigrationPage } from "@/pages/migration/Migration";
|
||||||
|
import { MigrationDirectPage } from "@/pages/migration/MigrationDirect";
|
||||||
import { OnboardingPage } from "@/pages/onboarding/Onboarding";
|
import { OnboardingPage } from "@/pages/onboarding/Onboarding";
|
||||||
import { OnboardingExtensionPage } from "@/pages/onboarding/OnboardingExtension";
|
import { OnboardingExtensionPage } from "@/pages/onboarding/OnboardingExtension";
|
||||||
import { OnboardingProxyPage } from "@/pages/onboarding/OnboardingProxy";
|
import { OnboardingProxyPage } from "@/pages/onboarding/OnboardingProxy";
|
||||||
|
|
@ -178,6 +180,74 @@ function App() {
|
||||||
{showDowntime && (
|
{showDowntime && (
|
||||||
<MaintenancePage onHomeButtonClick={handleButtonClick} />
|
<MaintenancePage onHomeButtonClick={handleButtonClick} />
|
||||||
)}
|
)}
|
||||||
|
<Routes>
|
||||||
|
{/* functional routes */}
|
||||||
|
<Route path="/s/:query" element={<QuickSearch />} />
|
||||||
|
<Route path="/search/:type" element={<Navigate to="/browse" />} />
|
||||||
|
<Route path="/search/:type/:query?" element={<QueryView />} />
|
||||||
|
|
||||||
|
{/* pages */}
|
||||||
|
<Route
|
||||||
|
path="/media/:media"
|
||||||
|
element={
|
||||||
|
<LegacyUrlView>
|
||||||
|
<Suspense fallback={null}>
|
||||||
|
<PlayerView />
|
||||||
|
</Suspense>
|
||||||
|
</LegacyUrlView>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/media/:media/:season/:episode"
|
||||||
|
element={
|
||||||
|
<LegacyUrlView>
|
||||||
|
<Suspense fallback={null}>
|
||||||
|
<PlayerView />
|
||||||
|
</Suspense>
|
||||||
|
</LegacyUrlView>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Route path="/browse/:query?" element={<HomePage />} />
|
||||||
|
<Route path="/" element={<HomePage />} />
|
||||||
|
<Route path="/register" element={<RegisterPage />} />
|
||||||
|
<Route path="/login" element={<LoginPage />} />
|
||||||
|
<Route path="/about" element={<AboutPage />} />
|
||||||
|
<Route path="/onboarding" element={<OnboardingPage />} />
|
||||||
|
<Route
|
||||||
|
path="/onboarding/extension"
|
||||||
|
element={<OnboardingExtensionPage />}
|
||||||
|
/>
|
||||||
|
<Route path="/onboarding/proxy" element={<OnboardingProxyPage />} />
|
||||||
|
|
||||||
|
<Route path="/migration" element={<MigrationPage />} />
|
||||||
|
<Route path="/migration/direct" element={<MigrationDirectPage />} />
|
||||||
|
|
||||||
|
{shouldHaveDmcaPage() ? (
|
||||||
|
<Route path="/dmca" element={<DmcaPage />} />
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{/* Settings page */}
|
||||||
|
<Route
|
||||||
|
path="/settings"
|
||||||
|
element={
|
||||||
|
<Suspense fallback={null}>
|
||||||
|
<SettingsPage />
|
||||||
|
</Suspense>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* admin routes */}
|
||||||
|
<Route path="/admin" element={<AdminPage />} />
|
||||||
|
|
||||||
|
{/* other */}
|
||||||
|
<Route path="/dev" element={<DeveloperPage />} />
|
||||||
|
<Route path="/dev/video" element={<VideoTesterView />} />
|
||||||
|
{/* developer routes that can abuse workers are disabled in production */}
|
||||||
|
{process.env.NODE_ENV === "development" ? (
|
||||||
|
<Route path="/dev/test" element={<TestView />} />
|
||||||
|
) : null}
|
||||||
|
<Route path="*" element={<NotFoundPage />} />
|
||||||
|
</Routes>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue