Localize all onboarding screens

This commit is contained in:
mrjvs 2024-01-20 11:53:24 +01:00
parent 9ec273e78c
commit 6a81b30585
4 changed files with 128 additions and 50 deletions

View file

@ -97,7 +97,8 @@
"login": "Login",
"pagetitle": "{{title}} - movie-web",
"register": "Register",
"settings": "Settings"
"settings": "Settings",
"onboarding": "Setup"
}
},
"home": {
@ -429,5 +430,64 @@
}
},
"unsaved": "You have unsaved changes"
},
"onboarding": {
"start": {
"title": "Let's get you setup with movie-web",
"explainer": "To get the best streams possible. You will need to choose which streaming method you want to use.",
"options": {
"proxy": {
"quality": "Good quality",
"title": "Custom proxy",
"description": "Setup a proxy in just 5 minutes and gain access to great sources.",
"action": "Setup proxy"
},
"extension": {
"quality": "Best quality",
"title": "Browser extension",
"description": "Install browser extension and gain access to the best sources.",
"action": "Install extension"
},
"default": {
"text": "I don't want good quality streams,<0 /> <1>use the default setup</1>"
}
}
},
"proxy": {
"title": "Let's make a new proxy",
"explainer": "With the proxy method, you can get great quality streams by making a self-service proxy.",
"link": "Learn how to make a proxy",
"input": {
"label": "Proxy URL",
"placeholder": "https://",
"errorInvalidUrl": "Not a valid URL",
"errorConnection": "Could not connect to proxy",
"errorNotProxy": "Expected a proxy but got a website"
},
"back": "Go back",
"submit": "Submit proxy"
},
"extension": {
"title": "Let's start with an extension",
"explainer": "Using the browser extension, you can get the best streams we have to offer. With just a simple install.",
"link": "Install extension",
"back": "Go back",
"status": {
"loading": "Waiting on extension",
"disallowed": "Extension disabled for this page",
"failed": "Failed to request status",
"outdated": "Extension version too old",
"noperms": "Extension does not have sufficient permissions",
"success": "Extension is working as expected!"
},
"submitCheck": "Check for extension",
"submitFinal": "Continue"
},
"defaultConfirm": {
"title": "Are you sure?",
"description": "The default setup does not have the best streams and can be unbearably slow.",
"cancel": "Cancel",
"confirm": "Use default setup"
}
}
}

View file

