Browse Source

Merge pull request #571 from movie-web/dev

Version v4.1.1
pull/774/head 4.1.1
William Oldham 2 years ago committed by GitHub
parent
commit
040a054b13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      package.json
  2. 8
      src/assets/locales/ar.json
  3. 1
      src/assets/locales/en.json
  4. 14
      src/assets/locales/fr.json
  5. 120
      src/assets/locales/ne.json
  6. 2
      src/assets/locales/zh.json
  7. 12
      src/backend/helpers/report.ts
  8. 4
      src/components/form/PassphraseDisplay.tsx
  9. 2
      src/components/utils/Lightbar.tsx
  10. 8
      src/hooks/auth/useAuthData.ts
  11. 2
      src/hooks/useSettingsState.ts
  12. 1
      src/index.tsx
  13. 2
      src/pages/Settings.tsx
  14. 2
      src/pages/parts/settings/SidebarPart.tsx
  15. 12
      src/stores/turnstile/index.tsx

2
package.json

@ -1,6 +1,6 @@
{ {
"name": "movie-web", "name": "movie-web",
"version": "4.1.0", "version": "4.1.1",
"private": true, "private": true,
"homepage": "https://movie-web.app", "homepage": "https://movie-web.app",
"scripts": { "scripts": {

8
src/assets/locales/ar.json

@ -86,7 +86,7 @@
"dmca": "DMCA", "dmca": "DMCA",
"github": "غيت هاب" "github": "غيت هاب"
}, },
"tagline": "شاهد عروضك وأفلامك المفضلة باستخدام البث تطبيق مفتوح المصدر هذا." "tagline": "شاهد عروضك وأفلامك المفضلة باستخدام تطبيق البث مفتوح المصدر هذا."
}, },
"global": { "global": {
"name": "movie-web", "name": "movie-web",
@ -157,7 +157,7 @@
}, },
"notFound": { "notFound": {
"badge": "صفحة غير موجودة", "badge": "صفحة غير موجودة",
"goHome": "العودة للصفحة الرئيسية", "goHome": "عودة",
"message": "بحثنا في كل مكان: في الخزانة وحتى تحت الصناديق، ومع ذلك لم نعثر عن الصفحة التي طلبتَها.", "message": "بحثنا في كل مكان: في الخزانة وحتى تحت الصناديق، ومع ذلك لم نعثر عن الصفحة التي طلبتَها.",
"title": "تعذر العثور على هته الصفحة" "title": "تعذر العثور على هته الصفحة"
}, },
@ -166,7 +166,7 @@
}, },
"player": { "player": {
"back": { "back": {
"default": ُدْ للصفحة الرئيسية", "default": ودة",
"short": ُدْ" "short": ُدْ"
}, },
"casting": { "casting": {
@ -305,7 +305,7 @@
}, },
"screens": { "screens": {
"dmca": { "dmca": {
"text": "مرحبًا بكم في صفحة اتصال بقانون الألفية للملكية الرقمية (DMCA) الخاصة بـ movie-web! نحن نحترم حقوق الملكية الفكرية ونرغب في التعامل بسرعة مع أي قلق يتعلق بحقوق الطبع والنشر. إذا كنت تعتقد أن عملك المحمي بحقوق الطبع والنشر قد تم استخدامه بشكل غير لائق على منصتنا، يرجى إرسال إشعار DMCA مفصل إلى البريد الإلكتروني أدناه. يرجى تضمين وصف للمواد المحمية بحقوق الطبع والنشر، وتفاصيل الاتصال الخاصة بك، وبيان من النية الصادقة. نحن ملتزمون بحل هذه القضايا بسرعة ونقدر تعاونكم في الحفاظ على movie-web كمكان يحترم الإبداع وحقوق الطبع والنشر.", "text": "مرحبًا بكم في صفحة movie-web الخاصة بالتواصل حول قانون الألفية للملكية الرقمية (DMCA) ! نحن نحترم حقوق الملكية الفكرية ونرغب في التعامل بسرعة مع أي مسألة تخص حقوق الطبع والنشر. إن كنت تعتقد أن أيا من أعمالك المحميو بحقوق الطبع والنشر قد تم استخدامها بشكل غير لائق على منصتنا، رجاءً أرسل إشعارا مفصلا إلى البريد الإلكتروني أدناه. يرجى تضمين وصف للمواد المحمية بحقوق الطبع والنشر، وكذا طريقةً للتواصل معك، إضافة إلى تصريح بمصداقية طلبك. نحن ملتزمون بحل هذه القضايا بسرعة ونقدر تعاونكم في الحفاظ على movie-web كمكان يحترم الإبداع وحقوق الطبع والنشر.",
"title": "DMCA" "title": "DMCA"
}, },
"loadingApp": "جار تحميل التطبيق", "loadingApp": "جار تحميل التطبيق",

1
src/assets/locales/en.json

@ -25,6 +25,7 @@
}, },
"generate": { "generate": {
"title": "Your passphrase", "title": "Your passphrase",
"passphraseFrameLabel": "Passphrase",
"next": "I have saved my passphrase", "next": "I have saved my passphrase",
"description": "Your passphrase acts as your username and password. Make sure to keep it safe as you will need to enter it to login to your account" "description": "Your passphrase acts as your username and password. Make sure to keep it safe as you will need to enter it to login to your account"
}, },

14
src/assets/locales/fr.json

@ -7,11 +7,11 @@
"title": "D'où vient le contenu ?" "title": "D'où vient le contenu ?"
}, },
"q2": { "q2": {
"body": "Il n'est pas possible de demander une émission ou un film, movie-web ne gère aucun contenu. Tous les contenus sont consultés par l'intermédiaire de sources sur Internet.", "body": "Il est impossible de solliciter une émission ou un film car movie-web ne gère aucun contenu. Les sources sur Internet sont utilisées pour consulter tous les contenus.",
"title": "Où puis-je demander un show ou un film ?" "title": "Où puis-je demander une série ou un film ?"
}, },
"q3": { "q3": {
"body": "Nos résultats de recherche sont fournis par The Movie Database (TMDB) et s'affichent indépendamment du fait que nos sources possèdent ou non le contenu.", "body": "Nos résultats de recherche sont disponibles dans The Movie Database (TMDB), indépendamment du fait que nos sources possèdent ou non le contenu.",
"title": "Les résultats de la recherche affichent l'émission ou le film, pourquoi ne puis-je pas le lire ?" "title": "Les résultats de la recherche affichent l'émission ou le film, pourquoi ne puis-je pas le lire ?"
}, },
"title": "A propos de movie-web" "title": "A propos de movie-web"
@ -21,7 +21,7 @@
"copy": "Copier" "copy": "Copier"
}, },
"auth": { "auth": {
"createAccount": "Vous n'avez pas encore de compte ? <0>Créer un compte.</0>", "createAccount": "N'avez-vous pas encore de compte? <0>Créer un compte.</0>",
"deviceNameLabel": "Nom de l'appareil", "deviceNameLabel": "Nom de l'appareil",
"deviceNamePlaceholder": "Téléphone personnel", "deviceNamePlaceholder": "Téléphone personnel",
"generate": { "generate": {
@ -29,7 +29,7 @@
"next": "J'ai sauvegardé ma passphrase", "next": "J'ai sauvegardé ma passphrase",
"title": "Votre passphrase" "title": "Votre passphrase"
}, },
"hasAccount": "Vous avez déjà un compte ? <0>Connectez-vous ici.</0>", "hasAccount": "Avez-vous déjà un compte? <0>Connectez-vous ici.</0>",
"login": { "login": {
"description": "Veuillez entrer votre passphrase pour vous connecter à votre compte", "description": "Veuillez entrer votre passphrase pour vous connecter à votre compte",
"deviceLengthError": "Veuillez saisir un nom d'appareil", "deviceLengthError": "Veuillez saisir un nom d'appareil",
@ -79,14 +79,14 @@
"footer": { "footer": {
"legal": { "legal": {
"disclaimer": "Avertissement", "disclaimer": "Avertissement",
"disclaimerText": "movie-web n'héberge aucun fichier, il se contente de proposer des liens vers des services tiers. Les questions juridiques doivent être réglées avec les hébergeurs et les fournisseurs de fichiers. movie-web n'est pas responsable des fichiers multimédias diffusés par les fournisseurs de vidéos." "disclaimerText": "Le site movie-web ne stocke pas de fichiers, mais propose des liens vers des services externes. Les problèmes juridiques doivent être traités avec les fournisseurs et les hébergeurs de fichiers. Les fichiers multimédias diffusés par les fournisseurs de vidéos ne sont pas couverts par movie-web."
}, },
"links": { "links": {
"discord": "Discord", "discord": "Discord",
"dmca": "DMCA", "dmca": "DMCA",
"github": "GitHub" "github": "GitHub"
}, },
"tagline": "Regardez vos émissions et films préférés avec cette application de streaming open source." "tagline": "Cette application de streaming open source vous permet de regarder vos émissions et films préférés."
}, },
"global": { "global": {
"name": "movie-web", "name": "movie-web",

120
src/assets/locales/ne.json

@ -1,4 +1,21 @@
{ {
"about": {
"description": "movie-web एउटब एप ह जसलिमहरि इनटरनटमछ। हमग उपभग गरनकिनतम दिणकि लकय रछ।",
"faqTitle": "सय परशनहर",
"q1": {
"body": "movie-web ल पनिमगट गरन। जब तपनकिििक गरछ, इनटरनटम चयन गरिएकििि गरिछ (लिङ सिनम र 'भिित' टबम तपन सत परयग गरिरहन भएक छ भनर दन सकछ)। मिि कहि पनि चलचिर-वब द अपलड हन, सबयनर मफत हछ।",
"title": "समग कहट आउछ?"
},
"q2": {
"body": "कयकरम व चलचिर अनध गरन समभव छन, movie-webल पनिमगयवसपन गरन। सबमग इनटरनटमतहरफत हिछ।",
"title": "म कहयकरम व चलचिर अनध गरन सक?"
},
"q3": {
"body": "हज परिमहर चलचिर डस (TMDB) दित हछन र हतहरमग छ किन भनरदरशन गरिछ।",
"title": "खज परिमहरयकरम व चलचिर परदरशन गरदछ, म यसलई किन प गरन सकिन?"
},
"title": "movie-web ब"
},
"actions": { "actions": {
"copied": "कप भय", "copied": "कप भय",
"copy": "कप" "copy": "कप"
@ -59,6 +76,18 @@
"showError": "तििवरण दउन", "showError": "तििवरण दउन",
"title": "ह एउटिमन गर!" "title": "ह एउटिमन गर!"
}, },
"footer": {
"legal": {
"disclaimer": "Disclaimer",
"disclaimerText": "movie-webल पनिइलहरट गरन, यसलवल त पकष सहरिक गरदछ। कहरइल हट र परदयकहरग लि परछ। चलचिर-वब भििरदयकहरइएक पनिििइलहरििर छन।"
},
"links": {
"discord": "Discord",
"dmca": "DMCA",
"github": "GitHub"
},
"tagline": "यत सििङ एपकथ आफ मनपर र चलचिरहर।"
},
"global": { "global": {
"name": "movie-web", "name": "movie-web",
"pages": { "pages": {
@ -293,8 +322,99 @@
} }
}, },
"settings": { "settings": {
"account": {
"accountDetails": {
"deviceNameLabel": "उपकरणकम",
"deviceNamePlaceholder": "वयकिगत फन",
"editProfile": "समदन गर",
"logoutButton": "बिर निकन"
},
"actions": {
"delete": {
"button": "खिट गर",
"confirmButton": "खिट गर",
"confirmDescription": "क तप आफिट गरन नशित हछ? तप सब हरउनछ!",
"confirmTitle": "क तपिित हछ?",
"text": "यय अपरिवरतनय छ। सबइनछ र कि पनिन: पत गरन सकिन।",
"title": "खिट गर"
},
"title": "कयहर"
},
"devices": {
"deviceNameLabel": "उपकरणकम",
"failed": "सतरहरड गरन असफल भय",
"removeDevice": "हटउन",
"title": "उपकरणहर"
},
"profile": {
"finish": "समदन समत गर",
"firstColor": "पइल रङ एक",
"secondColor": "पइल रङ दई",
"title": "पइल तसर समदन गर",
"userIcon": "परयगकर आइकन"
},
"register": {
"cta": "स गर",
"text": "उपकरणहरच आफ cपरगति गर र तिहरई सिक र।",
"title": "कउडमिक गर"
},
"title": "ख"
},
"appearance": {
"activeTheme": "सकिय",
"themes": {
"blue": "नि",
"default": "सरण",
"gray": "ख",
"red": "र",
"teal": "हरि-न"
},
"title": "रप-रग"
},
"captions": {
"backgroundLabel": "पठभि असपषटत",
"colorLabel": "रङ",
"previewQuote": "म डरउनन। डर मनक हत।",
"textSizeLabel": "शबदक आकर",
"title": "कशन"
},
"connections": {
"server": {
"description": "यदि तप आफ भणरण गरन अनलन बकइनडम जडन गरन चहनछ भन, यसलई सकषम गर र URL परदन गर।",
"label": "अनलन सरभर",
"urlLabel": "अनलन सरभर URL"
},
"title": "सबनधहर",
"workers": {
"addButton": "नय worker हरस",
"description": "एपिसन परकय बनउनकि, सबिक पहरफत रट गरिएक छ। यदि तप आफमदरहरउन चहनछ भन यसलई सकषम गर।",
"emptyState": "अहिसमम worker हरनन, तल एउट थप",
"label": "आफ proxy workers हर चलउन",
"urlLabel": "Worker URL हर",
"urlPlaceholder": "https://"
}
},
"locale": {
"language": "एपक",
"languageDescription": "समण अनरयगम गरि।",
"title": "भ"
},
"reset": "रिट गर", "reset": "रिट गर",
"save": "सभ गर", "save": "सभ गर",
"sidebar": {
"info": {
"appVersion": "एप सकरण",
"backendUrl": "बकइनड URL",
"backendVersion": "बकएनड सकरण",
"hostname": "हटकम",
"insecure": "असरकित",
"notLoggedIn": "तप लगद इन हन",
"secure": "सरकित",
"title": "एप बनक",
"unknownVersion": "अजत",
"userId": "परयगकर ID"
}
},
"unsaved": "तपग सरकित नगरिएक परिवरतनहर छन" "unsaved": "तपग सरकित नगरिएक परिवरतनहर छन"
} }
} }

2
src/assets/locales/zh.json

@ -396,7 +396,7 @@
}, },
"locale": { "locale": {
"language": "应用程序语言", "language": "应用程序语言",
"languageDescription": "语言已应用到整个应用程序。", "languageDescription": "当前已应用到整个应用程序的语言。",
"title": "本地化" "title": "本地化"
}, },
"reset": "重设", "reset": "重设",

12
src/backend/helpers/report.ts

@ -9,6 +9,7 @@ import { PlayerMeta } from "@/stores/player/slices/source";
// for anybody who cares - these are anonymous metrics. // for anybody who cares - these are anonymous metrics.
// They are just used for figuring out if providers are broken or not // They are just used for figuring out if providers are broken or not
const metricsEndpoint = "https://backend.movie-web.app/metrics/providers"; const metricsEndpoint = "https://backend.movie-web.app/metrics/providers";
const captchaMetricsEndpoint = "https://backend.movie-web.app/metrics/captcha";
const batchId = () => nanoid(32); const batchId = () => nanoid(32);
export type ProviderMetric = { export type ProviderMetric = {
@ -136,8 +137,17 @@ export function scrapePartsToProviderMetric(
export function useReportProviders() { export function useReportProviders() {
const report = useCallback((items: ProviderMetric[]) => { const report = useCallback((items: ProviderMetric[]) => {
if (items.length === 0) return; if (items.length === 0) return;
reportProviders(items); reportProviders(items).catch(() => {});
}, []); }, []);
return { report }; return { report };
} }
export function reportCaptchaSolve(success: boolean) {
ofetch(captchaMetricsEndpoint, {
method: "POST",
body: {
success,
},
}).catch(() => {});
}

4
src/components/form/PassphraseDisplay.tsx

@ -25,7 +25,9 @@ export function PassphraseDisplay(props: { mnemonic: string }) {
return ( return (
<div className="rounded-lg border border-authentication-border/50 "> <div className="rounded-lg border border-authentication-border/50 ">
<div className="px-4 py-2 flex justify-between border-b border-authentication-border/50"> <div className="px-4 py-2 flex justify-between border-b border-authentication-border/50">
<p className="font-bold text-sm text-white">Passphrase</p> <p className="font-bold text-sm text-white">
{t("auth.generate.passphraseFrameLabel")}
</p>
<button <button
type="button" type="button"
className="text-authentication-copyText hover:text-authentication-copyTextHover transition-colors flex gap-2 items-center cursor-pointer" className="text-authentication-copyText hover:text-authentication-copyTextHover transition-colors flex gap-2 items-center cursor-pointer"

2
src/components/utils/Lightbar.tsx

@ -160,7 +160,7 @@ function ParticlesCanvas() {
} }
// Fish easter egg // Fish easter egg
const shouldShowFishie = Math.floor(Math.random() * 600) === 1; const shouldShowFishie = Math.floor(Math.random() * 600) === 69;
if (shouldShowFishie) { if (shouldShowFishie) {
imageOverride = [ imageOverride = [
{ {

8
src/hooks/auth/useAuthData.ts

@ -24,7 +24,9 @@ export function useAuthData() {
const clearProgress = useProgressStore((s) => s.clear); const clearProgress = useProgressStore((s) => s.clear);
const setTheme = useThemeStore((s) => s.setTheme); const setTheme = useThemeStore((s) => s.setTheme);
const setAppLanguage = useLanguageStore((s) => s.setLanguage); const setAppLanguage = useLanguageStore((s) => s.setLanguage);
const setCaptionLanguage = useSubtitleStore((s) => s.setLanguage); const importSubtitleLanguage = useSubtitleStore(
(s) => s.importSubtitleLanguage
);
const replaceBookmarks = useBookmarkStore((s) => s.replaceBookmarks); const replaceBookmarks = useBookmarkStore((s) => s.replaceBookmarks);
const replaceItems = useProgressStore((s) => s.replaceItems); const replaceItems = useProgressStore((s) => s.replaceItems);
@ -72,7 +74,7 @@ export function useAuthData() {
} }
if (settings.defaultSubtitleLanguage) { if (settings.defaultSubtitleLanguage) {
setCaptionLanguage(settings.defaultSubtitleLanguage); importSubtitleLanguage(settings.defaultSubtitleLanguage);
} }
if (settings.applicationTheme) { if (settings.applicationTheme) {
@ -83,7 +85,7 @@ export function useAuthData() {
replaceBookmarks, replaceBookmarks,
replaceItems, replaceItems,
setAppLanguage, setAppLanguage,
setCaptionLanguage, importSubtitleLanguage,
setTheme, setTheme,
] ]
); );

2
src/hooks/useSettingsState.ts

@ -24,7 +24,7 @@ export function useDerived<T>(
const setter = useCallback<Dispatch<SetStateAction<T>>>( const setter = useCallback<Dispatch<SetStateAction<T>>>(
(inp) => { (inp) => {
if (!(inp instanceof Function)) setOverwrite(inp); if (!(inp instanceof Function)) setOverwrite(inp);
else setOverwrite((s) => inp(s ?? initial)); else setOverwrite((s) => inp(s !== undefined ? s : initial));
}, },
[initial, setOverwrite] [initial, setOverwrite]
); );

1
src/index.tsx

@ -10,7 +10,6 @@ import ReactDOM from "react-dom";
import { HelmetProvider } from "react-helmet-async"; import { HelmetProvider } from "react-helmet-async";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { BrowserRouter, HashRouter } from "react-router-dom"; import { BrowserRouter, HashRouter } from "react-router-dom";
import Turnstile from "react-turnstile";
import { useAsync } from "react-use"; import { useAsync } from "react-use";
import { Button } from "@/components/buttons/Button"; import { Button } from "@/components/buttons/Button";

2
src/pages/Settings.tsx

@ -196,7 +196,7 @@ export function SettingsPage() {
<SettingsLayout> <SettingsLayout>
<div id="settings-account"> <div id="settings-account">
<Heading1 border className="!mb-0"> <Heading1 border className="!mb-0">
Account {t("settings.account.title")}
</Heading1> </Heading1>
{user.account && state.profile.state ? ( {user.account && state.profile.state ? (
<AccountSettings <AccountSettings

2
src/pages/parts/settings/SidebarPart.tsx

@ -122,7 +122,7 @@ export function SidebarPart() {
boundaryElement=".sidebar-boundary" boundaryElement=".sidebar-boundary"
> >
<div className="hidden lg:block"> <div className="hidden lg:block">
<SidebarSection title="Settings"> <SidebarSection title={t("global.pages.settings")}>
{settingLinks.map((v) => ( {settingLinks.map((v) => (
<SidebarLink <SidebarLink
icon={v.icon} icon={v.icon}

12
src/stores/turnstile/index.tsx

@ -2,6 +2,7 @@ import Turnstile, { BoundTurnstileObject } from "react-turnstile";
import { create } from "zustand"; import { create } from "zustand";
import { immer } from "zustand/middleware/immer"; import { immer } from "zustand/middleware/immer";
import { reportCaptchaSolve } from "@/backend/helpers/report";
import { conf } from "@/setup/config"; import { conf } from "@/setup/config";
export interface TurnstileStore { export interface TurnstileStore {
@ -52,11 +53,18 @@ export function isTurnstileInitialized() {
return !!getTurnstile(); return !!getTurnstile();
} }
export function getTurnstileToken() { export async function getTurnstileToken() {
const turnstile = getTurnstile(); const turnstile = getTurnstile();
turnstile?.reset(); turnstile?.reset();
turnstile?.execute(); turnstile?.execute();
return useTurnstileStore.getState().getToken(); try {
const token = await useTurnstileStore.getState().getToken();
reportCaptchaSolve(true);
return token;
} catch (err) {
reportCaptchaSolve(false);
throw err;
}
} }
export function TurnstileProvider() { export function TurnstileProvider() {

Loading…
Cancel
Save