Compare commits

..

10 Commits

Author SHA1 Message Date
mrjvs
5468a4677b Merge pull request #282 from movie-web/dev
v3.0.14
2023-04-25 17:47:13 +02:00
mrjvs
85cfba1a7a Merge branch 'master' into dev 2023-04-25 17:41:12 +02:00
mrjvs
fd6895c326 Merge pull request #281 from movie-web/fix-referer-maybe
Fix referer maybe
2023-04-25 17:39:11 +02:00
mrjvs
dfc3d9e50f Merge branch 'dev' into fix-referer-maybe 2023-04-25 17:38:27 +02:00
mrjvs
fcdf45d3f5 bump version for real 2023-04-25 17:37:49 +02:00
mrjvs
592837e2a6 bump version for a small release 2023-04-25 17:35:59 +02:00
mrjvs
9b3c1ffa28 add some dev routes back 2023-04-25 17:35:09 +02:00
mrjvs
7cb9ccaf14 referrer policy 2023-04-25 17:35:03 +02:00
mrjvs
4c0c61b0b9 Merge pull request #278 from yilmazcabuk/dev
style: sort imports according to ESLint rules
2023-04-25 00:55:41 +02:00
Yılmaz ÇABUK
4880d46dc4 style: sort imports according to ESLint rules
This commit updates the import statements in the codebase to comply with ESLint rules for import ordering. All imports have been sorted alphabetically and grouped according to the specified import groups in the ESLint configuration. This improves the codebase's consistency and maintainability.
2023-04-24 18:41:54 +03:00
134 changed files with 482 additions and 295 deletions

View File

