Format code

This commit is contained in:
Zoe Roux 2023-09-16 16:07:30 +02:00
parent 01486dfbec
commit 3a9941f69f
No known key found for this signature in database
41 changed files with 164 additions and 126 deletions

View File

@ -9,6 +9,6 @@ indent_style = tab
indent_size = tab
smart_tab = true
[{*.yaml,*.yml}]
[{*.yaml,*.yml,*.nix}]
indent_style = space
indent_size = 2

View File

@ -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
View File

@ -0,0 +1 @@
.yarn

View File

@ -68,9 +68,7 @@ const config = {
projectId: "55de6b52-c649-4a15-9a45-569ff5ed036c",
},
},
plugins: [
"expo-build-properties"
],
plugins: ["expo-build-properties"],
},
};
export default config;

View File

@ -62,10 +62,7 @@ module.exports = addMonorepoSupport(
...defaultConfig,
resolver: {
...defaultConfig.resolver,
requireCycleIgnorePatterns: [
...defaultConfig.resolver.requireCycleIgnorePatterns,
/.*/,
],
requireCycleIgnorePatterns: [...defaultConfig.resolver.requireCycleIgnorePatterns, /.*/],
},
}),
);

View File

@ -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],
};

View File

@ -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>

View File

@ -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();

View File

@ -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"

View File

@ -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;
};

View File

@ -20,6 +20,6 @@
import { createContext } from "react";
export const useAccounts = () => {}
export const useAccounts = () => {};
export const AccountContext = createContext({});

View File

@ -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";

View File

@ -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.

View File

@ -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;
}
};

View File

@ -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(),

View File

@ -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;

View File

@ -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,

View File

@ -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({

View File

@ -33,7 +33,7 @@ export const HR = ({
{...css(
[
{
opacity: .7,
opacity: 0.7,
bg: (theme) => theme.overlay0,
borderWidth: 0,
},

View File

@ -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 = {

View File

@ -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),

View File

@ -39,9 +39,9 @@ export const A = ({
experimental={
replace
? {
nativeBehavior: "stack-replace",
isNestedNavigator: false,
}
nativeBehavior: "stack-replace",
isNestedNavigator: false,
}
: undefined
}
textProps={css(

View File

@ -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)}

View File

@ -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 && (

View File

@ -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 (

View File

@ -20,4 +20,3 @@
export * from "./theme";
export * from "./catppuccin";

View File

@ -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;
};

View File

@ -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>}

View File

@ -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) })} />

View File

@ -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",
},
});

View File

@ -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>
);
};

View File

@ -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(

View File

@ -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"]);

View File

@ -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 (

View File

@ -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);
};

View File

@ -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;

View File

@ -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);

View File

@ -72,8 +72,8 @@ declare module "libass-wasm" {
debug?: boolean;
/**
* The default font.
*/
* The default font.
*/
fallbackFont?: string;
/**

View File

@ -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;
}

View File

@ -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();

View File

@ -25,6 +25,8 @@ in
mediainfo
ffmpeg
postgresql_15
eslint_d
prettierd
];
RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";