From e1c09225ee67fd96b56a55673ed9928076c961d7 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Wed, 24 Jan 2024 14:51:00 +0100 Subject: [PATCH] Detect browser for extension --- package.json | 1 + pnpm-lock.yaml | 7 + src/assets/locales/en.json | 6 +- src/pages/onboarding/OnboardingExtension.tsx | 160 +++++++++++++++---- src/utils/detectFeatures.ts | 24 +++ 5 files changed, 168 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index f58b8eab..b8396c0f 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@types/node-forge": "^1.3.10", "classnames": "^2.3.2", "core-js": "^3.34.0", + "detect-browser": "^5.3.0", "dompurify": "^3.0.6", "flag-icons": "^7.1.0", "focus-trap-react": "^10.2.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a0e60397..329390b5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -48,6 +48,9 @@ dependencies: core-js: specifier: ^3.34.0 version: 3.34.0 + detect-browser: + specifier: ^5.3.0 + version: 5.3.0 dompurify: specifier: ^3.0.6 version: 3.0.6 @@ -3338,6 +3341,10 @@ packages: resolution: {integrity: sha512-M1Ob1zPSIvlARiJUkKqvAZ3VAqQY6Jcuth/pBKQ2b1dX/Qx0OnJ8Vux6J2H5PTMQeRzWrrbTu70VxBfv/OPDJA==} dev: false + /detect-browser@5.3.0: + resolution: {integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==} + dev: false + /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} dev: true diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index 15038d6f..84d4e08c 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -232,7 +232,7 @@ "downloadSubtitle": "Download current subtitle", "downloadPlaylist": "Download playlist", "downloadVideo": "Download video", - "hlsDisclaimer": "Downloads are taken directly from the provider. movie-web does not have control over how the downloads are provided.

Please note that you are downloading an HLS playlist, it is not recommended to download if you are not familiar with advanced streaming formats. Try different sources for different formats.", + "hlsDisclaimer": "Downloads are taken directly from the provider. movie-web does not have control over how the downloads are provided.

Please note that you are downloading an HLS playlist, it is not recommended to download if you are not familiar with advanced streaming formats. Try different sources for different formats.", "onAndroid": { "1": "To download on Android, click the download button then, on the new page, tap and hold on the video, then select save.", "shortTitle": "Download / Android", @@ -506,8 +506,10 @@ "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.", + "explainerIos": "Unfortunately, the browser extension is not supported on IOS, Press Go back to choose another option.", "extensionHelp": "If you've installed the extension but it's not detected. Open the extension through your browsers extension menu and follow the steps on screen.", - "link": "Install extension", + "linkChrome": "Install Chrome extension", + "linkFirefox": "Install Firefox extension", "back": "Go back", "status": { "loading": "Waiting for you to install the extension", diff --git a/src/pages/onboarding/OnboardingExtension.tsx b/src/pages/onboarding/OnboardingExtension.tsx index 3c17e3b8..5dbbecad 100644 --- a/src/pages/onboarding/OnboardingExtension.tsx +++ b/src/pages/onboarding/OnboardingExtension.tsx @@ -1,4 +1,4 @@ -import { ReactNode } from "react"; +import { ReactNode, useMemo } from "react"; import { Trans, useTranslation } from "react-i18next"; import { useAsyncFn, useInterval } from "react-use"; @@ -18,6 +18,10 @@ import { import { Card, Link } from "@/pages/onboarding/utils"; import { PageTitle } from "@/pages/parts/util/PageTitle"; import { conf } from "@/setup/config"; +import { + ExtensionDetectionResult, + detectExtensionInstall, +} from "@/utils/detectFeatures"; type ExtensionStatus = | "unknown" @@ -40,6 +44,7 @@ async function getExtensionState(): Promise { export function ExtensionStatus(props: { status: ExtensionStatus; loading: boolean; + showHelp?: boolean; }) { const { t } = useTranslation(); @@ -88,19 +93,119 @@ export function ExtensionStatus(props: { {content} - -
- -

- , - }} - /> -

-
-
+ {props.showHelp ? ( + +
+ +

+ , + }} + /> +

+
+
+ ) : null} + + ); +} + +interface ExtensionPageProps { + status: ExtensionStatus; + loading: boolean; +} + +function ChromeExtensionPage(props: ExtensionPageProps) { + const { t } = useTranslation(); + const installLink = conf().ONBOARDING_EXTENSION_INSTALL_LINK; + return ( + <> + + {t("onboarding.extension.title")} + + + {t("onboarding.extension.explainer")} + + {installLink ? ( + + {t("onboarding.extension.linkChrome")} + + ) : null} + + + + ); +} + +function FirefoxExtensionPage(props: ExtensionPageProps) { + const { t } = useTranslation(); + const installLink = conf().ONBOARDING_EXTENSION_INSTALL_LINK; + return ( + <> + + {t("onboarding.extension.title")} + + + {t("onboarding.extension.explainer")} + + {installLink ? ( + + {t("onboarding.extension.linkFirefox")} + + ) : null} + + + + ); +} + +function IosExtensionPage(_props: ExtensionPageProps) { + const { t } = useTranslation(); + return ( + <> + + {t("onboarding.extension.title")} + + + }} + /> + + + ); +} + +function UnknownExtensionPage(props: ExtensionPageProps) { + const { t } = useTranslation(); + const installChromeLink = conf().ONBOARDING_EXTENSION_INSTALL_LINK; + const installFirefoxLink = conf().ONBOARDING_EXTENSION_INSTALL_LINK; + return ( + <> + + {t("onboarding.extension.title")} + + + {t("onboarding.extension.explainer")} + +
+ {installChromeLink ? ( + + {t("onboarding.extension.linkChrome")} + + ) : null} +
+
+ {installFirefoxLink ? ( + + {t("onboarding.extension.linkFirefox")} + + ) : null} +
+ + ); } @@ -109,7 +214,7 @@ export function OnboardingExtensionPage() { const { t } = useTranslation(); const navigate = useNavigateOnboarding(); const { completeAndRedirect } = useRedirectBack(); - const installLink = conf().ONBOARDING_EXTENSION_INSTALL_LINK; + const extensionSupport = useMemo(() => detectExtensionInstall(), []); const [{ loading, value }, exec] = useAsyncFn( async (triggeredManually: boolean = false) => { @@ -121,24 +226,23 @@ export function OnboardingExtensionPage() { ); useInterval(exec, 1000); + const componentMap: Record< + ExtensionDetectionResult, + typeof UnknownExtensionPage + > = { + chrome: ChromeExtensionPage, + firefox: FirefoxExtensionPage, + ios: IosExtensionPage, + unknown: UnknownExtensionPage, + }; + const PageContent = componentMap[extensionSupport]; + return ( - - {t("onboarding.extension.title")} - - - {t("onboarding.extension.explainer")} - - {installLink ? ( - - {t("onboarding.extension.link")} - - ) : null} - - +