Start adding migration pages

This commit is contained in:
William Oldham 2024-03-11 20:35:09 +00:00
parent 8e73751f48
commit ee047327a1
6 changed files with 201 additions and 1 deletions

View file

@ -100,7 +100,8 @@
"onboarding": "Setup",
"pagetitle": "{{title}} - movie-web",
"register": "Register",
"settings": "Settings"
"settings": "Settings",
"migration": "Migration"
}
},
"home": {
@ -153,6 +154,27 @@
"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": {
"banner": {
"offline": "Check your internet connection"

View file

@ -64,6 +64,8 @@ export enum Icons {
DONATION = "donation",
CIRCLE_QUESTION = "circle_question",
BRUSH = "brush",
CLOUD_ARROW_UP = "cloud_arrow_up",
FILE_ARROW_DOWN = "file_arrow_down",
}
export interface IconProps {
@ -134,6 +136,8 @@ const iconList: Record<Icons, string> = {
donation: `<svg xmlns="http://www.w3.org/2000/svg" height="1em" width="1em" viewBox="0 0 576 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path opacity="1" fill="currentColor" d="M163.9 136.9c-29.4-29.8-29.4-78.2 0-108s77-29.8 106.4 0l17.7 18 17.7-18c29.4-29.8 77-29.8 106.4 0s29.4 78.2 0 108L310.5 240.1c-6.2 6.3-14.3 9.4-22.5 9.4s-16.3-3.1-22.5-9.4L163.9 136.9zM568.2 336.3c13.1 17.8 9.3 42.8-8.5 55.9L433.1 485.5c-23.4 17.2-51.6 26.5-80.7 26.5H192 32c-17.7 0-32-14.3-32-32V416c0-17.7 14.3-32 32-32H68.8l44.9-36c22.7-18.2 50.9-28 80-28H272h16 64c17.7 0 32 14.3 32 32s-14.3 32-32 32H288 272c-8.8 0-16 7.2-16 16s7.2 16 16 16H392.6l119.7-88.2c17.8-13.1 42.8-9.3 55.9 8.5zM193.6 384l0 0-.9 0c.3 0 .6 0 .9 0z"/></svg>`,
circle_question: `<svg xmlns="http://www.w3.org/2000/svg" height="1em" width="1em" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--><path opacity="1" fill="currentColor" d="M464 256A208 208 0 1 0 48 256a208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zm169.8-90.7c7.9-22.3 29.1-37.3 52.8-37.3h58.3c34.9 0 63.1 28.3 63.1 63.1c0 22.6-12.1 43.5-31.7 54.8L280 264.4c-.2 13-10.9 23.6-24 23.6c-13.3 0-24-10.7-24-24V250.5c0-8.6 4.6-16.5 12.1-20.8l44.3-25.4c4.7-2.7 7.6-7.7 7.6-13.1c0-8.4-6.8-15.1-15.1-15.1H222.6c-3.4 0-6.4 2.1-7.5 5.3l-.4 1.2c-4.4 12.5-18.2 19-30.6 14.6s-19-18.2-14.6-30.6l.4-1.2zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"/></svg>`,
brush: `<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 2023 Fonticons, Inc.--><path d="M162.4 6c-1.5-3.6-5-6-8.9-6h-19c-3.9 0-7.5 2.4-8.9 6L104.9 57.7c-3.2 8-14.6 8-17.8 0L66.4 6c-1.5-3.6-5-6-8.9-6H48C21.5 0 0 21.5 0 48V224v22.4V256H9.6 374.4 384v-9.6V224 48c0-26.5-21.5-48-48-48H230.5c-3.9 0-7.5 2.4-8.9 6L200.9 57.7c-3.2 8-14.6 8-17.8 0L162.4 6zM0 288v32c0 35.3 28.7 64 64 64h64v64c0 35.3 28.7 64 64 64s64-28.7 64-64V384h64c35.3 0 64-28.7 64-64V288H0zM192 432a16 16 0 1 1 0 32 16 16 0 1 1 0-32z" fill="currentColor"/></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() {

View 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>
);
}

View 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>
);
}

View 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>
);
}

View file

@ -19,6 +19,8 @@ import { DmcaPage, shouldHaveDmcaPage } from "@/pages/Dmca";
import { NotFoundPage } from "@/pages/errors/NotFoundPage";
import { HomePage } from "@/pages/HomePage";
import { LoginPage } from "@/pages/Login";
import { MigrationPage } from "@/pages/migration/Migration";
import { MigrationDirectPage } from "@/pages/migration/MigrationDirect";
import { OnboardingPage } from "@/pages/onboarding/Onboarding";
import { OnboardingExtensionPage } from "@/pages/onboarding/OnboardingExtension";
import { OnboardingProxyPage } from "@/pages/onboarding/OnboardingProxy";
@ -129,6 +131,9 @@ function App() {
/>
<Route path="/onboarding/proxy" element={<OnboardingProxyPage />} />
<Route path="/migration" element={<MigrationPage />} />
<Route path="/migration/direct" element={<MigrationDirectPage />} />
{shouldHaveDmcaPage() ? (
<Route path="/dmca" element={<DmcaPage />} />
) : null}