mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-23 17:52:36 -04:00
Format code
This commit is contained in:
parent
01486dfbec
commit
3a9941f69f
@ -9,6 +9,6 @@ indent_style = tab
|
||||
indent_size = tab
|
||||
smart_tab = true
|
||||
|
||||
[{*.yaml,*.yml}]
|
||||
[{*.yaml,*.yml,*.nix}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
2
.github/workflows/coding-style.yml
vendored
2
.github/workflows/coding-style.yml
vendored
@ -40,7 +40,7 @@ jobs:
|
||||
run: yarn install --immutable
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint
|
||||
run: yarn lint && yarn format
|
||||
|
||||
scanner:
|
||||
name: "Lint scanner"
|
||||
|
1
front/.prettierignore
Normal file
1
front/.prettierignore
Normal file
@ -0,0 +1 @@
|
||||
.yarn
|
@ -68,9 +68,7 @@ const config = {
|
||||
projectId: "55de6b52-c649-4a15-9a45-569ff5ed036c",
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
"expo-build-properties"
|
||||
],
|
||||
plugins: ["expo-build-properties"],
|
||||
},
|
||||
};
|
||||
export default config;
|
||||
|
@ -62,10 +62,7 @@ module.exports = addMonorepoSupport(
|
||||
...defaultConfig,
|
||||
resolver: {
|
||||
...defaultConfig.resolver,
|
||||
requireCycleIgnorePatterns: [
|
||||
...defaultConfig.resolver.requireCycleIgnorePatterns,
|
||||
/.*/,
|
||||
],
|
||||
requireCycleIgnorePatterns: [...defaultConfig.resolver.requireCycleIgnorePatterns, /.*/],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
@ -48,7 +48,8 @@ const nextConfig = {
|
||||
alias: {
|
||||
...config.resolve.alias,
|
||||
"react-native$": "react-native-web",
|
||||
'react-native/Libraries/Image/AssetRegistry$': 'react-native-web/dist/modules/AssetRegistry',
|
||||
"react-native/Libraries/Image/AssetRegistry$":
|
||||
"react-native-web/dist/modules/AssetRegistry",
|
||||
},
|
||||
extensions: [".web.ts", ".web.tsx", ".web.js", ".web.jsx", ...config.resolve.extensions],
|
||||
};
|
||||
|
@ -23,7 +23,13 @@ import "../polyfill";
|
||||
import { Hydrate, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { HiddenIfNoJs, SkeletonCss, ThemeSelector } from "@kyoo/primitives";
|
||||
import { WebTooltip } from "@kyoo/primitives/src/tooltip.web";
|
||||
import { createQueryClient, fetchQuery, getTokenWJ, QueryIdentifier, QueryPage } from "@kyoo/models";
|
||||
import {
|
||||
createQueryClient,
|
||||
fetchQuery,
|
||||
getTokenWJ,
|
||||
QueryIdentifier,
|
||||
QueryPage,
|
||||
} from "@kyoo/models";
|
||||
import { setSecureItem } from "@kyoo/models/src/secure-store.web";
|
||||
import { useState } from "react";
|
||||
import NextApp, { AppContext, type AppProps } from "next/app";
|
||||
@ -73,7 +79,11 @@ const GlobalCssTheme = () => {
|
||||
|
||||
::cue {
|
||||
background-color: transparent;
|
||||
text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
|
||||
text-shadow:
|
||||
-1px -1px 0 #000,
|
||||
1px -1px 0 #000,
|
||||
-1px 1px 0 #000,
|
||||
1px 1px 0 #000;
|
||||
}
|
||||
`}</style>
|
||||
<WebTooltip theme={theme} />
|
||||
@ -100,8 +110,7 @@ const App = ({ Component, pageProps }: AppProps) => {
|
||||
useMobileHover();
|
||||
|
||||
// Set the auth from the server (if the token was refreshed during SSR).
|
||||
if (typeof window !== "undefined" && token)
|
||||
setSecureItem("auth", JSON.stringify(token));
|
||||
if (typeof window !== "undefined" && token) setSecureItem("auth", JSON.stringify(token));
|
||||
|
||||
return (
|
||||
<YoshikiDebug>
|
||||
|
@ -21,7 +21,10 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { ComponentType } from "react";
|
||||
|
||||
export const withRoute = <Props,>(Component: ComponentType<Props>, defaultProps?: Partial<Props>) => {
|
||||
export const withRoute = <Props,>(
|
||||
Component: ComponentType<Props>,
|
||||
defaultProps?: Partial<Props>,
|
||||
) => {
|
||||
const WithUseRoute = (props: Props) => {
|
||||
const router = useRouter();
|
||||
|
||||
|
@ -9,7 +9,9 @@
|
||||
"build:mobile": "yarn workspace mobile build",
|
||||
"build:mobile:dev": "yarn workspace mobile build:dev",
|
||||
"update": "yarn workspace mobile update",
|
||||
"lint": "eslint ."
|
||||
"lint": "eslint .",
|
||||
"format": "prettier -c .",
|
||||
"format:fix": "prettier -w ."
|
||||
},
|
||||
"eslintIgnore": [
|
||||
"next-env.d.ts"
|
||||
|
@ -27,7 +27,9 @@ import { Account, loginFunc } from "./login";
|
||||
export const AccountContext = createContext<ReturnType<typeof useAccounts>>({ type: "loading" });
|
||||
|
||||
export const useAccounts = () => {
|
||||
const [accounts, setAccounts] = useState<Account[]>(JSON.parse(getSecureItem("accounts") ?? "[]"));
|
||||
const [accounts, setAccounts] = useState<Account[]>(
|
||||
JSON.parse(getSecureItem("accounts") ?? "[]"),
|
||||
);
|
||||
const [verified, setVerified] = useState<{
|
||||
status: "ok" | "error" | "loading" | "unverified";
|
||||
error?: string;
|
||||
@ -48,7 +50,7 @@ export const useAccounts = () => {
|
||||
|
||||
useEffect(() => {
|
||||
async function check() {
|
||||
setVerified({status: "loading"});
|
||||
setVerified({ status: "loading" });
|
||||
const selAcc = accounts![selected!];
|
||||
setApiUrl(selAcc.apiUrl);
|
||||
const verif = await loginFunc("refresh", selAcc.refresh_token, undefined, 5_000);
|
||||
@ -57,8 +59,8 @@ export const useAccounts = () => {
|
||||
|
||||
if (accounts.length && selected !== null) check();
|
||||
else setVerified({ status: "unverified" });
|
||||
// Use the length of the array and not the array directly because we don't care if the refresh token changes.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// Use the length of the array and not the array directly because we don't care if the refresh token changes.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [accounts.length, selected, retryCount]);
|
||||
|
||||
useMMKVListener((key) => {
|
||||
@ -87,4 +89,3 @@ export const useAccounts = () => {
|
||||
setSelected,
|
||||
} as const;
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,6 @@
|
||||
|
||||
import { createContext } from "react";
|
||||
|
||||
export const useAccounts = () => {}
|
||||
export const useAccounts = () => {};
|
||||
|
||||
export const AccountContext = createContext({});
|
||||
|
@ -23,7 +23,7 @@ export * from "./resources";
|
||||
export * from "./traits";
|
||||
export * from "./page";
|
||||
export * from "./kyoo-errors";
|
||||
export * from "./utils"
|
||||
export * from "./login"
|
||||
export * from "./utils";
|
||||
export * from "./login";
|
||||
|
||||
export * from "./query";
|
||||
|
@ -85,7 +85,7 @@ export const EpisodeP = BaseEpisodeP.extend({
|
||||
nextEpisode: BaseEpisodeP.nullable().optional(),
|
||||
|
||||
show: ShowP.optional(),
|
||||
})
|
||||
});
|
||||
|
||||
/**
|
||||
* A class to represent a single show's episode.
|
||||
|
@ -18,19 +18,17 @@
|
||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { MMKV } from 'react-native-mmkv'
|
||||
import { MMKV } from "react-native-mmkv";
|
||||
|
||||
export const storage = new MMKV();
|
||||
|
||||
export const setSecureItem = (key: string, value: string | null) => {
|
||||
if (value === null)
|
||||
storage.delete(key);
|
||||
else
|
||||
storage.set(key, value);
|
||||
}
|
||||
if (value === null) storage.delete(key);
|
||||
else storage.set(key, value);
|
||||
};
|
||||
|
||||
export const deleteSecureItem = (key: string) => setSecureItem(key, null);
|
||||
|
||||
export const getSecureItem = (key: string, _cookies?: string): string | null => {
|
||||
return storage.getString(key) || null;
|
||||
}
|
||||
};
|
||||
|
@ -22,10 +22,7 @@ import { Platform } from "react-native";
|
||||
import { z } from "zod";
|
||||
import { kyooApiUrl } from "..";
|
||||
|
||||
export const imageFn = (url: string) =>
|
||||
Platform.OS === "web"
|
||||
? `/api${url}`
|
||||
: kyooApiUrl + url;
|
||||
export const imageFn = (url: string) => (Platform.OS === "web" ? `/api${url}` : kyooApiUrl + url);
|
||||
|
||||
export const Img = z.object({
|
||||
source: z.string(),
|
||||
|
@ -18,14 +18,9 @@
|
||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
// Stolen from https://github.com/necolas/react-native-web/issues/1026#issuecomment-1458279681
|
||||
|
||||
import {
|
||||
Alert as RNAlert,
|
||||
type AlertOptions,
|
||||
type AlertButton,
|
||||
} from "react-native";
|
||||
import { Alert as RNAlert, type AlertOptions, type AlertButton } from "react-native";
|
||||
import { type SweetAlertIcon } from "sweetalert2";
|
||||
|
||||
export interface ExtendedAlertStatic {
|
||||
@ -38,4 +33,3 @@ export interface ExtendedAlertStatic {
|
||||
}
|
||||
|
||||
export const Alert: ExtendedAlertStatic = RNAlert as ExtendedAlertStatic;
|
||||
|
||||
|
@ -33,10 +33,10 @@ export class Alert {
|
||||
const confirmButton = buttons
|
||||
? buttons.find((button) => button.style === "default")
|
||||
: undefined;
|
||||
const denyButton = buttons ? buttons.find((button) => button.style === "destructive") : undefined;
|
||||
const cancelButton = buttons
|
||||
? buttons.find((button) => button.style === "cancel")
|
||||
const denyButton = buttons
|
||||
? buttons.find((button) => button.style === "destructive")
|
||||
: undefined;
|
||||
const cancelButton = buttons ? buttons.find((button) => button.style === "cancel") : undefined;
|
||||
|
||||
Swal.fire({
|
||||
title: title,
|
||||
|
@ -99,12 +99,7 @@ export const Avatar = forwardRef<
|
||||
)}
|
||||
>
|
||||
{src || isLoading ? (
|
||||
<Image
|
||||
src={src}
|
||||
quality={quality}
|
||||
alt={alt}
|
||||
layout={{ width: size, height: size }}
|
||||
/>
|
||||
<Image src={src} quality={quality} alt={alt} layout={{ width: size, height: size }} />
|
||||
) : placeholder ? (
|
||||
<P
|
||||
{...css({
|
||||
|
@ -33,7 +33,7 @@ export const HR = ({
|
||||
{...css(
|
||||
[
|
||||
{
|
||||
opacity: .7,
|
||||
opacity: 0.7,
|
||||
bg: (theme) => theme.overlay0,
|
||||
borderWidth: 0,
|
||||
},
|
||||
|
@ -25,8 +25,8 @@ import { YoshikiStyle } from "yoshiki/src/type";
|
||||
|
||||
export type YoshikiEnhanced<Style> = Style extends any
|
||||
? {
|
||||
[key in keyof Style]: YoshikiStyle<Style[key]>;
|
||||
}
|
||||
[key in keyof Style]: YoshikiStyle<Style[key]>;
|
||||
}
|
||||
: never;
|
||||
|
||||
export type Props = {
|
||||
|
@ -45,7 +45,7 @@ export const Input = forwardRef<
|
||||
padding: ts(0.5),
|
||||
flexDirection: "row",
|
||||
alignContent: "center",
|
||||
alignItems: "center"
|
||||
alignItems: "center",
|
||||
},
|
||||
variant === "big" && {
|
||||
borderRadius: ts(4),
|
||||
|
@ -39,9 +39,9 @@ export const A = ({
|
||||
experimental={
|
||||
replace
|
||||
? {
|
||||
nativeBehavior: "stack-replace",
|
||||
isNestedNavigator: false,
|
||||
}
|
||||
nativeBehavior: "stack-replace",
|
||||
isNestedNavigator: false,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
textProps={css(
|
||||
|
@ -106,7 +106,7 @@ export const Skeleton = ({
|
||||
<MotiView
|
||||
key={`skeleton_${i}`}
|
||||
// No clue why it is a number on mobile and a string on web but /shrug
|
||||
animate={{ opacity: Platform.OS === "web" ? "1" as any : 1 }}
|
||||
animate={{ opacity: Platform.OS === "web" ? ("1" as any) : 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ type: "timing" }}
|
||||
onLayout={(e) => setWidth(e.nativeEvent.layout.width)}
|
||||
|
@ -119,7 +119,7 @@ export const Slider = ({
|
||||
height: ts(1),
|
||||
bg: (theme) => theme.overlay0,
|
||||
},
|
||||
smallBar && { transform: "scaleY(0.4)" as any},
|
||||
smallBar && { transform: "scaleY(0.4)" as any },
|
||||
])}
|
||||
>
|
||||
{subtleProgress !== undefined && (
|
||||
|
@ -37,7 +37,12 @@ const styleText = (
|
||||
type?: "header" | "sub",
|
||||
custom?: TextStyle,
|
||||
) => {
|
||||
const Text = (props: Omit<ComponentProps<typeof EP>, "style"> & { style?: StyleProp<TextStyle>, children?: TextProps["children"] }) => {
|
||||
const Text = (
|
||||
props: Omit<ComponentProps<typeof EP>, "style"> & {
|
||||
style?: StyleProp<TextStyle>;
|
||||
children?: TextProps["children"];
|
||||
},
|
||||
) => {
|
||||
const { css, theme } = useYoshiki();
|
||||
|
||||
return (
|
||||
|
@ -20,4 +20,3 @@
|
||||
|
||||
export * from "./theme";
|
||||
export * from "./catppuccin";
|
||||
|
||||
|
@ -18,6 +18,12 @@
|
||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export const Head = ({ title, description }: { title?: string | null; description?: string | null }) => {
|
||||
export const Head = ({
|
||||
title,
|
||||
description,
|
||||
}: {
|
||||
title?: string | null;
|
||||
description?: string | null;
|
||||
}) => {
|
||||
return null;
|
||||
};
|
||||
|
@ -20,7 +20,13 @@
|
||||
|
||||
import NextHead from "next/head";
|
||||
|
||||
export const Head = ({ title, description }: { title?: string | null; description?: string | null }) => {
|
||||
export const Head = ({
|
||||
title,
|
||||
description,
|
||||
}: {
|
||||
title?: string | null;
|
||||
description?: string | null;
|
||||
}) => {
|
||||
return (
|
||||
<NextHead>
|
||||
{title && <title>{title + " - Kyoo"}</title>}
|
||||
|
@ -79,7 +79,14 @@ export const BrowseSettings = ({
|
||||
// TODO: implement filters in the front.
|
||||
|
||||
return (
|
||||
<View {...css({ flexDirection: "row-reverse", alignItems: "center", marginX: ts(4), marginY: ts(1) })}>
|
||||
<View
|
||||
{...css({
|
||||
flexDirection: "row-reverse",
|
||||
alignItems: "center",
|
||||
marginX: ts(4),
|
||||
marginY: ts(1),
|
||||
})}
|
||||
>
|
||||
{filters.length !== 0 && (
|
||||
<View {...css({ flexGrow: 1, flexDirection: "row", alignItems: "center" })}>
|
||||
<Icon icon={Style} {...css({ marginX: ts(1) })} />
|
||||
|
@ -67,9 +67,7 @@ const query = (
|
||||
path: slug ? ["library", slug, "items"] : ["items"],
|
||||
infinite: true,
|
||||
params: {
|
||||
sortBy: sortKey
|
||||
? `${sortKey}:${sortOrd ?? "asc"}`
|
||||
: "name:asc",
|
||||
sortBy: sortKey ? `${sortKey}:${sortOrd ?? "asc"}` : "name:asc",
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -104,7 +104,13 @@ export const ItemList = ({
|
||||
</Skeleton>
|
||||
)}
|
||||
</View>
|
||||
<Poster src={poster} alt="" quality="low" forcedLoading={isLoading} layout={{ height: percent(80) }} />
|
||||
<Poster
|
||||
src={poster}
|
||||
alt=""
|
||||
quality="low"
|
||||
forcedLoading={isLoading}
|
||||
layout={{ height: percent(80) }}
|
||||
/>
|
||||
</ImageBackground>
|
||||
);
|
||||
};
|
||||
|
@ -20,7 +20,15 @@
|
||||
|
||||
import { Page, QueryIdentifier, useInfiniteFetch } from "@kyoo/models";
|
||||
import { HR } from "@kyoo/primitives";
|
||||
import { ComponentType, Fragment, isValidElement, ReactElement, useCallback, useEffect, useRef } from "react";
|
||||
import {
|
||||
ComponentType,
|
||||
Fragment,
|
||||
isValidElement,
|
||||
ReactElement,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
} from "react";
|
||||
import { Stylable, useYoshiki } from "yoshiki";
|
||||
import { EmptyView, ErrorView, Layout, WithLoading } from "./fetch";
|
||||
|
||||
@ -65,7 +73,6 @@ const InfiniteScroll = <Props,>({
|
||||
onScroll();
|
||||
}, [isFetching, onScroll]);
|
||||
|
||||
|
||||
const list = (props: object) => (
|
||||
<div
|
||||
{...css(
|
||||
|
@ -84,7 +84,12 @@ export const RegisterPage: QueryPage = () => {
|
||||
text={t("login.register")}
|
||||
disabled={password !== confirm}
|
||||
onPress={async () => {
|
||||
const { error } = await loginFunc("register", { email, username, password }, cleanApiUrl(apiUrl), 5_000);
|
||||
const { error } = await loginFunc(
|
||||
"register",
|
||||
{ email, username, password },
|
||||
cleanApiUrl(apiUrl),
|
||||
5_000,
|
||||
);
|
||||
setError(error);
|
||||
if (error) return;
|
||||
queryClient.invalidateQueries(["auth", "me"]);
|
||||
|
@ -103,7 +103,7 @@ export const Hover = ({
|
||||
props,
|
||||
)}
|
||||
>
|
||||
<VideoPoster poster={poster} alt={showName}/>
|
||||
<VideoPoster poster={poster} alt={showName} />
|
||||
<View
|
||||
{...css({
|
||||
marginLeft: { xs: ts(0.5), sm: ts(3) },
|
||||
@ -209,7 +209,7 @@ export const Back = ({
|
||||
);
|
||||
};
|
||||
|
||||
const VideoPoster = ({ poster, alt }: { poster?: KyooImage | null, alt?: string }) => {
|
||||
const VideoPoster = ({ poster, alt }: { poster?: KyooImage | null; alt?: string }) => {
|
||||
const { css } = useYoshiki();
|
||||
|
||||
return (
|
||||
|
@ -100,10 +100,10 @@ const VolumeSlider = () => {
|
||||
isMuted || volume == 0
|
||||
? VolumeOff
|
||||
: volume < 25
|
||||
? VolumeMute
|
||||
: volume < 65
|
||||
? VolumeDown
|
||||
: VolumeUp
|
||||
? VolumeMute
|
||||
: volume < 65
|
||||
? VolumeDown
|
||||
: VolumeUp
|
||||
}
|
||||
onPress={() => setMuted(!isMuted)}
|
||||
{...tooltip(t("player.mute"), true)}
|
||||
@ -133,7 +133,8 @@ const ProgressText = () => {
|
||||
|
||||
const toTimerString = (timer?: number, duration?: number) => {
|
||||
if (!duration) duration = timer;
|
||||
if (timer === undefined || duration === undefined || isNaN(duration) || isNaN(timer)) return "??:??";
|
||||
if (timer === undefined || duration === undefined || isNaN(duration) || isNaN(timer))
|
||||
return "??:??";
|
||||
if (duration >= 3600) return new Date(timer * 1000).toISOString().substring(11, 19);
|
||||
return new Date(timer * 1000).toISOString().substring(14, 19);
|
||||
};
|
||||
|
@ -173,12 +173,12 @@ declare module "react-native-video" {
|
||||
/* Wrapper component */
|
||||
// Opaque type returned by require('./video.mp4')
|
||||
source:
|
||||
| {
|
||||
uri?: string | undefined;
|
||||
headers?: { [key: string]: string } | undefined;
|
||||
type?: string | undefined;
|
||||
}
|
||||
| number;
|
||||
| {
|
||||
uri?: string | undefined;
|
||||
headers?: { [key: string]: string } | undefined;
|
||||
type?: string | undefined;
|
||||
}
|
||||
| number;
|
||||
minLoadRetryCount?: number | undefined;
|
||||
maxBitRate?: number | undefined;
|
||||
resizeMode?: "stretch" | "contain" | "cover" | "none" | undefined; // via Image#resizeMode
|
||||
@ -190,13 +190,13 @@ declare module "react-native-video" {
|
||||
muted?: boolean | undefined;
|
||||
volume?: number | undefined;
|
||||
bufferConfig?:
|
||||
| {
|
||||
minBufferMs?: number | undefined;
|
||||
maxBufferMs?: number | undefined;
|
||||
bufferForPlaybackMs?: number | undefined;
|
||||
bufferForPlaybackAfterRebufferMs?: number | undefined;
|
||||
}
|
||||
| undefined;
|
||||
| {
|
||||
minBufferMs?: number | undefined;
|
||||
maxBufferMs?: number | undefined;
|
||||
bufferForPlaybackMs?: number | undefined;
|
||||
bufferForPlaybackAfterRebufferMs?: number | undefined;
|
||||
}
|
||||
| undefined;
|
||||
stereoPan?: number | undefined;
|
||||
rate?: number | undefined;
|
||||
pictureInPicture?: boolean | undefined;
|
||||
@ -242,31 +242,31 @@ declare module "react-native-video" {
|
||||
onRestoreUserInterfaceForPictureInPictureStop?(): void;
|
||||
onExternalPlaybackChange?(data: OnExternalPlaybackChangeData): void;
|
||||
selectedAudioTrack?:
|
||||
| {
|
||||
type: "system" | "disabled" | "title" | "language" | "index";
|
||||
value?: string | number | undefined;
|
||||
}
|
||||
| undefined;
|
||||
| {
|
||||
type: "system" | "disabled" | "title" | "language" | "index";
|
||||
value?: string | number | undefined;
|
||||
}
|
||||
| undefined;
|
||||
selectedTextTrack?:
|
||||
| {
|
||||
type: "system" | "disabled" | "title" | "language" | "index";
|
||||
value?: string | number | undefined;
|
||||
}
|
||||
| undefined;
|
||||
| {
|
||||
type: "system" | "disabled" | "title" | "language" | "index";
|
||||
value?: string | number | undefined;
|
||||
}
|
||||
| undefined;
|
||||
selectedVideoTrack?:
|
||||
| {
|
||||
type: "auto" | "disabled" | "resolution" | "index";
|
||||
value?: string | number | undefined;
|
||||
}
|
||||
| undefined;
|
||||
| {
|
||||
type: "auto" | "disabled" | "resolution" | "index";
|
||||
value?: string | number | undefined;
|
||||
}
|
||||
| undefined;
|
||||
textTracks?:
|
||||
| Array<{
|
||||
title?: string | undefined;
|
||||
language?: string | undefined;
|
||||
type: "application/x-subrip" | "application/ttml+xml" | "text/vtt";
|
||||
uri: string;
|
||||
}>
|
||||
| undefined;
|
||||
| Array<{
|
||||
title?: string | undefined;
|
||||
language?: string | undefined;
|
||||
type: "application/x-subrip" | "application/ttml+xml" | "text/vtt";
|
||||
uri: string;
|
||||
}>
|
||||
| undefined;
|
||||
|
||||
/* Required by react-native */
|
||||
scaleX?: number | undefined;
|
||||
|
@ -113,9 +113,9 @@ export const Video = memo(function Video({
|
||||
const [subtitle, setSubtitle] = useAtom(subtitleAtom);
|
||||
useEffect(() => {
|
||||
if (!subtitle || !subtitles) return;
|
||||
setSubtitle(subtitles.find(x => x.language === subtitle.language) ?? null);
|
||||
// When the video change, try to persist the subtitle language.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
setSubtitle(subtitles.find((x) => x.language === subtitle.language) ?? null);
|
||||
// When the video change, try to persist the subtitle language.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [subtitles]);
|
||||
|
||||
const volume = useAtomValue(volumeAtom);
|
||||
|
@ -72,8 +72,8 @@ declare module "libass-wasm" {
|
||||
debug?: boolean;
|
||||
|
||||
/**
|
||||
* The default font.
|
||||
*/
|
||||
* The default font.
|
||||
*/
|
||||
fallbackFont?: string;
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,7 @@ import "./react-native-video.d.ts";
|
||||
declare module "react-native-video" {
|
||||
interface VideoProperties {
|
||||
fonts?: string[];
|
||||
subtitles?: Subtitle[]
|
||||
subtitles?: Subtitle[];
|
||||
onPlayPause: (isPlaying: boolean) => void;
|
||||
onMediaUnsupported?: () => void;
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ const initHls = async (): Promise<Hls> => {
|
||||
retryDelayMs: 0,
|
||||
maxRetryDelayMs: 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
hls = new Hls({
|
||||
xhrSetup: (xhr) => {
|
||||
@ -125,7 +125,7 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function
|
||||
useEffect(() => {
|
||||
if (!ref.current || paused === ref.current.paused) return;
|
||||
if (paused) ref.current?.pause();
|
||||
else ref.current?.play().catch(() => { });
|
||||
else ref.current?.play().catch(() => {});
|
||||
}, [paused]);
|
||||
useEffect(() => {
|
||||
if (!ref.current || !volume) return;
|
||||
@ -157,7 +157,7 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function
|
||||
hls.on(Hls.Events.MANIFEST_LOADED, async () => {
|
||||
try {
|
||||
await ref.current?.play();
|
||||
} catch { }
|
||||
} catch {}
|
||||
});
|
||||
hls.on(Hls.Events.ERROR, (_, d) => {
|
||||
if (!d.fatal || !hls?.media) return;
|
||||
@ -292,8 +292,8 @@ const toWebVtt = async (srtUrl: string) => {
|
||||
const query = await fetch(srtUrl, {
|
||||
headers: token
|
||||
? {
|
||||
Authorization: token,
|
||||
}
|
||||
Authorization: token,
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
const srt = await query.blob();
|
||||
|
Loading…
x
Reference in New Issue
Block a user