Add better scrape error messages for the extension

This commit is contained in:
Cooper Ransom 2024-03-26 19:37:35 -04:00
parent 27e73a8ad4
commit 5ea284ae87
3 changed files with 81 additions and 14 deletions

View File

@ -1,19 +1,19 @@
window.__CONFIG__ = {
// The URL for the CORS proxy, the URL must NOT end with a slash!
// If not specified, the onboarding will not allow a "default setup". The user will have to use the extension or set up a proxy themselves
VITE_CORS_PROXY_URL: "",
VITE_CORS_PROXY_URL: "https://sudo-proxy.up.railway.app",
// The READ API key to access TMDB
VITE_TMDB_READ_API_KEY: "",
VITE_TMDB_READ_API_KEY: "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJhZTljNGE2ZDE1ZDFiODZiNzdlMWQyYmI5ZGY0MzdmYyIsInN1YiI6IjY1YjNmMWI0NTk0Yzk0MDE2MzNkZDBjNSIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.kAX7TkbKuJkNty6IsjcCLnoENFicVZn6d6DkLQsy3p8",
// The DMCA email displayed in the footer, null to hide the DMCA link
VITE_DMCA_EMAIL: null,
VITE_DMCA_EMAIL: "dev@sudo-flix.lol",
// Whether to disable hash-based routing, leave this as false if you don't know what this is
VITE_NORMAL_ROUTER: false,
VITE_NORMAL_ROUTER: true,
// The backend URL to communicate with
VITE_BACKEND_URL: null,
VITE_BACKEND_URL: "backend.sudo-flix.lol",
// A comma separated list of disallowed IDs in the case of a DMCA claim - in the format "series-<id>" and "movie-<id>"
VITE_DISALLOWED_IDS: "",

View File

@ -388,6 +388,14 @@
"homeButton": "Go home",
"text": "We have searched through our providers and cannot find the media you are looking for! We do not host the media and have no control over what is available. Please click 'Show details' below for more details.",
"title": "We couldn't find that"
},
"extensionFailure": {
"badge": "Not found",
"homeButton": "Go home",
"enableExtension": "Enable extension",
"disabledTitle": "Extension disabled",
"text": "You've installed the movie-web extension. To start using it, complete a few preliminary steps. Have you enabled the extension for this site?",
"title": "Extension Disabled"
}
},
"time": {

View File

@ -1,7 +1,9 @@
import { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { useEffect, useMemo, useState } from "react";
import { Trans, useTranslation } from "react-i18next";
import { useLocation } from "react-router-dom";
import { isAllowedExtensionVersion } from "@/backend/extension/compatibility";
import { extensionInfo, sendPage } from "@/backend/extension/messaging";
import { Button } from "@/components/buttons/Button";
import { Icons } from "@/components/Icon";
import { IconPill } from "@/components/layout/IconPill";
@ -14,6 +16,14 @@ import { getProviderApiUrls } from "@/utils/proxyUrls";
import { ErrorCardInModal } from "../errors/ErrorCard";
type ExtensionStatus =
| "unknown"
| "failed"
| "disallowed"
| "noperms"
| "outdated"
| "success";
export interface ScrapeErrorPartProps {
data: {
sources: Record<string, ScrapingSegment>;
@ -21,10 +31,24 @@ export interface ScrapeErrorPartProps {
};
}
async function getExtensionState(): Promise<ExtensionStatus> {
const info = await extensionInfo();
if (!info) return "unknown"; // cant talk to extension
if (!info.success) return "failed"; // extension failed to respond
if (!info.allowed) return "disallowed"; // extension is not enabled on this page
if (!info.hasPermission) return "noperms"; // extension has no perms to do it's tasks
if (!isAllowedExtensionVersion(info.version)) return "outdated"; // extension is too old
return "success"; // no problems
}
export function ScrapeErrorPart(props: ScrapeErrorPartProps) {
const { t } = useTranslation();
const modal = useModal("error");
const location = useLocation();
const [extensionState, setExtensionState] =
useState<ExtensionStatus>("unknown");
const [title, setTitle] = useState(t("player.scraping.notFound.title"));
const [icon, setIcon] = useState(Icons.WAND);
const error = useMemo(() => {
const data = props.data;
@ -42,14 +66,42 @@ export function ScrapeErrorPart(props: ScrapeErrorPartProps) {
return str;
}, [props, location]);
useEffect(() => {
getExtensionState().then((state) => {
setExtensionState(state);
if (state === "disallowed") {
setTitle(t("player.scraping.extensionFailure.disabledTitle"));
setIcon(Icons.LOCK);
}
});
}, [t]);
return (
<ErrorLayout>
<ErrorContainer>
<IconPill icon={Icons.WAND}>
{t("player.scraping.notFound.badge")}
</IconPill>
<Title>{t("player.scraping.notFound.title")}</Title>
<Paragraph>{t("player.scraping.notFound.text")}</Paragraph>
<IconPill icon={icon}>{t("player.scraping.notFound.badge")}</IconPill>
<Title>{title}</Title>
<Paragraph>
{extensionState === "disallowed" ? (
<Trans
i18nKey="player.scraping.extensionFailure.text"
components={{
bold: (
<span className="font-bold" style={{ color: "#cfcfcf" }} />
),
}}
/>
) : (
<Trans
i18nKey="player.scraping.notFound.text"
components={{
bold: (
<span className="font-bold" style={{ color: "#cfcfcf" }} />
),
}}
/>
)}
</Paragraph>
<div className="flex gap-3">
<Button
href="/"
@ -60,12 +112,19 @@ export function ScrapeErrorPart(props: ScrapeErrorPartProps) {
{t("player.scraping.notFound.homeButton")}
</Button>
<Button
onClick={() => modal.show()}
onClick={() => {
sendPage({
page: "PermissionGrant",
redirectUrl: window.location.href,
});
}}
theme="purple"
padding="md:px-12 p-2.5"
className="mt-6"
>
{t("player.scraping.notFound.detailsButton")}
{extensionState === "unknown"
? t("player.scraping.notFound.detailsButton")
: t("player.scraping.extensionFailure.enableExtension")}
</Button>
</div>
</ErrorContainer>