mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-29 16:07:40 +01:00
Localize all onboarding screens
This commit is contained in:
parent
9ec273e78c
commit
6a81b30585
4 changed files with 128 additions and 50 deletions
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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'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'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>
|
||||
|
|
|
@ -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'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>
|
||||
|
|
|
@ -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'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>
|
||||
|
|
Loading…
Reference in a new issue