@ -1,4 +1,5 @@
import classNames from "classnames";
import { Trans, useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { Button } from "@/components/buttons/Button";
@ -23,20 +24,23 @@ export function OnboardingPage() {
const navigate = useNavigate();
const skipModal = useModal("skip");
const { completeAndRedirect } = useRedirectBack();
const { t } = useTranslation();
return (
<MinimalPageLayout>
<PageTitle subpage k="global.pages.about" />
<PageTitle subpage k="global.pages.onboarding" />
<Modal id={skipModal.id}>
<ModalCard>
<ModalCard>
<Heading1 className="!mt-0">Lorem ipsum</Heading1>
<Paragraph>Lorem ipsum Lorem ipsum Lorem ipsum</Paragraph>
<Heading1 className="!mt-0">
{t("onboarding.defaultConfirm.title")}
</Heading1>
<Paragraph>{t("onboarding.defaultConfirm.description")}</Paragraph>
<Button theme="secondary" onClick={skipModal.hide}>
Lorem ipsum
{t("onboarding.defaultConfirm.cancel")}
</Button>
<Button theme="danger" onClick={() => completeAndRedirect()}>
Lorem ipsum
{t("onboarding.defaultConfirm.confirm")}
</Button>
</ModalCard>
</ModalCard>
@ -44,22 +48,21 @@ export function OnboardingPage() {
<CenterContainer>
<Stepper steps={2} current={1} className="mb-12" />
<Heading2 className="!mt-0 !text-3xl max-w-[435px]">
Let&apos;s get you set up with movie-web
{t("onboarding.start.title")}
</Heading2>
<Paragraph className="max-w-[320px]">
To get the best streams possible, you will need to choose which
streaming method you want to use.
{t("onboarding.start.explainer")}
</Paragraph>
<div className="w-full grid grid-cols-[1fr,auto,1fr] gap-3">
<Card onClick={() => navigate("/onboarding/proxy")}>
<CardContent
colorClass="!text-onboarding-good"
title="Custom proxy"
subtitle="Good quality"
description="Set up a proxy in only 5 minutes and gain access to great sources."
title={t("onboarding.start.options.proxy.title")}
subtitle={t("onboarding.start.options.proxy.quality")}
description={t("onboarding.start.options.proxy.description")}
>
<Link>Set up proxy</Link>
<Link>{t("onboarding.start.options.proxy.action")}</Link>
</CardContent>
</Card>
<div className="grid grid-rows-[1fr,auto,1fr] justify-center gap-4">
@ -70,24 +73,24 @@ export function OnboardingPage() {
<Card onClick={() => navigate("/onboarding/extension")}>
<CardContent
colorClass="!text-onboarding-best"
title="Browser extension"
subtitle="Best quality"
description="Install browser extension and gain access to the best sources."
title={t("onboarding.start.options.extension.title")}
subtitle={t("onboarding.start.options.extension.quality")}
description={t("onboarding.start.options.extension.description")}
>
<Link>Install extension</Link>
<Link>{t("onboarding.start.options.extension.action")}</Link>
</CardContent>
</Card>
</div>
<p className="text-center mt-12">
I don&apos;t want good quality, <br />
<a
onClick={skipModal.show}
type="button"
className="text-onboarding-link hover:opacity-75 cursor-pointer"
>
use the default setup
</a>
<Trans i18nKey="onboarding.start.options.default.text">
<br />
<a
onClick={skipModal.show}
type="button"
className="text-onboarding-link hover:opacity-75 cursor-pointer"
/>
</Trans>
</p>
</CenterContainer>
</MinimalPageLayout>

View file

@ -1,4 +1,5 @@
import { ReactNode } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { useAsyncFn, useInterval } from "react-use";
@ -36,20 +37,26 @@ export function ExtensionStatus(props: {
status: ExtensionStatus;
loading: boolean;
}) {
const { t } = useTranslation();
let content: ReactNode = null;
if (props.loading || props.status === "unknown")
content = (
<>
<Loading />
<p>waiting on extension</p>
<p>{t("onboarding.extension.status.loading")}</p>
</>
);
if (props.status === "disallowed")
content = <p>Extension disabled for this page</p>;
else if (props.status === "failed") content = <p>Failed to request status</p>;
else if (props.status === "outdated") content = <p>Extension too old</p>;
else if (props.status === "noperms") content = <p>No permissions to act</p>;
else if (props.status === "success") content = <p>Extension is working!</p>;
content = <p>{t("onboarding.extension.status.disallowed")}</p>;
else if (props.status === "failed")
content = <p>{t("onboarding.extension.status.failed")}</p>;
else if (props.status === "outdated")
content = <p>{t("onboarding.extension.status.outdated")}</p>;
else if (props.status === "noperms")
content = <p>{t("onboarding.extension.status.noperms")}</p>;
else if (props.status === "success")
content = <p>{t("onboarding.extension.status.success")}</p>;
return (
<Card>
<div className="flex py-6 flex-col space-y-2 items-center justify-center">
@ -60,6 +67,7 @@ export function ExtensionStatus(props: {
}
export function OnboardingExtensionPage() {
const { t } = useTranslation();
const navigate = useNavigate();
const { completeAndRedirect } = useRedirectBack();
@ -75,27 +83,30 @@ export function OnboardingExtensionPage() {
return (
<MinimalPageLayout>
<PageTitle subpage k="global.pages.about" />
<PageTitle subpage k="global.pages.onboarding" />
<CenterContainer>
<Stepper steps={2} current={2} className="mb-12" />
<Heading2 className="!mt-0 !text-3xl max-w-[435px]">
Let&apos;s start with an extension
{t("onboarding.extension.title")}
</Heading2>
<Paragraph className="max-w-[320px] mb-4">
Using the browser extension, you can get the best streams we have to
offer. With just a simple install.
{t("onboarding.extension.explainer")}
</Paragraph>
<Link href="https://google.com" target="_blank" className="mb-12">
Install extension
{t("onboarding.extension.link")}
</Link>
<ExtensionStatus status={value ?? "unknown"} loading={loading} />
<div className="flex justify-between items-center mt-8">
<Button onClick={() => navigate("/onboarding")} theme="secondary">
Back
{t("onboarding.extension.back")}
</Button>
<Button onClick={() => exec(true)} theme="purple">
{value === "success" ? "Continue" : "Check extension"}{" "}
{t(
value === "success"
? "onboarding.extension.submitFinal"
: "onboarding.extension.submitCheck",
)}
</Button>
</div>
</CenterContainer>

View file

@ -1,4 +1,5 @@
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { useAsyncFn } from "react-use";
@ -19,52 +20,55 @@ import { useAuthStore } from "@/stores/auth";
const testUrl = "https://postman-echo.com/get";
export function OnboardingProxyPage() {
const { t } = useTranslation();
const navigate = useNavigate();
const { completeAndRedirect } = useRedirectBack();
const [url, setUrl] = useState("");
const setProxySet = useAuthStore((s) => s.setProxySet);
const [{ loading, error }, test] = useAsyncFn(async () => {
if (!url.startsWith("http")) throw new Error("Not a valid URL");
if (!url.startsWith("http"))
throw new Error("onboarding.proxy.input.errorInvalidUrl");
try {
const res = await singularProxiedFetch(url, testUrl, {});
if (res.url !== testUrl) throw new Error("Not a proxy");
if (res.url !== testUrl)
throw new Error("onboarding.proxy.input.errorNotProxy");
setProxySet([url]);
completeAndRedirect();
} catch (e) {
throw new Error("Could not connect to proxy");
throw new Error("onboarding.proxy.input.errorConnection");
}
}, [url, completeAndRedirect, setProxySet]);
return (
<MinimalPageLayout>
<PageTitle subpage k="global.pages.about" />
<PageTitle subpage k="global.pages.onboarding" />
<CenterContainer>
<Stepper steps={2} current={2} className="mb-12" />
<Heading2 className="!mt-0 !text-3xl max-w-[435px]">
Let&apos;s setup a custom proxy
{t("onboarding.proxy.title")}
</Heading2>
<Paragraph className="max-w-[320px] !mb-5">
Using a custom proxy, you can get great quality streams!
{t("onboarding.proxy.explainer")}
</Paragraph>
<Link>Learn how to make a custom proxy</Link>
<Link>{t("onboarding.proxy.link")}</Link>
<div className="w-[400px] max-w-full mt-14 mb-28">
<AuthInputBox
label="Proxy URL"
label={t("onboarding.proxy.input.label")}
value={url}
onChange={setUrl}
placeholder="lorem ipsum"
placeholder={t("onboarding.proxy.input.placeholder")}
className="mb-4"
/>
{error ? <ErrorLine>{error.message}</ErrorLine> : null}
{error ? <ErrorLine>{t(error.message)}</ErrorLine> : null}
</div>
<Divider />
<div className="flex justify-between">
<Button theme="secondary" onClick={() => navigate("/onboarding")}>
Back
{t("onboarding.proxy.back")}
</Button>
<Button theme="purple" loading={loading} onClick={test}>
Submit proxy
{t("onboarding.proxy.submit")}
</Button>
</div>
</CenterContainer>