@@ -8,27 +8,28 @@ const a11yOff = Object.keys(require("eslint-plugin-jsx-a11y").rules).reduce(
module.exports = { module.exports = {
env: { env: {
browser: true browser: true,
}, },
extends: [ extends: [
"airbnb", "airbnb",
"airbnb/hooks", "airbnb/hooks",
"plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended",
"prettier", "plugin:prettier/recommended",
"plugin:prettier/recommended"
], ],
ignorePatterns: ["public/*", "dist/*", "/*.js", "/*.ts"], ignorePatterns: ["public/*", "dist/*", "/*.js", "/*.ts"],
parser: "@typescript-eslint/parser", parser: "@typescript-eslint/parser",
parserOptions: { parserOptions: {
project: "./tsconfig.json", project: "./tsconfig.json",
tsconfigRootDir: "./" tsconfigRootDir: "./",
}, },
settings: { settings: {
"import/resolver": { "import/resolver": {
typescript: {} typescript: {
} project: "./tsconfig.json",
},
},
}, },
plugins: ["@typescript-eslint", "import"], plugins: ["@typescript-eslint", "import", "prettier"],
rules: { rules: {
"react/jsx-uses-react": "off", "react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off", "react/react-in-jsx-scope": "off",
@@ -54,16 +55,44 @@ module.exports = {
"@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }], "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
"react/jsx-filename-extension": [ "react/jsx-filename-extension": [
"error", "error",
{ extensions: [".js", ".tsx", ".jsx"] } { extensions: [".js", ".tsx", ".jsx"] },
], ],
"import/extensions": [ "import/extensions": [
"error", "error",
"ignorePackages", "ignorePackages",
{ {
ts: "never", ts: "never",
tsx: "never" tsx: "never",
} },
], ],
...a11yOff "import/order": [
} "error",
{
groups: [
"builtin",
"external",
"internal",
["sibling", "parent"],
"index",
"unknown",
],
"newlines-between": "always",
alphabetize: {
order: "asc",
caseInsensitive: true,
},
},
],
"sort-imports": [
"error",
{
ignoreCase: false,
ignoreDeclarationSort: true,
ignoreMemberSort: false,
memberSyntaxSortOrder: ["none", "all", "multiple", "single"],
allowSeparatedGroups: true,
},
],
...a11yOff,
},
}; };

View File

@@ -29,6 +29,9 @@
<!-- prevent darkreader extension from messing with our already dark site --> <!-- prevent darkreader extension from messing with our already dark site -->
<meta name="darkreader-lock" /> <meta name="darkreader-lock" />
<!-- disabling referrer can fix some provider problems -->
<meta name="referrer" content="no-referrer" />
<title>movie-web</title> <title>movie-web</title>
</head> </head>
<body> <body>

View File

@@ -1,6 +1,6 @@
{ {
"name": "movie-web", "name": "movie-web",
"version": "3.0.13", "version": "3.0.14",
"private": true, "private": true,
"homepage": "https://movie-web.app", "homepage": "https://movie-web.app",
"dependencies": { "dependencies": {
@@ -82,7 +82,7 @@
"eslint-config-airbnb": "19.0.4", "eslint-config-airbnb": "19.0.4",
"eslint-config-prettier": "^8.6.0", "eslint-config-prettier": "^8.6.0",
"eslint-import-resolver-typescript": "^2.5.0", "eslint-import-resolver-typescript": "^2.5.0",
"eslint-plugin-import": "^2.25.4", "eslint-plugin-import": "^2.27.5",
"eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "7.29.4", "eslint-plugin-react": "7.29.4",

View File

@@ -1,9 +1,10 @@
import { describe, it } from "vitest"; import { describe, it } from "vitest";
import "@/backend"; import "@/backend";
import { getProviders } from "@/backend/helpers/register";
import { MWMediaType } from "@/backend/metadata/types";
import { runProvider } from "@/backend/helpers/run";
import { testData } from "@/__tests__/providers/testdata"; import { testData } from "@/__tests__/providers/testdata";
import { getProviders } from "@/backend/helpers/register";
import { runProvider } from "@/backend/helpers/run";
import { MWMediaType } from "@/backend/metadata/types";
describe("providers", () => { describe("providers", () => {
const providers = getProviders(); const providers = getProviders();

View File

@@ -1,11 +1,11 @@
import { MWEmbedType } from "@/backend/helpers/embed"; import { MWEmbedType } from "@/backend/helpers/embed";
import { proxiedFetch } from "@/backend/helpers/fetch";
import { registerEmbedScraper } from "@/backend/helpers/register"; import { registerEmbedScraper } from "@/backend/helpers/register";
import { import {
MWEmbedStream,
MWStreamQuality, MWStreamQuality,
MWStreamType, MWStreamType,
MWEmbedStream,
} from "@/backend/helpers/streams"; } from "@/backend/helpers/streams";
import { proxiedFetch } from "@/backend/helpers/fetch";
const HOST = "streamm4u.club"; const HOST = "streamm4u.club";
const URL_BASE = `https://${HOST}`; const URL_BASE = `https://${HOST}`;

View File

@@ -1,8 +1,9 @@
import DOMPurify from "dompurify";
import { detect, list, parse } from "subsrt-ts";
import { ContentCaption } from "subsrt-ts/dist/types/handler";
import { mwFetch, proxiedFetch } from "@/backend/helpers/fetch"; import { mwFetch, proxiedFetch } from "@/backend/helpers/fetch";
import { MWCaption } from "@/backend/helpers/streams"; import { MWCaption } from "@/backend/helpers/streams";
import DOMPurify from "dompurify";
import { parse, detect, list } from "subsrt-ts";
import { ContentCaption } from "subsrt-ts/dist/types/handler";
export const customCaption = "external-custom"; export const customCaption = "external-custom";
export function makeCaptionId(caption: MWCaption, isLinked: boolean): string { export function makeCaptionId(caption: MWCaption, isLinked: boolean): string {

View File

@@ -1,6 +1,7 @@
import { conf } from "@/setup/config";
import { ofetch } from "ofetch"; import { ofetch } from "ofetch";
import { conf } from "@/setup/config";
let proxyUrlIndex = Math.floor(Math.random() * conf().PROXY_URLS.length); let proxyUrlIndex = Math.floor(Math.random() * conf().PROXY_URLS.length);
// round robins all proxy urls // round robins all proxy urls

View File

@@ -1,7 +1,7 @@
import { DetailedMeta } from "../metadata/getmeta";
import { MWMediaType } from "../metadata/types";
import { MWEmbed } from "./embed"; import { MWEmbed } from "./embed";
import { MWStream } from "./streams"; import { MWStream } from "./streams";
import { DetailedMeta } from "../metadata/getmeta";
import { MWMediaType } from "../metadata/types";
export type MWProviderScrapeResult = { export type MWProviderScrapeResult = {
stream?: MWStream; stream?: MWStream;

View File

@@ -1,13 +1,14 @@
import { FetchError } from "ofetch"; import { FetchError } from "ofetch";
import { makeUrl, proxiedFetch } from "../helpers/fetch";
import { import {
formatJWMeta,
JWMediaResult, JWMediaResult,
JWSeasonMetaResult, JWSeasonMetaResult,
JW_API_BASE, JW_API_BASE,
formatJWMeta,
mediaTypeToJW, mediaTypeToJW,
} from "./justwatch"; } from "./justwatch";
import { MWMediaMeta, MWMediaType } from "./types"; import { MWMediaMeta, MWMediaType } from "./types";
import { makeUrl, proxiedFetch } from "../helpers/fetch";
type JWExternalIdType = type JWExternalIdType =
| "eidr" | "eidr"

View File

@@ -1,13 +1,14 @@
import { SimpleCache } from "@/utils/cache"; import { SimpleCache } from "@/utils/cache";
import { proxiedFetch } from "../helpers/fetch";
import { import {
formatJWMeta,
JWContentTypes, JWContentTypes,
JWMediaResult, JWMediaResult,
JW_API_BASE, JW_API_BASE,
formatJWMeta,
mediaTypeToJW, mediaTypeToJW,
} from "./justwatch"; } from "./justwatch";
import { MWMediaMeta, MWQuery } from "./types"; import { MWMediaMeta, MWQuery } from "./types";
import { proxiedFetch } from "../helpers/fetch";
const cache = new SimpleCache<MWQuery, MWMediaMeta[]>(); const cache = new SimpleCache<MWQuery, MWMediaMeta[]>();
cache.setCompare((a, b) => { cache.setCompare((a, b) => {

View File

@@ -1,4 +1,5 @@
import { compareTitle } from "@/utils/titleMatch"; import { compareTitle } from "@/utils/titleMatch";
import { proxiedFetch } from "../helpers/fetch"; import { proxiedFetch } from "../helpers/fetch";
import { registerProvider } from "../helpers/register"; import { registerProvider } from "../helpers/register";
import { import {

View File

@@ -1,9 +1,10 @@
import { unpack } from "unpacker";
import CryptoJS from "crypto-js"; import CryptoJS from "crypto-js";
import { unpack } from "unpacker";
import { registerProvider } from "@/backend/helpers/register"; import { registerProvider } from "@/backend/helpers/register";
import { MWMediaType } from "@/backend/metadata/types";
import { MWStreamQuality } from "@/backend/helpers/streams"; import { MWStreamQuality } from "@/backend/helpers/streams";
import { MWMediaType } from "@/backend/metadata/types";
import { proxiedFetch } from "../helpers/fetch"; import { proxiedFetch } from "../helpers/fetch";
const format = { const format = {

View File

@@ -1,4 +1,5 @@
import { MWEmbed, MWEmbedType } from "@/backend/helpers/embed"; import { MWEmbed, MWEmbedType } from "@/backend/helpers/embed";
import { proxiedFetch } from "../helpers/fetch"; import { proxiedFetch } from "../helpers/fetch";
import { registerProvider } from "../helpers/register"; import { registerProvider } from "../helpers/register";
import { MWMediaType } from "../metadata/types"; import { MWMediaType } from "../metadata/types";

View File

@@ -1,15 +1,15 @@
import { registerProvider } from "@/backend/helpers/register";
import { MWMediaType } from "@/backend/metadata/types";
import { customAlphabet } from "nanoid";
import CryptoJS from "crypto-js"; import CryptoJS from "crypto-js";
import { customAlphabet } from "nanoid";
import { proxiedFetch } from "@/backend/helpers/fetch"; import { proxiedFetch } from "@/backend/helpers/fetch";
import { registerProvider } from "@/backend/helpers/register";
import { import {
MWCaption, MWCaption,
MWCaptionType, MWCaptionType,
MWStreamQuality, MWStreamQuality,
MWStreamType, MWStreamType,
} from "@/backend/helpers/streams"; } from "@/backend/helpers/streams";
import { MWMediaType } from "@/backend/metadata/types";
import { compareTitle } from "@/utils/titleMatch"; import { compareTitle } from "@/utils/titleMatch";
const nanoid = customAlphabet("0123456789abcdef", 32); const nanoid = customAlphabet("0123456789abcdef", 32);

View File

@@ -1,6 +1,7 @@
import { Icon, Icons } from "@/components/Icon";
import { ReactNode } from "react"; import { ReactNode } from "react";
import { Icon, Icons } from "@/components/Icon";
interface Props { interface Props {
icon?: Icons; icon?: Icons;
onClick?: () => void; onClick?: () => void;

View File

@@ -1,4 +1,5 @@
import { useSettings } from "@/state/settings"; import { useSettings } from "@/state/settings";
import { Icon, Icons } from "./Icon"; import { Icon, Icons } from "./Icon";
export const colors = ["#ffffff", "#00ffff", "#ffff00"]; export const colors = ["#ffffff", "#00ffff", "#ffff00"];

View File

@@ -1,6 +1,6 @@
import { Listbox, Transition } from "@headlessui/react";
import React, { Fragment } from "react"; import React, { Fragment } from "react";
import { Listbox, Transition } from "@headlessui/react";
import { Icon, Icons } from "@/components/Icon"; import { Icon, Icons } from "@/components/Icon";
export interface OptionItem { export interface OptionItem {

View File

@@ -1,6 +1,7 @@
import { Transition } from "@/components/Transition";
import { Helmet } from "react-helmet"; import { Helmet } from "react-helmet";
import { Transition } from "@/components/Transition";
export function Overlay(props: { children: React.ReactNode }) { export function Overlay(props: { children: React.ReactNode }) {
return ( return (
<> <>

View File

@@ -1,6 +1,8 @@
import { MWMediaType, MWQuery } from "@/backend/metadata/types";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { MWMediaType, MWQuery } from "@/backend/metadata/types";
import { DropdownButton } from "./buttons/DropdownButton"; import { DropdownButton } from "./buttons/DropdownButton";
import { Icon, Icons } from "./Icon"; import { Icon, Icons } from "./Icon";
import { TextInputControl } from "./text-inputs/TextInputControl"; import { TextInputControl } from "./text-inputs/TextInputControl";

View File

@@ -1,8 +1,8 @@
import { Fragment, ReactNode } from "react";
import { import {
Transition as HeadlessTransition, Transition as HeadlessTransition,
TransitionClasses, TransitionClasses,
} from "@headlessui/react"; } from "@headlessui/react";
import { Fragment, ReactNode } from "react";
type TransitionAnimations = type TransitionAnimations =
| "slide-down" | "slide-down"

View File

@@ -4,10 +4,11 @@ import React, {
useEffect, useEffect,
useState, useState,
} from "react"; } from "react";
import { Icon, Icons } from "@/components/Icon";
import { Icon, Icons } from "@/components/Icon";
import { BackdropContainer, useBackdrop } from "@/components/layout/Backdrop"; import { BackdropContainer, useBackdrop } from "@/components/layout/Backdrop";
import { ButtonControlProps, ButtonControl } from "./ButtonControl";
import { ButtonControl, ButtonControlProps } from "./ButtonControl";
export interface OptionItem { export interface OptionItem {
id: string; id: string;

View File

@@ -1,7 +1,9 @@
import { Icon, Icons } from "@/components/Icon";
import { useAutoAnimate } from "@formkit/auto-animate/react"; import { useAutoAnimate } from "@formkit/auto-animate/react";
import { useCallback } from "react"; import { useCallback } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Icon, Icons } from "@/components/Icon";
import { ButtonControl } from "./ButtonControl"; import { ButtonControl } from "./ButtonControl";
export interface EditButtonProps { export interface EditButtonProps {

View File

@@ -1,5 +1,6 @@
import { Icon, Icons } from "@/components/Icon"; import { Icon, Icons } from "@/components/Icon";
import { ButtonControlProps, ButtonControl } from "./ButtonControl";
import { ButtonControl, ButtonControlProps } from "./ButtonControl";
export interface IconButtonProps extends ButtonControlProps { export interface IconButtonProps extends ButtonControlProps {
icon: Icons; icon: Icons;

View File

@@ -1,5 +1,6 @@
import React, { createRef, useEffect, useState } from "react"; import React, { createRef, useEffect, useState } from "react";
import { createPortal } from "react-dom"; import { createPortal } from "react-dom";
import { useFade } from "@/hooks/useFade"; import { useFade } from "@/hooks/useFade";
interface BackdropProps { interface BackdropProps {

View File

@@ -1,4 +1,5 @@
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Icon, Icons } from "@/components/Icon"; import { Icon, Icons } from "@/components/Icon";
export function BrandPill(props: { export function BrandPill(props: {

View File

@@ -1,10 +1,11 @@
import { Component } from "react"; import { Component } from "react";
import { Trans, useTranslation } from "react-i18next";
import { IconPatch } from "@/components/buttons/IconPatch"; import { IconPatch } from "@/components/buttons/IconPatch";
import { Icons } from "@/components/Icon"; import { Icons } from "@/components/Icon";
import { Link } from "@/components/text/Link"; import { Link } from "@/components/text/Link";
import { Title } from "@/components/text/Title"; import { Title } from "@/components/text/Title";
import { conf } from "@/setup/config"; import { conf } from "@/setup/config";
import { Trans, useTranslation } from "react-i18next";
interface ErrorShowcaseProps { interface ErrorShowcaseProps {
error: { error: {

View File

@@ -1,8 +1,9 @@
import { Overlay } from "@/components/Overlay";
import { Transition } from "@/components/Transition";
import { ReactNode } from "react"; import { ReactNode } from "react";
import { createPortal } from "react-dom"; import { createPortal } from "react-dom";
import { Overlay } from "@/components/Overlay";
import { Transition } from "@/components/Transition";
interface Props { interface Props {
show: boolean; show: boolean;
children?: ReactNode; children?: ReactNode;

View File

@@ -1,10 +1,12 @@
import { ReactNode, useState } from "react"; import { ReactNode, useState } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { IconPatch } from "@/components/buttons/IconPatch"; import { IconPatch } from "@/components/buttons/IconPatch";
import { Icons } from "@/components/Icon"; import { Icons } from "@/components/Icon";
import { conf } from "@/setup/config";
import { useBannerSize } from "@/hooks/useBanner"; import { useBannerSize } from "@/hooks/useBanner";
import { conf } from "@/setup/config";
import SettingsModal from "@/views/SettingsModal"; import SettingsModal from "@/views/SettingsModal";
import { BrandPill } from "./BrandPill"; import { BrandPill } from "./BrandPill";
export interface NavigationProps { export interface NavigationProps {

View File

@@ -1,4 +1,5 @@
import { ReactNode } from "react"; import { ReactNode } from "react";
import { Icon, Icons } from "@/components/Icon"; import { Icon, Icons } from "@/components/Icon";
interface SectionHeadingProps { interface SectionHeadingProps {

View File

@@ -1,10 +1,12 @@
import { Link } from "react-router-dom";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { DotList } from "@/components/text/DotList"; import { Link } from "react-router-dom";
import { MWMediaMeta } from "@/backend/metadata/types";
import { JWMediaToId } from "@/backend/metadata/justwatch"; import { JWMediaToId } from "@/backend/metadata/justwatch";
import { Icons } from "../Icon"; import { MWMediaMeta } from "@/backend/metadata/types";
import { DotList } from "@/components/text/DotList";
import { IconPatch } from "../buttons/IconPatch"; import { IconPatch } from "../buttons/IconPatch";
import { Icons } from "../Icon";
export interface MediaCardProps { export interface MediaCardProps {
media: MWMediaMeta; media: MWMediaMeta;

View File

@@ -1,6 +1,8 @@
import { useMemo } from "react";
import { MWMediaMeta } from "@/backend/metadata/types"; import { MWMediaMeta } from "@/backend/metadata/types";
import { useWatchedContext } from "@/state/watched"; import { useWatchedContext } from "@/state/watched";
import { useMemo } from "react";
import { MediaCard } from "./MediaCard"; import { MediaCard } from "./MediaCard";
export interface WatchedMediaCardProps { export interface WatchedMediaCardProps {

View File

@@ -1,12 +1,14 @@
import { animated, easings, useSpringValue } from "@react-spring/web";
import { ReactNode, useCallback, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { FloatingCardAnchorPosition } from "@/components/popout/positions/FloatingCardAnchorPosition"; import { FloatingCardAnchorPosition } from "@/components/popout/positions/FloatingCardAnchorPosition";
import { FloatingCardMobilePosition } from "@/components/popout/positions/FloatingCardMobilePosition"; import { FloatingCardMobilePosition } from "@/components/popout/positions/FloatingCardMobilePosition";
import { useIsMobile } from "@/hooks/useIsMobile"; import { useIsMobile } from "@/hooks/useIsMobile";
import { PopoutSection } from "@/video/components/popouts/PopoutUtils"; import { PopoutSection } from "@/video/components/popouts/PopoutUtils";
import { useSpringValue, animated, easings } from "@react-spring/web";
import { ReactNode, useCallback, useEffect, useRef, useState } from "react";
import { Icon, Icons } from "../Icon";
import { FloatingDragHandle, MobilePopoutSpacer } from "./FloatingDragHandle"; import { FloatingDragHandle, MobilePopoutSpacer } from "./FloatingDragHandle";
import { Icon, Icons } from "../Icon";
interface FloatingCardProps { interface FloatingCardProps {
children?: ReactNode; children?: ReactNode;

View File

@@ -1,4 +1,3 @@
import { Transition } from "@/components/Transition";
import React, { import React, {
ReactNode, ReactNode,
useCallback, useCallback,
@@ -8,6 +7,8 @@ import React, {
} from "react"; } from "react";
import { createPortal } from "react-dom"; import { createPortal } from "react-dom";
import { Transition } from "@/components/Transition";
interface Props { interface Props {
children?: ReactNode; children?: ReactNode;
onClose?: () => void; onClose?: () => void;

View File

@@ -1,6 +1,7 @@
import { ReactNode } from "react";
import { Transition } from "@/components/Transition"; import { Transition } from "@/components/Transition";
import { useIsMobile } from "@/hooks/useIsMobile"; import { useIsMobile } from "@/hooks/useIsMobile";
import { ReactNode } from "react";
interface Props { interface Props {
children?: ReactNode; children?: ReactNode;

View File

@@ -1,6 +1,7 @@
import { createFloatingAnchorEvent } from "@/components/popout/FloatingAnchor";
import { ReactNode, useCallback, useEffect, useRef, useState } from "react"; import { ReactNode, useCallback, useEffect, useRef, useState } from "react";
import { createFloatingAnchorEvent } from "@/components/popout/FloatingAnchor";
interface AnchorPositionProps { interface AnchorPositionProps {
children?: ReactNode; children?: ReactNode;
id: string; id: string;

View File

@@ -1,4 +1,4 @@
import { useSpring, animated, config } from "@react-spring/web"; import { animated, config, useSpring } from "@react-spring/web";
import { useDrag } from "@use-gesture/react"; import { useDrag } from "@use-gesture/react";
import { ReactNode, useEffect, useRef, useState } from "react"; import { ReactNode, useEffect, useRef, useState } from "react";

View File

@@ -1,4 +1,5 @@
import { Link as LinkRouter } from "react-router-dom"; import { Link as LinkRouter } from "react-router-dom";
import { Icon, Icons } from "@/components/Icon"; import { Icon, Icons } from "@/components/Icon";
interface IArrowLinkPropsBase { interface IArrowLinkPropsBase {

View File

@@ -1,12 +1,12 @@
import { import {
ReactNode,
createContext,
useState,
useMemo,
Dispatch, Dispatch,
ReactNode,
SetStateAction, SetStateAction,
useEffect, createContext,
useContext, useContext,
useEffect,
useMemo,
useState,
} from "react"; } from "react";
import { useMeasure } from "react-use"; import { useMeasure } from "react-use";

View File

@@ -1,8 +1,9 @@
/// <reference types="chromecast-caf-sender"/> /// <reference types="chromecast-caf-sender"/>
import { isChromecastAvailable } from "@/setup/chromecast";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { isChromecastAvailable } from "@/setup/chromecast";
export function useChromecastAvailable() { export function useChromecastAvailable() {
const [available, setAvailable] = useState<boolean | null>(null); const [available, setAvailable] = useState<boolean | null>(null);

View File

@@ -1,8 +1,9 @@
import { useEffect, useState } from "react";
import { findBestStream } from "@/backend/helpers/scrape"; import { findBestStream } from "@/backend/helpers/scrape";
import { MWStream } from "@/backend/helpers/streams"; import { MWStream } from "@/backend/helpers/streams";
import { DetailedMeta } from "@/backend/metadata/getmeta"; import { DetailedMeta } from "@/backend/metadata/getmeta";
import { MWMediaType } from "@/backend/metadata/types"; import { MWMediaType } from "@/backend/metadata/types";
import { useEffect, useState } from "react";
export interface ScrapeEventLog { export interface ScrapeEventLog {
type: "provider" | "embed"; type: "provider" | "embed";

View File

@@ -1,7 +1,8 @@
import { MWMediaType, MWQuery } from "@/backend/metadata/types";
import { useState } from "react"; import { useState } from "react";
import { generatePath, useHistory, useRouteMatch } from "react-router-dom"; import { generatePath, useHistory, useRouteMatch } from "react-router-dom";
import { MWMediaType, MWQuery } from "@/backend/metadata/types";
function getInitialValue(params: { type: string; query: string }) { function getInitialValue(params: { type: string; query: string }) {
const type = const type =
Object.values(MWMediaType).find((v) => params.type === v) || Object.values(MWMediaType).find((v) => params.type === v) ||

View File

@@ -1,6 +1,7 @@
import { useState } from "react";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useMediaPlaying } from "@/video/state/logic/mediaplaying"; import { useMediaPlaying } from "@/video/state/logic/mediaplaying";
import { useState } from "react";
export function useVolumeControl(descriptor: string) { export function useVolumeControl(descriptor: string) {
const [storedVolume, setStoredVolume] = useState(1); const [storedVolume, setStoredVolume] = useState(1);

View File

@@ -3,11 +3,12 @@ import React, { Suspense } from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import { BrowserRouter, HashRouter } from "react-router-dom"; import { BrowserRouter, HashRouter } from "react-router-dom";
import type { ReactNode } from "react-router-dom/node_modules/@types/react/index"; import type { ReactNode } from "react-router-dom/node_modules/@types/react/index";
import { ErrorBoundary } from "@/components/layout/ErrorBoundary";
import { conf } from "@/setup/config";
import { registerSW } from "virtual:pwa-register"; import { registerSW } from "virtual:pwa-register";
import { ErrorBoundary } from "@/components/layout/ErrorBoundary";
import App from "@/setup/App"; import App from "@/setup/App";
import { conf } from "@/setup/config";
import "@/setup/ga"; import "@/setup/ga";
import "@/setup/sentry"; import "@/setup/sentry";
import "@/setup/i18n"; import "@/setup/i18n";

View File

@@ -1,16 +1,16 @@
import { lazy } from "react"; import { lazy } from "react";
import { Redirect, Route, Switch } from "react-router-dom"; import { Redirect, Route, Switch } from "react-router-dom";
import { BookmarkContextProvider } from "@/state/bookmark";
import { WatchedContextProvider } from "@/state/watched";
import { SettingsProvider } from "@/state/settings";
import { NotFoundPage } from "@/views/notfound/NotFoundView";
import { MediaView } from "@/views/media/MediaView";
import { SearchView } from "@/views/search/SearchView";
import { MWMediaType } from "@/backend/metadata/types"; import { MWMediaType } from "@/backend/metadata/types";
import { V2MigrationView } from "@/views/other/v2Migration";
import { BannerContextProvider } from "@/hooks/useBanner"; import { BannerContextProvider } from "@/hooks/useBanner";
import { Layout } from "@/setup/Layout"; import { Layout } from "@/setup/Layout";
import { BookmarkContextProvider } from "@/state/bookmark";
import { SettingsProvider } from "@/state/settings";
import { WatchedContextProvider } from "@/state/watched";
import { MediaView } from "@/views/media/MediaView";
import { NotFoundPage } from "@/views/notfound/NotFoundView";
import { V2MigrationView } from "@/views/other/v2Migration";
import { SearchView } from "@/views/search/SearchView";
function App() { function App() {
return ( return (
@@ -40,15 +40,23 @@ function App() {
/> />
{/* other */} {/* other */}
<Route
exact
path="/dev"
component={lazy(
() => import("@/views/developer/DeveloperView")
)}
/>
<Route
exact
path="/dev/video"
component={lazy(
() => import("@/views/developer/VideoTesterView")
)}
/>
{/* developer routes that can abuse workers are disabled in production */}
{process.env.NODE_ENV === "development" ? ( {process.env.NODE_ENV === "development" ? (
<> <>
<Route
exact
path="/dev"
component={lazy(
() => import("@/views/developer/DeveloperView")
)}
/>
<Route <Route
exact exact
path="/dev/test" path="/dev/test"
@@ -56,13 +64,7 @@ function App() {
() => import("@/views/developer/TestView") () => import("@/views/developer/TestView")
)} )}
/> />
<Route
exact
path="/dev/video"
component={lazy(
() => import("@/views/developer/VideoTesterView")
)}
/>
<Route <Route
exact exact
path="/dev/providers" path="/dev/providers"

View File

@@ -1,8 +1,9 @@
import { ReactNode } from "react";
import { useTranslation } from "react-i18next";
import { Banner } from "@/components/Banner"; import { Banner } from "@/components/Banner";
import { useBannerSize } from "@/hooks/useBanner"; import { useBannerSize } from "@/hooks/useBanner";
import { useIsOnline } from "@/hooks/usePing"; import { useIsOnline } from "@/hooks/usePing";
import { ReactNode } from "react";
import { useTranslation } from "react-i18next";
export function Layout(props: { children: ReactNode }) { export function Layout(props: { children: ReactNode }) {
const { t } = useTranslation(); const { t } = useTranslation();

View File

@@ -1,4 +1,4 @@
import { APP_VERSION, GITHUB_LINK, DISCORD_LINK } from "./constants"; import { APP_VERSION, DISCORD_LINK, GITHUB_LINK } from "./constants";
interface Config { interface Config {
APP_VERSION: string; APP_VERSION: string;

View File

@@ -1,4 +1,5 @@
import ReactGA from "react-ga4"; import ReactGA from "react-ga4";
import { GA_ID } from "@/setup/constants"; import { GA_ID } from "@/setup/constants";
ReactGA.initialize([ ReactGA.initialize([

View File

@@ -1,14 +1,13 @@
import i18n from "i18next"; import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector"; import LanguageDetector from "i18next-browser-languagedetector";
import { initReactI18next } from "react-i18next";
// Languages // Languages
import { captionLanguages } from "./iso6391";
import en from "./locales/en/translation.json"; import en from "./locales/en/translation.json";
import fr from "./locales/fr/translation.json";
import nl from "./locales/nl/translation.json"; import nl from "./locales/nl/translation.json";
import tr from "./locales/tr/translation.json"; import tr from "./locales/tr/translation.json";
import fr from "./locales/fr/translation.json";
import { captionLanguages } from "./iso6391";
const locales = { const locales = {
en: { en: {

View File

@@ -1,7 +1,8 @@
import * as Sentry from "@sentry/react";
import { CaptureConsole, HttpClient } from "@sentry/integrations"; import { CaptureConsole, HttpClient } from "@sentry/integrations";
import { SENTRY_DSN } from "@/setup/constants"; import * as Sentry from "@sentry/react";
import { conf } from "@/setup/config"; import { conf } from "@/setup/config";
import { SENTRY_DSN } from "@/setup/constants";
Sentry.init({ Sentry.init({
dsn: SENTRY_DSN, dsn: SENTRY_DSN,

View File

@@ -1,6 +1,8 @@
import { ReactNode, createContext, useContext, useMemo } from "react";
import { MWMediaMeta } from "@/backend/metadata/types"; import { MWMediaMeta } from "@/backend/metadata/types";
import { useStore } from "@/utils/storage"; import { useStore } from "@/utils/storage";
import { createContext, ReactNode, useContext, useMemo } from "react";
import { BookmarkStore } from "./store"; import { BookmarkStore } from "./store";
import { BookmarkStoreData } from "./types"; import { BookmarkStoreData } from "./types";

View File

@@ -1,6 +1,7 @@
import { createVersionedStore } from "@/utils/storage"; import { createVersionedStore } from "@/utils/storage";
import { migrateV1Bookmarks, OldBookmarks } from "../watched/migrations/v2";
import { BookmarkStoreData } from "./types"; import { BookmarkStoreData } from "./types";
import { OldBookmarks, migrateV1Bookmarks } from "../watched/migrations/v2";
export const BookmarkStore = createVersionedStore<BookmarkStoreData>() export const BookmarkStore = createVersionedStore<BookmarkStoreData>()
.setKey("mw-bookmarks") .setKey("mw-bookmarks")

View File

@@ -1,6 +1,8 @@
import { useStore } from "@/utils/storage"; import { ReactNode, createContext, useContext, useMemo } from "react";
import { createContext, ReactNode, useContext, useMemo } from "react";
import { LangCode } from "@/setup/iso6391"; import { LangCode } from "@/setup/iso6391";
import { useStore } from "@/utils/storage";
import { SettingsStore } from "./store"; import { SettingsStore } from "./store";
import { MWSettingsData } from "./types"; import { MWSettingsData } from "./types";

View File

@@ -1,4 +1,5 @@
import { createVersionedStore } from "@/utils/storage"; import { createVersionedStore } from "@/utils/storage";
import { MWSettingsData, MWSettingsDataV1 } from "./types"; import { MWSettingsData, MWSettingsDataV1 } from "./types";
export const SettingsStore = createVersionedStore<MWSettingsData>() export const SettingsStore = createVersionedStore<MWSettingsData>()

View File

@@ -1,16 +1,18 @@
import { DetailedMeta } from "@/backend/metadata/getmeta";
import { MWMediaType } from "@/backend/metadata/types";
import { useStore } from "@/utils/storage";
import { import {
createContext,
ReactNode, ReactNode,
createContext,
useCallback, useCallback,
useContext, useContext,
useMemo, useMemo,
useRef, useRef,
} from "react"; } from "react";
import { DetailedMeta } from "@/backend/metadata/getmeta";
import { MWMediaType } from "@/backend/metadata/types";
import { useStore } from "@/utils/storage";
import { VideoProgressStore } from "./store"; import { VideoProgressStore } from "./store";
import { StoreMediaItem, WatchedStoreItem, WatchedStoreData } from "./types"; import { StoreMediaItem, WatchedStoreData, WatchedStoreItem } from "./types";
const FIVETEEN_MINUTES = 15 * 60; const FIVETEEN_MINUTES = 15 * 60;
const FIVE_MINUTES = 5 * 60; const FIVE_MINUTES = 5 * 60;

View File

@@ -2,6 +2,7 @@ import { DetailedMeta, getMetaFromId } from "@/backend/metadata/getmeta";
import { searchForMedia } from "@/backend/metadata/search"; import { searchForMedia } from "@/backend/metadata/search";
import { MWMediaMeta, MWMediaType } from "@/backend/metadata/types"; import { MWMediaMeta, MWMediaType } from "@/backend/metadata/types";
import { compareTitle } from "@/utils/titleMatch"; import { compareTitle } from "@/utils/titleMatch";
import { WatchedStoreData, WatchedStoreItem } from "../types"; import { WatchedStoreData, WatchedStoreItem } from "../types";
interface OldMediaBase { interface OldMediaBase {

View File

@@ -1,5 +1,6 @@
import { createVersionedStore } from "@/utils/storage"; import { createVersionedStore } from "@/utils/storage";
import { migrateV2Videos, OldData } from "./migrations/v2";
import { OldData, migrateV2Videos } from "./migrations/v2";
import { WatchedStoreData } from "./types"; import { WatchedStoreData } from "./types";
export const VideoProgressStore = createVersionedStore<WatchedStoreData>() export const VideoProgressStore = createVersionedStore<WatchedStoreData>()

View File

@@ -1,36 +1,38 @@
import { ReactNode, useCallback, useState } from "react";
import { Transition } from "@/components/Transition"; import { Transition } from "@/components/Transition";
import { useIsMobile } from "@/hooks/useIsMobile"; import { useIsMobile } from "@/hooks/useIsMobile";
import { AirplayAction } from "@/video/components/actions/AirplayAction"; import { AirplayAction } from "@/video/components/actions/AirplayAction";
import { BackdropAction } from "@/video/components/actions/BackdropAction"; import { BackdropAction } from "@/video/components/actions/BackdropAction";
import { CastingTextAction } from "@/video/components/actions/CastingTextAction";
import { ChromecastAction } from "@/video/components/actions/ChromecastAction";
import { FullscreenAction } from "@/video/components/actions/FullscreenAction"; import { FullscreenAction } from "@/video/components/actions/FullscreenAction";
import { HeaderAction } from "@/video/components/actions/HeaderAction"; import { HeaderAction } from "@/video/components/actions/HeaderAction";
import { KeyboardShortcutsAction } from "@/video/components/actions/KeyboardShortcutsAction";
import { LoadingAction } from "@/video/components/actions/LoadingAction"; import { LoadingAction } from "@/video/components/actions/LoadingAction";
import { MiddlePauseAction } from "@/video/components/actions/MiddlePauseAction"; import { MiddlePauseAction } from "@/video/components/actions/MiddlePauseAction";
import { MobileCenterAction } from "@/video/components/actions/MobileCenterAction"; import { MobileCenterAction } from "@/video/components/actions/MobileCenterAction";
import { PageTitleAction } from "@/video/components/actions/PageTitleAction"; import { PageTitleAction } from "@/video/components/actions/PageTitleAction";
import { PauseAction } from "@/video/components/actions/PauseAction"; import { PauseAction } from "@/video/components/actions/PauseAction";
import { PictureInPictureAction } from "@/video/components/actions/PictureInPictureAction";
import { ProgressAction } from "@/video/components/actions/ProgressAction"; import { ProgressAction } from "@/video/components/actions/ProgressAction";
import { SeriesSelectionAction } from "@/video/components/actions/SeriesSelectionAction"; import { SeriesSelectionAction } from "@/video/components/actions/SeriesSelectionAction";
import { ShowTitleAction } from "@/video/components/actions/ShowTitleAction"; import { ShowTitleAction } from "@/video/components/actions/ShowTitleAction";
import { KeyboardShortcutsAction } from "@/video/components/actions/KeyboardShortcutsAction";
import { SkipTimeAction } from "@/video/components/actions/SkipTimeAction"; import { SkipTimeAction } from "@/video/components/actions/SkipTimeAction";
import { TimeAction } from "@/video/components/actions/TimeAction"; import { TimeAction } from "@/video/components/actions/TimeAction";
import { VolumeAction } from "@/video/components/actions/VolumeAction"; import { VolumeAction } from "@/video/components/actions/VolumeAction";
import { VideoPlayerError } from "@/video/components/parts/VideoPlayerError"; import { VideoPlayerError } from "@/video/components/parts/VideoPlayerError";
import { PopoutProviderAction } from "@/video/components/popouts/PopoutProviderAction";
import { import {
VideoPlayerBase, VideoPlayerBase,
VideoPlayerBaseProps, VideoPlayerBaseProps,
} from "@/video/components/VideoPlayerBase"; } from "@/video/components/VideoPlayerBase";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { ReactNode, useCallback, useState } from "react";
import { PopoutProviderAction } from "@/video/components/popouts/PopoutProviderAction";
import { ChromecastAction } from "@/video/components/actions/ChromecastAction";
import { CastingTextAction } from "@/video/components/actions/CastingTextAction";
import { PictureInPictureAction } from "@/video/components/actions/PictureInPictureAction";
import { CaptionRendererAction } from "./actions/CaptionRendererAction"; import { CaptionRendererAction } from "./actions/CaptionRendererAction";
import { SettingsAction } from "./actions/SettingsAction";
import { DividerAction } from "./actions/DividerAction"; import { DividerAction } from "./actions/DividerAction";
import { SettingsAction } from "./actions/SettingsAction";
import { VolumeAdjustedAction } from "./actions/VolumeAdjustedAction"; import { VolumeAdjustedAction } from "./actions/VolumeAdjustedAction";
type Props = VideoPlayerBaseProps; type Props = VideoPlayerBaseProps;

View File

@@ -1,15 +1,17 @@
import { useRef } from "react";
import { CastingInternal } from "@/video/components/internal/CastingInternal"; import { CastingInternal } from "@/video/components/internal/CastingInternal";
import { WrapperRegisterInternal } from "@/video/components/internal/WrapperRegisterInternal"; import { WrapperRegisterInternal } from "@/video/components/internal/WrapperRegisterInternal";
import { VideoErrorBoundary } from "@/video/components/parts/VideoErrorBoundary"; import { VideoErrorBoundary } from "@/video/components/parts/VideoErrorBoundary";
import { useInterface } from "@/video/state/logic/interface"; import { useInterface } from "@/video/state/logic/interface";
import { useMeta } from "@/video/state/logic/meta"; import { useMeta } from "@/video/state/logic/meta";
import { useRef } from "react";
import {
useVideoPlayerDescriptor,
VideoPlayerContextProvider,
} from "../state/hooks";
import { MetaAction } from "./actions/MetaAction"; import { MetaAction } from "./actions/MetaAction";
import { VideoElementInternal } from "./internal/VideoElementInternal"; import { VideoElementInternal } from "./internal/VideoElementInternal";
import {
VideoPlayerContextProvider,
useVideoPlayerDescriptor,
} from "../state/hooks";
export interface VideoPlayerBaseProps { export interface VideoPlayerBaseProps {
children?: children?:

View File

@@ -1,8 +1,10 @@
import { useCallback } from "react";
import { Icons } from "@/components/Icon"; import { Icons } from "@/components/Icon";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useMisc } from "@/video/state/logic/misc"; import { useMisc } from "@/video/state/logic/misc";
import { useCallback } from "react";
import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton"; import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton";
interface Props { interface Props {

View File

@@ -1,8 +1,9 @@
import React, { useCallback, useEffect, useRef, useState } from "react";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useInterface } from "@/video/state/logic/interface"; import { useInterface } from "@/video/state/logic/interface";
import { useMediaPlaying } from "@/video/state/logic/mediaplaying"; import { useMediaPlaying } from "@/video/state/logic/mediaplaying";
import React, { useCallback, useEffect, useRef, useState } from "react";
interface BackdropActionProps { interface BackdropActionProps {
children?: React.ReactNode; children?: React.ReactNode;

View File

@@ -1,9 +1,11 @@
import { Transition } from "@/components/Transition";
import { useSettings } from "@/state/settings";
import { sanitize, parseSubtitles } from "@/backend/helpers/captions";
import { ContentCaption } from "subsrt-ts/dist/types/handler";
import { useRef } from "react"; import { useRef } from "react";
import { useAsync } from "react-use"; import { useAsync } from "react-use";
import { ContentCaption } from "subsrt-ts/dist/types/handler";
import { parseSubtitles, sanitize } from "@/backend/helpers/captions";
import { Transition } from "@/components/Transition";
import { useSettings } from "@/state/settings";
import { useVideoPlayerDescriptor } from "../../state/hooks"; import { useVideoPlayerDescriptor } from "../../state/hooks";
import { useProgress } from "../../state/logic/progress"; import { useProgress } from "../../state/logic/progress";
import { useSource } from "../../state/logic/source"; import { useSource } from "../../state/logic/source";

View File

@@ -1,7 +1,8 @@
import { useTranslation } from "react-i18next";
import { Icon, Icons } from "@/components/Icon"; import { Icon, Icons } from "@/components/Icon";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useMisc } from "@/video/state/logic/misc"; import { useMisc } from "@/video/state/logic/misc";
import { useTranslation } from "react-i18next";
export function CastingTextAction() { export function CastingTextAction() {
const { t } = useTranslation(); const { t } = useTranslation();

View File

@@ -1,8 +1,9 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { Icons } from "@/components/Icon"; import { Icons } from "@/components/Icon";
import { VideoPlayerIconButton } from "@/video/components/parts/VideoPlayerIconButton"; import { VideoPlayerIconButton } from "@/video/components/parts/VideoPlayerIconButton";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useMisc } from "@/video/state/logic/misc"; import { useMisc } from "@/video/state/logic/misc";
import { useCallback, useEffect, useRef, useState } from "react";
interface Props { interface Props {
className?: string; className?: string;

View File

@@ -1,6 +1,6 @@
import { MWMediaType } from "@/backend/metadata/types";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useMeta } from "@/video/state/logic/meta"; import { useMeta } from "@/video/state/logic/meta";
import { MWMediaType } from "@/backend/metadata/types";
export function DividerAction() { export function DividerAction() {
const descriptor = useVideoPlayerDescriptor(); const descriptor = useVideoPlayerDescriptor();

View File

@@ -1,9 +1,11 @@
import { useCallback } from "react";
import { Icons } from "@/components/Icon"; import { Icons } from "@/components/Icon";
import { canFullscreen } from "@/utils/detectFeatures"; import { canFullscreen } from "@/utils/detectFeatures";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useInterface } from "@/video/state/logic/interface"; import { useInterface } from "@/video/state/logic/interface";
import { useCallback } from "react";
import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton"; import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton";
interface Props { interface Props {

View File

@@ -1,11 +1,12 @@
import { useEffect, useRef } from "react"; import { useEffect, useRef } from "react";
import { useVolumeControl } from "@/hooks/useVolumeToggle";
import { getPlayerState } from "@/video/state/cache";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useInterface } from "@/video/state/logic/interface"; import { useInterface } from "@/video/state/logic/interface";
import { getPlayerState } from "@/video/state/cache";
import { useMediaPlaying } from "@/video/state/logic/mediaplaying"; import { useMediaPlaying } from "@/video/state/logic/mediaplaying";
import { useProgress } from "@/video/state/logic/progress"; import { useProgress } from "@/video/state/logic/progress";
import { useVolumeControl } from "@/hooks/useVolumeToggle";
export function KeyboardShortcutsAction() { export function KeyboardShortcutsAction() {
const descriptor = useVideoPlayerDescriptor(); const descriptor = useVideoPlayerDescriptor();

View File

@@ -1,9 +1,10 @@
import { useEffect } from "react";
import { MWCaption } from "@/backend/helpers/streams"; import { MWCaption } from "@/backend/helpers/streams";
import { DetailedMeta } from "@/backend/metadata/getmeta"; import { DetailedMeta } from "@/backend/metadata/getmeta";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useMeta } from "@/video/state/logic/meta"; import { useMeta } from "@/video/state/logic/meta";
import { useProgress } from "@/video/state/logic/progress"; import { useProgress } from "@/video/state/logic/progress";
import { useEffect } from "react";
export type WindowMeta = { export type WindowMeta = {
meta: DetailedMeta; meta: DetailedMeta;

View File

@@ -1,8 +1,9 @@
import { useCallback } from "react";
import { Icon, Icons } from "@/components/Icon"; import { Icon, Icons } from "@/components/Icon";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useMediaPlaying } from "@/video/state/logic/mediaplaying"; import { useMediaPlaying } from "@/video/state/logic/mediaplaying";
import { useCallback } from "react";
export function MiddlePauseAction() { export function MiddlePauseAction() {
const descriptor = useVideoPlayerDescriptor(); const descriptor = useVideoPlayerDescriptor();

View File

@@ -1,5 +1,7 @@
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { Helmet } from "react-helmet"; import { Helmet } from "react-helmet";
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useCurrentSeriesEpisodeInfo } from "../hooks/useCurrentSeriesEpisodeInfo"; import { useCurrentSeriesEpisodeInfo } from "../hooks/useCurrentSeriesEpisodeInfo";
export function PageTitleAction() { export function PageTitleAction() {

View File

@@ -1,8 +1,10 @@
import { useCallback } from "react";
import { Icons } from "@/components/Icon"; import { Icons } from "@/components/Icon";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useMediaPlaying } from "@/video/state/logic/mediaplaying"; import { useMediaPlaying } from "@/video/state/logic/mediaplaying";
import { useCallback } from "react";
import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton"; import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton";
interface Props { interface Props {

View File

@@ -1,13 +1,15 @@
import { useCallback } from "react";
import { useTranslation } from "react-i18next";
import { Icons } from "@/components/Icon"; import { Icons } from "@/components/Icon";
import { useIsMobile } from "@/hooks/useIsMobile"; import { useIsMobile } from "@/hooks/useIsMobile";
import { useTranslation } from "react-i18next";
import { useControls } from "@/video/state/logic/controls";
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useCallback } from "react";
import { import {
canPictureInPicture, canPictureInPicture,
canWebkitPictureInPicture, canWebkitPictureInPicture,
} from "@/utils/detectFeatures"; } from "@/utils/detectFeatures";
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls";
import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton"; import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton";
interface Props { interface Props {

View File

@@ -1,3 +1,5 @@
import { useCallback, useEffect, useRef } from "react";
import { import {
makePercentage, makePercentage,
makePercentageString, makePercentageString,
@@ -7,7 +9,6 @@ import { getPlayerState } from "@/video/state/cache";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useProgress } from "@/video/state/logic/progress"; import { useProgress } from "@/video/state/logic/progress";
import { useCallback, useEffect, useRef } from "react";
export function ProgressAction() { export function ProgressAction() {
const descriptor = useVideoPlayerDescriptor(); const descriptor = useVideoPlayerDescriptor();

View File

@@ -1,12 +1,13 @@
import { Icons } from "@/components/Icon"; import { useTranslation } from "react-i18next";
import { MWMediaType } from "@/backend/metadata/types"; import { MWMediaType } from "@/backend/metadata/types";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { Icons } from "@/components/Icon";
import { useMeta } from "@/video/state/logic/meta"; import { FloatingAnchor } from "@/components/popout/FloatingAnchor";
import { VideoPlayerIconButton } from "@/video/components/parts/VideoPlayerIconButton"; import { VideoPlayerIconButton } from "@/video/components/parts/VideoPlayerIconButton";
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useInterface } from "@/video/state/logic/interface"; import { useInterface } from "@/video/state/logic/interface";
import { useTranslation } from "react-i18next"; import { useMeta } from "@/video/state/logic/meta";
import { FloatingAnchor } from "@/components/popout/FloatingAnchor";
interface Props { interface Props {
className?: string; className?: string;

View File

@@ -1,11 +1,12 @@
import { useTranslation } from "react-i18next";
import { Icons } from "@/components/Icon"; import { Icons } from "@/components/Icon";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { FloatingAnchor } from "@/components/popout/FloatingAnchor";
import { useIsMobile } from "@/hooks/useIsMobile";
import { VideoPlayerIconButton } from "@/video/components/parts/VideoPlayerIconButton"; import { VideoPlayerIconButton } from "@/video/components/parts/VideoPlayerIconButton";
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useInterface } from "@/video/state/logic/interface"; import { useInterface } from "@/video/state/logic/interface";
import { useIsMobile } from "@/hooks/useIsMobile";
import { useTranslation } from "react-i18next";
import { FloatingAnchor } from "@/components/popout/FloatingAnchor";
interface Props { interface Props {
className?: string; className?: string;

View File

@@ -1,4 +1,5 @@
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useCurrentSeriesEpisodeInfo } from "../hooks/useCurrentSeriesEpisodeInfo"; import { useCurrentSeriesEpisodeInfo } from "../hooks/useCurrentSeriesEpisodeInfo";
export function ShowTitleAction() { export function ShowTitleAction() {

View File

@@ -2,6 +2,7 @@ import { Icons } from "@/components/Icon";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useProgress } from "@/video/state/logic/progress"; import { useProgress } from "@/video/state/logic/progress";
import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton"; import { VideoPlayerIconButton } from "../parts/VideoPlayerIconButton";
interface Props { interface Props {

View File

@@ -1,11 +1,12 @@
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useIsMobile } from "@/hooks/useIsMobile";
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls";
import { useInterface } from "@/video/state/logic/interface";
import { useMediaPlaying } from "@/video/state/logic/mediaplaying"; import { useMediaPlaying } from "@/video/state/logic/mediaplaying";
import { useProgress } from "@/video/state/logic/progress"; import { useProgress } from "@/video/state/logic/progress";
import { useInterface } from "@/video/state/logic/interface";
import { VideoPlayerTimeFormat } from "@/video/state/types"; import { VideoPlayerTimeFormat } from "@/video/state/types";
import { useIsMobile } from "@/hooks/useIsMobile";
import { useControls } from "@/video/state/logic/controls";
function durationExceedsHour(secs: number): boolean { function durationExceedsHour(secs: number): boolean {
return secs > 60 * 60; return secs > 60 * 60;

View File

@@ -1,3 +1,5 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { Icon, Icons } from "@/components/Icon"; import { Icon, Icons } from "@/components/Icon";
import { import {
makePercentage, makePercentage,
@@ -10,7 +12,6 @@ import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useInterface } from "@/video/state/logic/interface"; import { useInterface } from "@/video/state/logic/interface";
import { useMediaPlaying } from "@/video/state/logic/mediaplaying"; import { useMediaPlaying } from "@/video/state/logic/mediaplaying";
import { useCallback, useEffect, useRef, useState } from "react";
interface Props { interface Props {
className?: string; className?: string;

View File

@@ -1,5 +1,7 @@
import { Icons } from "@/components/Icon";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Icons } from "@/components/Icon";
import { PopoutListAction } from "../../popouts/PopoutUtils"; import { PopoutListAction } from "../../popouts/PopoutUtils";
interface Props { interface Props {

View File

@@ -1,10 +1,12 @@
import { Icons } from "@/components/Icon";
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useSource } from "@/video/state/logic/source";
import { MWStreamType } from "@/backend/helpers/streams";
import { normalizeTitle } from "@/utils/normalizeTitle";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { MWStreamType } from "@/backend/helpers/streams";
import { Icons } from "@/components/Icon";
import { normalizeTitle } from "@/utils/normalizeTitle";
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useMeta } from "@/video/state/logic/meta"; import { useMeta } from "@/video/state/logic/meta";
import { useSource } from "@/video/state/logic/source";
import { PopoutListAction } from "../../popouts/PopoutUtils"; import { PopoutListAction } from "../../popouts/PopoutUtils";
export function DownloadAction() { export function DownloadAction() {

View File

@@ -1,5 +1,7 @@
import { Icons } from "@/components/Icon";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Icons } from "@/components/Icon";
import { PopoutListAction } from "../../popouts/PopoutUtils"; import { PopoutListAction } from "../../popouts/PopoutUtils";
interface Props { interface Props {

View File

@@ -1,7 +1,9 @@
import { Icons } from "@/components/Icon";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { PopoutListAction } from "../../popouts/PopoutUtils";
import { Icons } from "@/components/Icon";
import { QualityDisplayAction } from "./QualityDisplayAction"; import { QualityDisplayAction } from "./QualityDisplayAction";
import { PopoutListAction } from "../../popouts/PopoutUtils";
interface Props { interface Props {
onClick?: () => any; onClick?: () => any;

View File

@@ -1,9 +1,10 @@
import { useEffect } from "react";
import { MWCaption } from "@/backend/helpers/streams"; import { MWCaption } from "@/backend/helpers/streams";
import { MWSeasonWithEpisodeMeta } from "@/backend/metadata/types"; import { MWSeasonWithEpisodeMeta } from "@/backend/metadata/types";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { VideoPlayerMeta } from "@/video/state/types"; import { VideoPlayerMeta } from "@/video/state/types";
import { useEffect } from "react";
interface MetaControllerProps { interface MetaControllerProps {
data?: VideoPlayerMeta; data?: VideoPlayerMeta;

View File

@@ -1,10 +1,11 @@
import { useEffect, useMemo, useRef } from "react";
import throttle from "lodash.throttle"; import throttle from "lodash.throttle";
import { useEffect, useMemo, useRef } from "react";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useMediaPlaying } from "@/video/state/logic/mediaplaying";
import { useProgress } from "@/video/state/logic/progress";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useMediaPlaying } from "@/video/state/logic/mediaplaying";
import { useMisc } from "@/video/state/logic/misc"; import { useMisc } from "@/video/state/logic/misc";
import { useProgress } from "@/video/state/logic/progress";
interface Props { interface Props {
startAt?: number; startAt?: number;

View File

@@ -1,8 +1,9 @@
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useMeta } from "@/video/state/logic/meta";
import { useEffect, useRef } from "react"; import { useEffect, useRef } from "react";
import { useHistory } from "react-router-dom"; import { useHistory } from "react-router-dom";
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useMeta } from "@/video/state/logic/meta";
interface SeriesControllerProps { interface SeriesControllerProps {
onSelect?: (state: { episodeId?: string; seasonId?: string }) => void; onSelect?: (state: { episodeId?: string; seasonId?: string }) => void;
} }

View File

@@ -1,3 +1,5 @@
import { useEffect, useRef } from "react";
import { getCaptionUrl, makeCaptionId } from "@/backend/helpers/captions"; import { getCaptionUrl, makeCaptionId } from "@/backend/helpers/captions";
import { import {
MWCaption, MWCaption,
@@ -9,7 +11,6 @@ import { useSettings } from "@/state/settings";
import { useInitialized } from "@/video/components/hooks/useInitialized"; import { useInitialized } from "@/video/components/hooks/useInitialized";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useEffect, useRef } from "react";
interface SourceControllerProps { interface SourceControllerProps {
source: string; source: string;

View File

@@ -1,8 +1,9 @@
import { MWMediaType } from "@/backend/metadata/types";
import { useMeta } from "@/video/state/logic/meta";
import { useMemo } from "react"; import { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { MWMediaType } from "@/backend/metadata/types";
import { useMeta } from "@/video/state/logic/meta";
export function useCurrentSeriesEpisodeInfo(descriptor: string) { export function useCurrentSeriesEpisodeInfo(descriptor: string) {
const meta = useMeta(descriptor); const meta = useMeta(descriptor);
const { t } = useTranslation(); const { t } = useTranslation();

View File

@@ -1,6 +1,7 @@
import { useMisc } from "@/video/state/logic/misc";
import { useMemo } from "react"; import { useMemo } from "react";
import { useMisc } from "@/video/state/logic/misc";
export function useInitialized(descriptor: string): { initialized: boolean } { export function useInitialized(descriptor: string): { initialized: boolean } {
const misc = useMisc(descriptor); const misc = useMisc(descriptor);
const initialized = useMemo(() => !!misc.initalized, [misc]); const initialized = useMemo(() => !!misc.initalized, [misc]);

View File

@@ -1,8 +1,9 @@
import { ControlMethods, useControls } from "@/video/state/logic/controls";
import { useInterface } from "@/video/state/logic/interface";
import { useEffect, useRef } from "react"; import { useEffect, useRef } from "react";
import { useHistory, useLocation } from "react-router-dom"; import { useHistory, useLocation } from "react-router-dom";
import { ControlMethods, useControls } from "@/video/state/logic/controls";
import { useInterface } from "@/video/state/logic/interface";
function syncRouteToPopout( function syncRouteToPopout(
location: ReturnType<typeof useLocation>, location: ReturnType<typeof useLocation>,
controls: ControlMethods controls: ControlMethods

View File

@@ -1,10 +1,11 @@
import { useEffect, useMemo, useRef } from "react";
import { useChromecastAvailable } from "@/hooks/useChromecastAvailable"; import { useChromecastAvailable } from "@/hooks/useChromecastAvailable";
import { getPlayerState } from "@/video/state/cache"; import { getPlayerState } from "@/video/state/cache";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { updateMisc, useMisc } from "@/video/state/logic/misc"; import { updateMisc, useMisc } from "@/video/state/logic/misc";
import { createCastingStateProvider } from "@/video/state/providers/castingStateProvider"; import { createCastingStateProvider } from "@/video/state/providers/castingStateProvider";
import { setProvider, unsetStateProvider } from "@/video/state/providers/utils"; import { setProvider, unsetStateProvider } from "@/video/state/providers/utils";
import { useEffect, useMemo, useRef } from "react";
export function CastingInternal() { export function CastingInternal() {
const descriptor = useVideoPlayerDescriptor(); const descriptor = useVideoPlayerDescriptor();

View File

@@ -1,9 +1,10 @@
import { useEffect, useMemo, useRef } from "react";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useMediaPlaying } from "@/video/state/logic/mediaplaying"; import { useMediaPlaying } from "@/video/state/logic/mediaplaying";
import { useMisc } from "@/video/state/logic/misc"; import { useMisc } from "@/video/state/logic/misc";
import { setProvider, unsetStateProvider } from "@/video/state/providers/utils"; import { setProvider, unsetStateProvider } from "@/video/state/providers/utils";
import { createVideoStateProvider } from "@/video/state/providers/videoStateProvider"; import { createVideoStateProvider } from "@/video/state/providers/videoStateProvider";
import { useEffect, useMemo, useRef } from "react";
interface Props { interface Props {
autoPlay?: boolean; autoPlay?: boolean;

View File

@@ -1,7 +1,8 @@
import { useEffect } from "react";
import { getPlayerState } from "@/video/state/cache"; import { getPlayerState } from "@/video/state/cache";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { updateMisc } from "@/video/state/logic/misc"; import { updateMisc } from "@/video/state/logic/misc";
import { useEffect } from "react";
export function WrapperRegisterInternal(props: { export function WrapperRegisterInternal(props: {
wrapper: HTMLDivElement | null; wrapper: HTMLDivElement | null;

View File

@@ -1,10 +1,12 @@
import { Component } from "react";
import { Trans } from "react-i18next";
import type { ReactNode } from "react-router-dom/node_modules/@types/react/index";
import { MWMediaMeta } from "@/backend/metadata/types"; import { MWMediaMeta } from "@/backend/metadata/types";
import { ErrorMessage } from "@/components/layout/ErrorBoundary"; import { ErrorMessage } from "@/components/layout/ErrorBoundary";
import { Link } from "@/components/text/Link"; import { Link } from "@/components/text/Link";
import { conf } from "@/setup/config"; import { conf } from "@/setup/config";
import { Component } from "react";
import { Trans } from "react-i18next";
import type { ReactNode } from "react-router-dom/node_modules/@types/react/index";
import { VideoPlayerHeader } from "./VideoPlayerHeader"; import { VideoPlayerHeader } from "./VideoPlayerHeader";
interface ErrorBoundaryState { interface ErrorBoundaryState {

View File

@@ -1,10 +1,12 @@
import { ReactNode } from "react";
import { IconPatch } from "@/components/buttons/IconPatch"; import { IconPatch } from "@/components/buttons/IconPatch";
import { Icons } from "@/components/Icon"; import { Icons } from "@/components/Icon";
import { Title } from "@/components/text/Title"; import { Title } from "@/components/text/Title";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useError } from "@/video/state/logic/error"; import { useError } from "@/video/state/logic/error";
import { useMeta } from "@/video/state/logic/meta"; import { useMeta } from "@/video/state/logic/meta";
import { ReactNode } from "react";
import { VideoPlayerHeader } from "./VideoPlayerHeader"; import { VideoPlayerHeader } from "./VideoPlayerHeader";
interface VideoPlayerErrorProps { interface VideoPlayerErrorProps {

View File

@@ -1,16 +1,17 @@
import { useTranslation } from "react-i18next";
import { MWMediaMeta } from "@/backend/metadata/types"; import { MWMediaMeta } from "@/backend/metadata/types";
import { IconPatch } from "@/components/buttons/IconPatch"; import { IconPatch } from "@/components/buttons/IconPatch";
import { Icon, Icons } from "@/components/Icon"; import { Icon, Icons } from "@/components/Icon";
import { BrandPill } from "@/components/layout/BrandPill"; import { BrandPill } from "@/components/layout/BrandPill";
import { useBannerSize } from "@/hooks/useBanner";
import { useIsMobile } from "@/hooks/useIsMobile";
import { import {
getIfBookmarkedFromPortable, getIfBookmarkedFromPortable,
useBookmarkContext, useBookmarkContext,
} from "@/state/bookmark"; } from "@/state/bookmark";
import { AirplayAction } from "@/video/components/actions/AirplayAction"; import { AirplayAction } from "@/video/components/actions/AirplayAction";
import { ChromecastAction } from "@/video/components/actions/ChromecastAction"; import { ChromecastAction } from "@/video/components/actions/ChromecastAction";
import { useTranslation } from "react-i18next";
import { useIsMobile } from "@/hooks/useIsMobile";
import { useBannerSize } from "@/hooks/useBanner";
interface VideoPlayerHeaderProps { interface VideoPlayerHeaderProps {
media?: MWMediaMeta; media?: MWMediaMeta;

View File

@@ -1,6 +1,7 @@
import { Icon, Icons } from "@/components/Icon";
import React, { forwardRef } from "react"; import React, { forwardRef } from "react";
import { Icon, Icons } from "@/components/Icon";
export interface VideoPlayerIconButtonProps { export interface VideoPlayerIconButtonProps {
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void; onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
icon: Icons; icon: Icons;

View File

@@ -1,7 +1,8 @@
import { useEffect, useRef } from "react";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useInterface } from "@/video/state/logic/interface"; import { useInterface } from "@/video/state/logic/interface";
import { useEffect, useRef } from "react";
interface Props { interface Props {
children?: React.ReactNode; children?: React.ReactNode;

View File

@@ -1,3 +1,6 @@
import { useMemo, useRef } from "react";
import { useTranslation } from "react-i18next";
import { import {
customCaption, customCaption,
getCaptionUrl, getCaptionUrl,
@@ -15,8 +18,7 @@ import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls"; import { useControls } from "@/video/state/logic/controls";
import { useMeta } from "@/video/state/logic/meta"; import { useMeta } from "@/video/state/logic/meta";
import { useSource } from "@/video/state/logic/source"; import { useSource } from "@/video/state/logic/source";
import { useMemo, useRef } from "react";
import { useTranslation } from "react-i18next";
import { PopoutListEntry, PopoutSection } from "./PopoutUtils"; import { PopoutListEntry, PopoutSection } from "./PopoutUtils";
export function CaptionSelectionPopout(props: { export function CaptionSelectionPopout(props: {

View File

@@ -1,13 +1,13 @@
import { FloatingCardView } from "@/components/popout/FloatingCard";
import { FloatingView } from "@/components/popout/FloatingView";
import { useFloatingRouter } from "@/hooks/useFloatingRouter";
import { useSettings } from "@/state/settings";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Slider } from "@/components/Slider";
import CaptionColorSelector, { import CaptionColorSelector, {
colors, colors,
} from "@/components/CaptionColorSelector"; } from "@/components/CaptionColorSelector";
import { FloatingCardView } from "@/components/popout/FloatingCard";
import { FloatingView } from "@/components/popout/FloatingView";
import { Slider } from "@/components/Slider";
import { useFloatingRouter } from "@/hooks/useFloatingRouter";
import { useSettings } from "@/state/settings";
export function CaptionSettingsPopout(props: { export function CaptionSettingsPopout(props: {
router: ReturnType<typeof useFloatingRouter>; router: ReturnType<typeof useFloatingRouter>;

View File

@@ -1,20 +1,22 @@
import { useCallback, useMemo, useState } from "react"; import { useCallback, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { Icon, Icons } from "@/components/Icon";
import { useLoading } from "@/hooks/useLoading";
import { MWMediaType, MWSeasonWithEpisodeMeta } from "@/backend/metadata/types";
import { getMetaFromId } from "@/backend/metadata/getmeta"; import { getMetaFromId } from "@/backend/metadata/getmeta";
import { decodeJWId } from "@/backend/metadata/justwatch"; import { decodeJWId } from "@/backend/metadata/justwatch";
import { Loading } from "@/components/layout/Loading"; import { MWMediaType, MWSeasonWithEpisodeMeta } from "@/backend/metadata/types";
import { IconPatch } from "@/components/buttons/IconPatch"; import { IconPatch } from "@/components/buttons/IconPatch";
import { useVideoPlayerDescriptor } from "@/video/state/hooks"; import { Icon, Icons } from "@/components/Icon";
import { useMeta } from "@/video/state/logic/meta"; import { Loading } from "@/components/layout/Loading";
import { useControls } from "@/video/state/logic/controls"; import { FloatingCardView } from "@/components/popout/FloatingCard";
import { useWatchedContext } from "@/state/watched";
import { useTranslation } from "react-i18next";
import { FloatingView } from "@/components/popout/FloatingView"; import { FloatingView } from "@/components/popout/FloatingView";
import { useFloatingRouter } from "@/hooks/useFloatingRouter"; import { useFloatingRouter } from "@/hooks/useFloatingRouter";
import { FloatingCardView } from "@/components/popout/FloatingCard"; import { useLoading } from "@/hooks/useLoading";
import { useWatchedContext } from "@/state/watched";
import { useVideoPlayerDescriptor } from "@/video/state/hooks";
import { useControls } from "@/video/state/logic/controls";
import { useMeta } from "@/video/state/logic/meta";
import { PopoutListEntry } from "./PopoutUtils"; import { PopoutListEntry } from "./PopoutUtils";
export function EpisodeSelectionPopout() { export function EpisodeSelectionPopout() {

Some files were not shown because too many files have changed in this diff Show More