diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
new file mode 100644
index 00000000..d63811e7
--- /dev/null
+++ b/.github/workflows/lint.yaml
@@ -0,0 +1,28 @@
+name: Lint
+
+on:
+ pull_request:
+ branches: [ develop, master ]
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: '20.x'
+
+ - name: Setup Bun
+ uses: oven-sh/setup-bun@v1
+ with:
+ bun-version: latest
+
+ - name: Install dependencies
+ run: bun install
+
+ - name: Run linting checks
+ run: bun run check
diff --git a/README.md b/README.md
index cd578d84..30f63546 100644
--- a/README.md
+++ b/README.md
@@ -86,6 +86,7 @@ We welcome any help to make Streamyfin better. If you'd like to contribute, plea
1. Use node `>20`
2. Install dependencies `bun i && bun run submodule-reload`
3. Make sure you have xcode and/or android studio installed. (follow the guides for expo: https://docs.expo.dev/workflow/android-studio-emulator/)
+4. Install BiomeJS extension in VSCode/Your IDE (https://biomejs.dev/)
4. run `npm run prebuild`
5. Create an expo dev build by running `npm run ios` or `npm run android`. This will open a simulator on your computer and run the app.
diff --git a/app/(auth)/(tabs)/(custom-links)/index.tsx b/app/(auth)/(tabs)/(custom-links)/index.tsx
index 251b12e6..d6b34fb2 100644
--- a/app/(auth)/(tabs)/(custom-links)/index.tsx
+++ b/app/(auth)/(tabs)/(custom-links)/index.tsx
@@ -26,11 +26,11 @@ export default function menuLinks() {
const getMenuLinks = useCallback(async () => {
try {
const response = await api?.axiosInstance.get(
- api?.basePath + "/web/config.json",
+ `${api?.basePath}/web/config.json`,
);
const config = response?.data;
- if (!config && !config.hasOwnProperty("menuLinks")) {
+ if (!config && !Object.hasOwn(config, "menuLinks")) {
console.error("Menu links not found");
return;
}
diff --git a/app/(auth)/(tabs)/(favorites)/_layout.tsx b/app/(auth)/(tabs)/(favorites)/_layout.tsx
index ba0844d8..82df4a12 100644
--- a/app/(auth)/(tabs)/(favorites)/_layout.tsx
+++ b/app/(auth)/(tabs)/(favorites)/_layout.tsx
@@ -17,7 +17,7 @@ export default function SearchLayout() {
backgroundColor: "black",
},
headerBlurEffect: "prominent",
- headerTransparent: Platform.OS === "ios" ? true : false,
+ headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
}}
/>
diff --git a/app/(auth)/(tabs)/(home)/_layout.tsx b/app/(auth)/(tabs)/(home)/_layout.tsx
index 0d533ac9..86ae2cbe 100644
--- a/app/(auth)/(tabs)/(home)/_layout.tsx
+++ b/app/(auth)/(tabs)/(home)/_layout.tsx
@@ -32,7 +32,7 @@ export default function IndexLayout() {
{!Platform.isTV && (
<>
- {user && user.Policy?.IsAdministrator && }
+ {user?.Policy?.IsAdministrator && }
>
)}
diff --git a/app/(auth)/(tabs)/(home)/downloads/[seriesId].tsx b/app/(auth)/(tabs)/(home)/downloads/[seriesId].tsx
index 59d111f4..9e617d67 100644
--- a/app/(auth)/(tabs)/(home)/downloads/[seriesId].tsx
+++ b/app/(auth)/(tabs)/(home)/downloads/[seriesId].tsx
@@ -29,7 +29,7 @@ export default function page() {
try {
return (
downloadedFiles
- ?.filter((f) => f.item.SeriesId == seriesId)
+ ?.filter((f) => f.item.SeriesId === seriesId)
?.sort(
(a, b) => a?.item.ParentIndexNumber! - b.item.ParentIndexNumber!,
) || []
diff --git a/app/(auth)/(tabs)/(home)/sessions/index.tsx b/app/(auth)/(tabs)/(home)/sessions/index.tsx
index 590d89db..6c589f40 100644
--- a/app/(auth)/(tabs)/(home)/sessions/index.tsx
+++ b/app/(auth)/(tabs)/(home)/sessions/index.tsx
@@ -36,7 +36,7 @@ export default function page() {
);
- if (!sessions || sessions.length == 0)
+ if (!sessions || sessions.length === 0)
return (
@@ -175,7 +175,7 @@ const SessionCard = ({ session }: SessionCardProps) => {
{
const videoStream = useMemo(() => {
return session.NowPlayingItem?.MediaStreams?.filter(
- (s) => s.Type == "Video",
+ (s) => s.Type === "Video",
)[0];
}, [session]);
@@ -318,7 +318,7 @@ const TranscodingView = ({ session }: SessionCardProps) => {
const isTranscoding = useMemo(() => {
return (
- session.PlayState?.PlayMethod == "Transcode" && session.TranscodingInfo
+ session.PlayState?.PlayMethod === "Transcode" && session.TranscodingInfo
);
}, [session.PlayState?.PlayMethod, session.TranscodingInfo]);
@@ -341,9 +341,7 @@ const TranscodingView = ({ session }: SessionCardProps) => {
codec: session.TranscodingInfo?.VideoCodec,
}}
isTranscoding={
- isTranscoding && !session.TranscodingInfo?.IsVideoDirect
- ? true
- : false
+ !!(isTranscoding && !session.TranscodingInfo?.IsVideoDirect)
}
/>
@@ -360,24 +358,20 @@ const TranscodingView = ({ session }: SessionCardProps) => {
audioChannels: session.TranscodingInfo?.AudioChannels?.toString(),
}}
isTranscoding={
- isTranscoding && !session.TranscodingInfo?.IsVideoDirect
- ? true
- : false
+ !!(isTranscoding && !session.TranscodingInfo?.IsVideoDirect)
}
/>
{subtitleStream && (
- <>
-
- >
+
)}
);
diff --git a/app/(auth)/(tabs)/(home)/settings/logs/page.tsx b/app/(auth)/(tabs)/(home)/settings/logs/page.tsx
index 1e90983e..df09611b 100644
--- a/app/(auth)/(tabs)/(home)/settings/logs/page.tsx
+++ b/app/(auth)/(tabs)/(home)/settings/logs/page.tsx
@@ -1,73 +1,77 @@
+import { Loader } from "@/components/Loader";
import { Text } from "@/components/common/Text";
-import {LogLevel, useLog, writeErrorLog} from "@/utils/log";
+import { FilterButton } from "@/components/filters/FilterButton";
+import { LogLevel, useLog, writeErrorLog } from "@/utils/log";
+import * as FileSystem from "expo-file-system";
+import { useNavigation } from "expo-router";
+import * as Sharing from "expo-sharing";
+import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
-import {ScrollView, TouchableOpacity, View} from "react-native";
+import { ScrollView, TouchableOpacity, View } from "react-native";
import Collapsible from "react-native-collapsible";
-import React, {useCallback, useEffect, useMemo, useState} from "react";
-import {FilterButton} from "@/components/filters/FilterButton";
-import {useNavigation} from "expo-router";
-import * as FileSystem from 'expo-file-system';
-import * as Sharing from 'expo-sharing';
-import {Loader} from "@/components/Loader";
export default function page() {
const navigation = useNavigation();
const { logs } = useLog();
const { t } = useTranslation();
- const defaultLevels: LogLevel[] = ["INFO", "ERROR", "DEBUG", "WARN"]
+ const defaultLevels: LogLevel[] = ["INFO", "ERROR", "DEBUG", "WARN"];
const codeBlockStyle = {
- backgroundColor: '#000',
+ backgroundColor: "#000",
padding: 10,
- fontFamily: 'monospace',
- maxHeight: 300
- }
+ fontFamily: "monospace",
+ maxHeight: 300,
+ };
- const [loading, setLoading] = useState(false)
- const [state, setState] = useState>({})
+ const [loading, setLoading] = useState(false);
+ const [state, setState] = useState>({});
const [order, setOrder] = useState<"asc" | "desc">("desc");
const [levels, setLevels] = useState(defaultLevels);
const filteredLogs = useMemo(
- () => logs
- ?.filter(log => levels.includes(log.level))
- // Already in asc order as they are recorded. just reverse for desc
- ?.[order === "desc" ? "reverse" : "concat"]?.(),
- [logs, order, levels]
- )
+ () =>
+ logs
+ ?.filter((log) => levels.includes(log.level))
+ ?.[
+ // Already in asc order as they are recorded. just reverse for desc
+ order === "desc" ? "reverse" : "concat"
+ ]?.(),
+ [logs, order, levels],
+ );
// Sharing it as txt while its formatted allows us to share it with many more applications
const share = useCallback(async () => {
- const uri = FileSystem.documentDirectory + "logs.txt"
+ const uri = `${FileSystem.documentDirectory}logs.txt`;
- setLoading(true)
+ setLoading(true);
FileSystem.writeAsStringAsync(uri, JSON.stringify(filteredLogs))
.then(() => {
- setLoading(false)
- Sharing.shareAsync(uri, {mimeType: "txt", UTI: "txt"})
+ setLoading(false);
+ Sharing.shareAsync(uri, { mimeType: "txt", UTI: "txt" });
})
- .catch((e) => writeErrorLog("Something went wrong attempting to export", e))
- .finally(() => setLoading(false))
- }, [filteredLogs])
+ .catch((e) =>
+ writeErrorLog("Something went wrong attempting to export", e),
+ )
+ .finally(() => setLoading(false));
+ }, [filteredLogs]);
useEffect(() => {
navigation.setOptions({
- headerRight: () => (
- loading
- ?
- : (
+ headerRight: () =>
+ loading ? (
+
+ ) : (
{t("home.settings.logs.export_logs")}
- )
- ),
+ ),
});
}, [share, loading]);
return (
<>
-
+
{filteredLogs?.map((log, index) => (
-
+
setState((v) => ({...v, [log.timestamp]: !v[log.timestamp]}))}
+ onPress={() =>
+ setState((v) => ({
+ ...v,
+ [log.timestamp]: !v[log.timestamp],
+ }))
+ }
>
-
+
+ `}
+ >
{log.level}
- {new Date(log.timestamp).toLocaleString()}
+
+ {new Date(log.timestamp).toLocaleString()}
+
{log.message}
@@ -121,14 +130,14 @@ export default function page() {
{log.data && (
<>
{!state[log.timestamp] && (
- {t("home.settings.logs.click_for_more_info")}
+
+ {t("home.settings.logs.click_for_more_info")}
+
)}
-
-
-
- {JSON.stringify(log.data, null, 2)}
-
+
+
+ {JSON.stringify(log.data, null, 2)}
diff --git a/app/(auth)/(tabs)/(home)/settings/marlin-search/page.tsx b/app/(auth)/(tabs)/(home)/settings/marlin-search/page.tsx
index c13390da..f061afbb 100644
--- a/app/(auth)/(tabs)/(home)/settings/marlin-search/page.tsx
+++ b/app/(auth)/(tabs)/(home)/settings/marlin-search/page.tsx
@@ -93,7 +93,7 @@ export default function page() {
showText={!pluginSettings?.searchEngine?.locked}
className='mt-2 flex flex-col rounded-xl overflow-hidden pl-4 bg-neutral-900 px-4'
>
-
+
{t("home.settings.plugins.marlin_search.url")}
diff --git a/app/(auth)/(tabs)/(home)/settings/optimized-server/page.tsx b/app/(auth)/(tabs)/(home)/settings/optimized-server/page.tsx
index 1c53d7e2..9fbc0a23 100644
--- a/app/(auth)/(tabs)/(home)/settings/optimized-server/page.tsx
+++ b/app/(auth)/(tabs)/(home)/settings/optimized-server/page.tsx
@@ -31,7 +31,7 @@ export default function page() {
return;
}
- const updatedUrl = newVal.endsWith("/") ? newVal : newVal + "/";
+ const updatedUrl = newVal.endsWith("/") ? newVal : `${newVal}/`;
updateSettings({
optimizedVersionsServerUrl: updatedUrl,
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/actors/[actorId].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/actors/[actorId].tsx
index 1486581d..1e898c33 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/actors/[actorId].tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/actors/[actorId].tsx
@@ -133,7 +133,7 @@ const page: React.FC = () => {
queryFn={fetchItems}
queryKey={["actor", "movies", actorId]}
/>
-
+
);
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/collections/[collectionId].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/collections/[collectionId].tsx
index f1b48cbf..6add1ede 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/collections/[collectionId].tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/collections/[collectionId].tsx
@@ -157,9 +157,8 @@ const page: React.FC = () => {
if (accumulatedItems < totalItems) {
return lastPage?.Items?.length * pages.length;
- } else {
- return undefined;
}
+ return undefined;
},
initialPageParam: 0,
enabled: !!api && !!user?.Id && !!collection,
@@ -412,7 +411,7 @@ const page: React.FC = () => {
width: 10,
height: 10,
}}
- >
+ />
)}
/>
);
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/items/page.tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/items/page.tsx
index 1f9d322b..b7c39f9f 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/items/page.tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/items/page.tsx
@@ -93,19 +93,19 @@ const Page: React.FC = () => {
height: item?.Type === "Episode" ? 300 : 450,
}}
className='bg-transparent rounded-lg mb-4 w-full'
- >
-
-
-
+ />
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
{item && }
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/company/[companyId].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/company/[companyId].tsx
index 1f4b139d..8e744ee0 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/company/[companyId].tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/company/[companyId].tsx
@@ -33,9 +33,11 @@ export default function page() {
};
return jellyseerrApi?.discover(
- (type == DiscoverSliderType.NETWORKS
- ? Endpoints.DISCOVER_TV_NETWORK
- : Endpoints.DISCOVER_MOVIES_STUDIO) + `/${companyId}`,
+ `${
+ type === DiscoverSliderType.NETWORKS
+ ? Endpoints.DISCOVER_TV_NETWORK
+ : Endpoints.DISCOVER_MOVIES_STUDIO
+ }/${companyId}`,
params,
);
},
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/genre/[genreId].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/genre/[genreId].tsx
index 0d94a9a5..368bc127 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/genre/[genreId].tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/genre/[genreId].tsx
@@ -36,7 +36,7 @@ export default function page() {
};
return jellyseerrApi?.discover(
- type == DiscoverSliderType.MOVIE_GENRES
+ type === DiscoverSliderType.MOVIE_GENRES
? Endpoints.DISCOVER_MOVIES
: Endpoints.DISCOVER_TV,
params,
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/page.tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/page.tsx
index 845a7676..6629ef55 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/page.tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/jellyseerr/page.tsx
@@ -240,7 +240,7 @@ const Page: React.FC = () => {
g.name) || []} />
{isLoading || isFetching ? (
-
+
) : canRequest ? (
+ />
{channels?.Items?.map((c, i) => (
{
{!Platform.isTV && (
- <>
- (
-
- )}
- DownloadedIconComponent={() => (
-
- )}
- />
- >
+ (
+
+ )}
+ DownloadedIconComponent={() => (
+
+ )}
+ />
)}
),
@@ -127,20 +125,18 @@ const page: React.FC = () => {
/>
}
logo={
- <>
- {logoUrl ? (
-
- ) : null}
- >
+ logoUrl ? (
+
+ ) : null
}
>
diff --git a/app/(auth)/(tabs)/(libraries)/[libraryId].tsx b/app/(auth)/(tabs)/(libraries)/[libraryId].tsx
index 096c0948..24340170 100644
--- a/app/(auth)/(tabs)/(libraries)/[libraryId].tsx
+++ b/app/(auth)/(tabs)/(libraries)/[libraryId].tsx
@@ -216,9 +216,8 @@ const Page = () => {
if (accumulatedItems < totalItems) {
return lastPage?.Items?.length * pages.length;
- } else {
- return undefined;
}
+ return undefined;
},
initialPageParam: 0,
enabled: !!api && !!user?.Id && !!library,
@@ -478,7 +477,7 @@ const Page = () => {
width: 10,
height: 10,
}}
- >
+ />
)}
/>
);
diff --git a/app/(auth)/(tabs)/(libraries)/_layout.tsx b/app/(auth)/(tabs)/(libraries)/_layout.tsx
index 36647450..66bdad1f 100644
--- a/app/(auth)/(tabs)/(libraries)/_layout.tsx
+++ b/app/(auth)/(tabs)/(libraries)/_layout.tsx
@@ -25,7 +25,7 @@ export default function IndexLayout() {
headerLargeStyle: {
backgroundColor: "black",
},
- headerTransparent: Platform.OS === "ios" ? true : false,
+ headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerRight: () =>
!pluginSettings?.libraryOptions?.locked &&
@@ -159,7 +159,7 @@ export default function IndexLayout() {
updateSettings({
libraryOptions: {
...settings.libraryOptions,
- showTitles: newValue === "on" ? true : false,
+ showTitles: newValue === "on",
},
});
}}
@@ -176,7 +176,7 @@ export default function IndexLayout() {
updateSettings({
libraryOptions: {
...settings.libraryOptions,
- showStats: newValue === "on" ? true : false,
+ showStats: newValue === "on",
},
});
}}
@@ -200,7 +200,7 @@ export default function IndexLayout() {
title: "",
headerShown: true,
headerBlurEffect: "prominent",
- headerTransparent: Platform.OS === "ios" ? true : false,
+ headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
}}
/>
@@ -213,7 +213,7 @@ export default function IndexLayout() {
title: "",
headerShown: true,
headerBlurEffect: "prominent",
- headerTransparent: Platform.OS === "ios" ? true : false,
+ headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
}}
/>
diff --git a/app/(auth)/(tabs)/(libraries)/index.tsx b/app/(auth)/(tabs)/(libraries)/index.tsx
index 880a93a5..3b39d527 100644
--- a/app/(auth)/(tabs)/(libraries)/index.tsx
+++ b/app/(auth)/(tabs)/(libraries)/index.tsx
@@ -100,7 +100,7 @@ export default function index() {
height: StyleSheet.hairlineWidth,
}}
className='bg-neutral-800 mx-2 my-4'
- >
+ />
) : (
)
diff --git a/app/(auth)/(tabs)/(search)/_layout.tsx b/app/(auth)/(tabs)/(search)/_layout.tsx
index 6156546b..806f192e 100644
--- a/app/(auth)/(tabs)/(search)/_layout.tsx
+++ b/app/(auth)/(tabs)/(search)/_layout.tsx
@@ -20,7 +20,7 @@ export default function SearchLayout() {
backgroundColor: "black",
},
headerBlurEffect: "prominent",
- headerTransparent: Platform.OS === "ios" ? true : false,
+ headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
}}
/>
@@ -33,7 +33,7 @@ export default function SearchLayout() {
title: "",
headerShown: true,
headerBlurEffect: "prominent",
- headerTransparent: Platform.OS === "ios" ? true : false,
+ headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
}}
/>
diff --git a/app/(auth)/(tabs)/(search)/index.tsx b/app/(auth)/(tabs)/(search)/index.tsx
index 8a5184a6..b6bccf87 100644
--- a/app/(auth)/(tabs)/(search)/index.tsx
+++ b/app/(auth)/(tabs)/(search)/index.tsx
@@ -13,8 +13,7 @@ import SeriesPoster from "@/components/posters/SeriesPoster";
import { LoadingSkeleton } from "@/components/search/LoadingSkeleton";
import { SearchItemWrapper } from "@/components/search/SearchItemWrapper";
import { useJellyseerr } from "@/hooks/useJellyseerr";
-import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
-import { sortOrderOptions } from "@/utils/atoms/filters";
+import { apiAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings";
import { eventBus } from "@/utils/eventBus";
import type {
@@ -64,7 +63,6 @@ export default function search() {
const [debouncedSearch] = useDebounce(search, 500);
const [api] = useAtom(apiAtom);
- const [user] = useAtom(userAtom);
const [settings] = useSettings();
const { jellyseerrApi } = useJellyseerr();
@@ -83,7 +81,9 @@ export default function search() {
}, [settings]);
useEffect(() => {
- if (q && q.length > 0) setSearch(q);
+ if (q && q.length > 0) {
+ setSearch(q);
+ }
}, [q]);
const searchFn = useCallback(
@@ -94,7 +94,9 @@ export default function search() {
types: BaseItemKind[];
query: string;
}): Promise => {
- if (!api || !query) return [];
+ if (!api || !query) {
+ return [];
+ }
try {
if (searchEngine === "Jellyfin") {
@@ -105,28 +107,31 @@ export default function search() {
});
return (searchApi.data.SearchHints as BaseItemDto[]) || [];
- } else {
- if (!settings?.marlinServerUrl) return [];
-
- const url = `${
- settings.marlinServerUrl
- }/search?q=${encodeURIComponent(query)}&includeItemTypes=${types
- .map((type) => encodeURIComponent(type))
- .join("&includeItemTypes=")}`;
-
- const response1 = await axios.get(url);
-
- const ids = response1.data.ids;
-
- if (!ids || !ids.length) return [];
-
- const response2 = await getItemsApi(api).getItems({
- ids,
- enableImageTypes: ["Primary", "Backdrop", "Thumb"],
- });
-
- return (response2.data.Items as BaseItemDto[]) || [];
}
+ if (!settings?.marlinServerUrl) {
+ return [];
+ }
+
+ const url = `${
+ settings.marlinServerUrl
+ }/search?q=${encodeURIComponent(query)}&includeItemTypes=${types
+ .map((type) => encodeURIComponent(type))
+ .join("&includeItemTypes=")}`;
+
+ const response1 = await axios.get(url);
+
+ const ids = response1.data.ids;
+
+ if (!ids || !ids.length) {
+ return [];
+ }
+
+ const response2 = await getItemsApi(api).getItems({
+ ids,
+ enableImageTypes: ["Primary", "Backdrop", "Thumb"],
+ });
+
+ return (response2.data.Items as BaseItemDto[]) || [];
} catch (error) {
console.error("Error during search:", error);
return []; // Ensure an empty array is returned in case of an error
@@ -162,8 +167,10 @@ export default function search() {
useEffect(() => {
const unsubscribe = eventBus.on("searchTabPressed", () => {
- // Screen not actuve
- if (!searchBarRef.current) return;
+ // Screen not active
+ if (!searchBarRef.current) {
+ return;
+ }
// Screen is active, focus search bar
searchBarRef.current?.focus();
});
@@ -254,64 +261,62 @@ export default function search() {
}}
>
{jellyseerrApi && (
- <>
-
- setSearchType("Library")}>
-
-
- setSearchType("Discover")}>
-
-
- {searchType === "Discover" &&
- !loading &&
- noResults &&
- debouncedSearch.length > 0 && (
-
-
- Object.keys(JellyseerrSearchSort).filter((v) =>
- isNaN(Number(v)),
- )
- }
- set={(value) => setJellyseerrOrderBy(value[0])}
- values={[jellyseerrOrderBy]}
- title={t("library.filters.sort_by")}
- renderItemLabel={(item) =>
- t(`home.settings.plugins.jellyseerr.order_by.${item}`)
- }
- showSearch={false}
- />
- ["asc", "desc"]}
- set={(value) => setJellyseerrSortOrder(value[0])}
- values={[jellyseerrSortOrder]}
- title={t("library.filters.sort_order")}
- renderItemLabel={(item) => t(`library.filters.${item}`)}
- showSearch={false}
- />
-
- )}
-
- >
+
+ setSearchType("Library")}>
+
+
+ setSearchType("Discover")}>
+
+
+ {searchType === "Discover" &&
+ !loading &&
+ noResults &&
+ debouncedSearch.length > 0 && (
+
+
+ Object.keys(JellyseerrSearchSort).filter((v) =>
+ Number.isNaN(Number(v)),
+ )
+ }
+ set={(value) => setJellyseerrOrderBy(value[0])}
+ values={[jellyseerrOrderBy]}
+ title={t("library.filters.sort_by")}
+ renderItemLabel={(item) =>
+ t(`home.settings.plugins.jellyseerr.order_by.${item}`)
+ }
+ showSearch={false}
+ />
+ ["asc", "desc"]}
+ set={(value) => setJellyseerrSortOrder(value[0])}
+ values={[jellyseerrSortOrder]}
+ title={t("library.filters.sort_order")}
+ renderItemLabel={(item) => t(`library.filters.${item}`)}
+ showSearch={false}
+ />
+
+ )}
+
)}
@@ -411,32 +416,29 @@ export default function search() {
/>
)}
- {searchType === "Library" && (
- <>
- {!loading && noResults && debouncedSearch.length > 0 ? (
-
-
- {t("search.no_results_found_for")}
-
-
- "{debouncedSearch}"
-
-
- ) : debouncedSearch.length === 0 ? (
-
- {exampleSearches.map((e) => (
- setSearch(e)}
- key={e}
- className='mb-2'
- >
- {e}
-
- ))}
-
- ) : null}
- >
- )}
+ {searchType === "Library" &&
+ (!loading && noResults && debouncedSearch.length > 0 ? (
+
+
+ {t("search.no_results_found_for")}
+
+
+ "{debouncedSearch}"
+
+
+ ) : debouncedSearch.length === 0 ? (
+
+ {exampleSearches.map((e) => (
+ setSearch(e)}
+ key={e}
+ className='mb-2'
+ >
+ {e}
+
+ ))}
+
+ ) : null)}
>
diff --git a/app/(auth)/(tabs)/_layout.tsx b/app/(auth)/(tabs)/_layout.tsx
index f26309b7..d8fd30b6 100644
--- a/app/(auth)/(tabs)/_layout.tsx
+++ b/app/(auth)/(tabs)/_layout.tsx
@@ -72,7 +72,7 @@ export default function TabLayout() {
options={{
title: t("tabs.home"),
tabBarIcon:
- Platform.OS == "android"
+ Platform.OS === "android"
? ({ color, focused, size }) =>
require("@/assets/icons/house.fill.png")
: ({ focused }) =>
@@ -91,7 +91,7 @@ export default function TabLayout() {
options={{
title: t("tabs.search"),
tabBarIcon:
- Platform.OS == "android"
+ Platform.OS === "android"
? ({ color, focused, size }) =>
require("@/assets/icons/magnifyingglass.png")
: ({ focused }) =>
@@ -105,7 +105,7 @@ export default function TabLayout() {
options={{
title: t("tabs.favorites"),
tabBarIcon:
- Platform.OS == "android"
+ Platform.OS === "android"
? ({ color, focused, size }) =>
focused
? require("@/assets/icons/heart.fill.png")
@@ -121,7 +121,7 @@ export default function TabLayout() {
options={{
title: t("tabs.library"),
tabBarIcon:
- Platform.OS == "android"
+ Platform.OS === "android"
? ({ color, focused, size }) =>
require("@/assets/icons/server.rack.png")
: ({ focused }) =>
@@ -135,9 +135,9 @@ export default function TabLayout() {
options={{
title: t("tabs.custom_links"),
// @ts-expect-error
- tabBarItemHidden: settings?.showCustomMenuLinks ? false : true,
+ tabBarItemHidden: !settings?.showCustomMenuLinks,
tabBarIcon:
- Platform.OS == "android"
+ Platform.OS === "android"
? ({ focused }) => require("@/assets/icons/list.png")
: ({ focused }) =>
focused
diff --git a/app/_layout.tsx b/app/_layout.tsx
index 55185c45..2d5c14fa 100644
--- a/app/_layout.tsx
+++ b/app/_layout.tsx
@@ -16,7 +16,12 @@ import {
BACKGROUND_FETCH_TASK_SESSIONS,
registerBackgroundFetchAsyncSessions,
} from "@/utils/background-tasks";
-import {LogProvider, writeDebugLog, writeErrorLog, writeToLog} from "@/utils/log";
+import {
+ LogProvider,
+ writeDebugLog,
+ writeErrorLog,
+ writeToLog,
+} from "@/utils/log";
import { storage } from "@/utils/mmkv";
import { cancelJobById, getAllJobsByDeviceId } from "@/utils/optimize-server";
import { ActionSheetProvider } from "@expo/react-native-action-sheet";
@@ -31,8 +36,8 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const BackgroundFetch = !Platform.isTV
? require("expo-background-fetch")
: null;
-import * as FileSystem from "expo-file-system";
import * as Device from "expo-device";
+import * as FileSystem from "expo-file-system";
const Notifications = !Platform.isTV ? require("expo-notifications") : null;
import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { Stack, router, useSegments } from "expo-router";
@@ -161,7 +166,7 @@ if (!Platform.isTV) {
for (const job of jobs) {
if (job.status === "completed") {
- const downloadUrl = url + "download/" + job.id;
+ const downloadUrl = `${url}download/${job.id}`;
const tasks = await BackGroundDownloader.checkForExistingDownloads();
if (tasks.find((task: { id: string }) => task.id === job.id)) {
@@ -194,7 +199,7 @@ if (!Platform.isTV) {
title: job.item.Name,
body: "Download completed",
data: {
- url: `/downloads`,
+ url: "/downloads",
},
},
trigger: null,
@@ -208,7 +213,7 @@ if (!Platform.isTV) {
title: job.item.Name,
body: "Download failed",
data: {
- url: `/downloads`,
+ url: "/downloads",
},
},
trigger: null,
@@ -333,7 +338,7 @@ function Layout() {
}
// only create push token for real devices (pointless for emulators)
- if(Device.isDevice) {
+ if (Device.isDevice) {
Notifications?.getExpoPushTokenAsync()
.then((token: ExpoPushToken) => token && setExpoPushToken(token))
.catch((reason: any) => console.log("Failed to get token", reason));
@@ -357,9 +362,12 @@ function Layout() {
Notifications?.addNotificationResponseReceivedListener(
(response: NotificationResponse) => {
// Currently the notifications supported by the plugin will send data for deep links.
- const {title, data} = response.notification.request.content;
+ const { title, data } = response.notification.request.content;
- writeDebugLog(`Notification ${title} opened`, response.notification.request.content)
+ writeDebugLog(
+ `Notification ${title} opened`,
+ response.notification.request.content,
+ );
if (data && Object.keys(data).length > 0) {
const type = data?.type?.toLower?.();
@@ -367,12 +375,12 @@ function Layout() {
switch (type) {
case "movie":
- router.push(`/(auth)/(tabs)/home/items/page?id=${itemId}`)
+ router.push(`/(auth)/(tabs)/home/items/page?id=${itemId}`);
break;
case "episode":
// We just clicked a notification for an individual episode.
if (itemId) {
- router.push(`/(auth)/(tabs)/home/items/page?id=${itemId}`)
+ router.push(`/(auth)/(tabs)/home/items/page?id=${itemId}`);
}
// summarized season notification for multiple episodes. Bring them to series season
else {
@@ -380,10 +388,11 @@ function Layout() {
const seasonIndex = data.seasonIndex;
if (seasonIndex) {
- router.push(`/(auth)/(tabs)/home/series/${seriesId}?seasonIndex=${seasonIndex}`)
- }
- else {
- router.push(`/(auth)/(tabs)/home/series/${seriesId}`)
+ router.push(
+ `/(auth)/(tabs)/home/series/${seriesId}?seasonIndex=${seasonIndex}`,
+ );
+ } else {
+ router.push(`/(auth)/(tabs)/home/series/${seriesId}`);
}
}
break;
diff --git a/app/login.tsx b/app/login.tsx
index 34a3ca82..e59d1d35 100644
--- a/app/login.tsx
+++ b/app/login.tsx
@@ -218,16 +218,14 @@ const Login: React.FC = () => {
- <>
- {serverName ? (
- <>
- {t("login.login_to_title") + " "}
- {serverName}
- >
- ) : (
- t("login.login_title")
- )}
- >
+ {serverName ? (
+ <>
+ {`${t("login.login_to_title")} `}
+ {serverName}
+ >
+ ) : (
+ t("login.login_title")
+ )}
{api.basePath}
@@ -284,7 +282,7 @@ const Login: React.FC = () => {
-
+
>
) : (
diff --git a/augmentations/number.ts b/augmentations/number.ts
index a60f8811..11c0837d 100644
--- a/augmentations/number.ts
+++ b/augmentations/number.ts
@@ -17,9 +17,7 @@ Number.prototype.bytesToReadable = function (decimals = 2) {
const i = Math.floor(Math.log(bytes) / Math.log(k));
- return (
- Number.parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i]
- );
+ return `${Number.parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`;
};
Number.prototype.secondsToMilliseconds = function () {
diff --git a/biome.json b/biome.json
index bf2ae1c8..f9fd721d 100644
--- a/biome.json
+++ b/biome.json
@@ -9,7 +9,8 @@
"ios",
"android",
"Streamyfin.app",
- "utils/jellyseerr"
+ "utils/jellyseerr",
+ ".expo"
]
},
"linter": {
@@ -17,12 +18,18 @@
"rules": {
"style": {
"useImportType": "off",
- "noNonNullAssertion": "off"
+ "noNonNullAssertion": "off",
+ "noParameterAssign": "off",
+ "useLiteralEnumMembers": "off"
+ },
+ "complexity": {
+ "noForEach": "off"
},
"recommended": true,
"correctness": { "useExhaustiveDependencies": "off" },
"suspicious": {
- "noExplicitAny": "off"
+ "noExplicitAny": "off",
+ "noArrayIndexKey": "off"
}
}
},
diff --git a/components/Button.tsx b/components/Button.tsx
index cbaa3e17..aeb319bc 100644
--- a/components/Button.tsx
+++ b/components/Button.tsx
@@ -73,7 +73,7 @@ export const Button: React.FC> = ({
flex flex-row items-center justify-between w-full
${justify === "between" ? "justify-between" : "justify-center"}`}
>
- {iconLeft ? iconLeft : }
+ {iconLeft ? iconLeft : }
> = ({
>
{children}
- {iconRight ? iconRight : }
+ {iconRight ? iconRight : }
)}
diff --git a/components/ContinueWatchingPoster.tsx b/components/ContinueWatchingPoster.tsx
index 02218cff..c15495ce 100644
--- a/components/ContinueWatchingPoster.tsx
+++ b/components/ContinueWatchingPoster.tsx
@@ -27,33 +27,39 @@ const ContinueWatchingPoster: React.FC = ({
* Get horizontal poster for movie and episode, with failover to primary.
*/
const url = useMemo(() => {
- if (!api) return;
+ if (!api) {
+ return;
+ }
if (item.Type === "Episode" && useEpisodePoster) {
return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
}
if (item.Type === "Episode") {
- if (item.ParentBackdropItemId && item.ParentThumbImageTag)
+ if (item.ParentBackdropItemId && item.ParentThumbImageTag) {
return `${api?.basePath}/Items/${item.ParentBackdropItemId}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ParentThumbImageTag}`;
- else
- return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
+ }
+
+ return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
}
if (item.Type === "Movie") {
- if (item.ImageTags?.["Thumb"])
- return `${api?.basePath}/Items/${item.Id}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ImageTags?.["Thumb"]}`;
- else
- return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
+ if (item.ImageTags?.Thumb) {
+ return `${api?.basePath}/Items/${item.Id}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ImageTags?.Thumb}`;
+ }
+
+ return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
}
if (item.Type === "Program") {
- if (item.ImageTags?.["Thumb"])
- return `${api?.basePath}/Items/${item.Id}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ImageTags?.["Thumb"]}`;
- else
- return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
+ if (item.ImageTags?.Thumb) {
+ return `${api?.basePath}/Items/${item.Id}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ImageTags?.Thumb}`;
+ }
+
+ return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
}
- if (item.ImageTags?.["Thumb"])
- return `${api?.basePath}/Items/${item.Id}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ImageTags?.["Thumb"]}`;
- else
- return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
+ if (item.ImageTags?.Thumb) {
+ return `${api?.basePath}/Items/${item.Id}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ImageTags?.Thumb}`;
+ }
+
+ return `${api?.basePath}/Items/${item.Id}/Images/Primary?fillHeight=389&quality=80`;
}, [item]);
const progress = useMemo(() => {
@@ -64,15 +70,12 @@ const ContinueWatchingPoster: React.FC = ({
const total = endDate.getTime() - startDate.getTime();
const elapsed = now.getTime() - startDate.getTime();
return (elapsed / total) * 100;
- } else {
- return item.UserData?.PlayedPercentage || 0;
}
+ return item.UserData?.PlayedPercentage || 0;
}, [item]);
if (!url)
- return (
-
- );
+ return ;
return (
= ({
{progress > 0 && (
<>
+ className={
+ "absolute w-100 bottom-0 left-0 h-1 bg-neutral-700 opacity-80 w-full"
+ }
+ />
+ className={"absolute bottom-0 left-0 h-1 bg-purple-600 w-full"}
+ />
>
)}
diff --git a/components/ItemContent.tsx b/components/ItemContent.tsx
index f27e0f41..43e8ec45 100644
--- a/components/ItemContent.tsx
+++ b/components/ItemContent.tsx
@@ -147,22 +147,20 @@ export const ItemContent: React.FC<{ item: BaseItemDto }> = React.memo(
}
logo={
- <>
- {logoUrl ? (
- setLoadingLogo(false)}
- onError={() => setLoadingLogo(false)}
- />
- ) : null}
- >
+ logoUrl ? (
+ setLoadingLogo(false)}
+ onError={() => setLoadingLogo(false)}
+ />
+ ) : null
}
>
diff --git a/components/ItemTechnicalDetails.tsx b/components/ItemTechnicalDetails.tsx
index b0354fa0..5222e6f8 100644
--- a/components/ItemTechnicalDetails.tsx
+++ b/components/ItemTechnicalDetails.tsx
@@ -237,5 +237,5 @@ const formatFileSize = (bytes?: number | null) => {
const i = Number.parseInt(
Math.floor(Math.log(bytes) / Math.log(1024)).toString(),
);
- return Math.round((bytes / Math.pow(1024, i)) * 100) / 100 + " " + sizes[i];
+ return `${Math.round((bytes / 1024 ** i) * 100) / 100} ${sizes[i]}`;
};
diff --git a/components/MoreMoviesWithActor.tsx b/components/MoreMoviesWithActor.tsx
index bb9edf5e..3f88d69e 100644
--- a/components/MoreMoviesWithActor.tsx
+++ b/components/MoreMoviesWithActor.tsx
@@ -63,9 +63,8 @@ export const MoreMoviesWithActor: React.FC = ({
const x = acc.find((item) => item.Id === current.Id);
if (!x) {
return acc.concat([current]);
- } else {
- return acc;
}
+ return acc;
}, [] as BaseItemDto[]) || [];
return uniqueItems;
diff --git a/components/PlayButton.tsx b/components/PlayButton.tsx
index a4cf50ef..8bbbe046 100644
--- a/components/PlayButton.tsx
+++ b/components/PlayButton.tsx
@@ -239,7 +239,7 @@ export const PlayButton: React.FC = ({
const derivedTargetWidth = useDerivedValue(() => {
if (!item || !item.RunTimeTicks) return 0;
const userData = item.UserData;
- if (userData && userData.PlaybackPositionTicks) {
+ if (userData?.PlaybackPositionTicks) {
return userData.PlaybackPositionTicks > 0
? Math.max(
(userData.PlaybackPositionTicks / item.RunTimeTicks) * 100,
@@ -331,7 +331,7 @@ export const PlayButton: React.FC = ({
accessibilityLabel='Play button'
accessibilityHint='Tap to play the media'
onPress={onPress}
- className={`relative`}
+ className={"relative"}
{...props}
>
diff --git a/components/PlayButton.tv.tsx b/components/PlayButton.tv.tsx
index a68058c5..2c7a2e35 100644
--- a/components/PlayButton.tv.tsx
+++ b/components/PlayButton.tv.tsx
@@ -85,7 +85,7 @@ export const PlayButton: React.FC = ({
const derivedTargetWidth = useDerivedValue(() => {
if (!item || !item.RunTimeTicks) return 0;
const userData = item.UserData;
- if (userData && userData.PlaybackPositionTicks) {
+ if (userData?.PlaybackPositionTicks) {
return userData.PlaybackPositionTicks > 0
? Math.max(
(userData.PlaybackPositionTicks / item.RunTimeTicks) * 100,
@@ -176,7 +176,7 @@ export const PlayButton: React.FC = ({
accessibilityLabel='Play button'
accessibilityHint='Tap to play the media'
onPress={onPress}
- className={`relative`}
+ className={"relative"}
{...props}
>
diff --git a/components/WatchedIndicator.tsx b/components/WatchedIndicator.tsx
index 662dcb7e..c815eaf9 100644
--- a/components/WatchedIndicator.tsx
+++ b/components/WatchedIndicator.tsx
@@ -7,7 +7,7 @@ export const WatchedIndicator: React.FC<{ item: BaseItemDto }> = ({ item }) => {
<>
{item.UserData?.Played === false &&
(item.Type === "Movie" || item.Type === "Episode") && (
-
+
)}
>
);
diff --git a/components/__tests__/ThemedText-test.tsx b/components/__tests__/ThemedText-test.tsx
index 591f09e2..89037a1e 100644
--- a/components/__tests__/ThemedText-test.tsx
+++ b/components/__tests__/ThemedText-test.tsx
@@ -3,7 +3,7 @@ import renderer from "react-test-renderer";
import { ThemedText } from "../ThemedText";
-it(`renders correctly`, () => {
+it("renders correctly", () => {
const tree = renderer
.create(Snapshot test!)
.toJSON();
diff --git a/components/_template.tsx b/components/_template.tsx
index 2e3dab21..c3933960 100644
--- a/components/_template.tsx
+++ b/components/_template.tsx
@@ -6,7 +6,7 @@ interface Props extends ViewProps {}
export const TitleHeader: React.FC = ({ ...props }) => {
return (
-
+
);
};
diff --git a/components/common/Dropdown.tsx b/components/common/Dropdown.tsx
index 4578da12..586fc65f 100644
--- a/components/common/Dropdown.tsx
+++ b/components/common/Dropdown.tsx
@@ -75,7 +75,7 @@ const Dropdown = ({
multiple ? (
keyExtractor(s) == keyExtractor(item))
+ selected?.some((s) => keyExtractor(s) === keyExtractor(item))
? "on"
: "off"
}
@@ -83,7 +83,7 @@ const Dropdown = ({
onValueChange={(next: "on" | "off", previous: "on" | "off") => {
setSelected((p) => {
const prev = p || [];
- if (next == "on") {
+ if (next === "on") {
return [...prev, item];
}
return [
diff --git a/components/common/HorrizontalScroll.tsx b/components/common/HorrizontalScroll.tsx
index 2ba30f94..4e6e94ca 100644
--- a/components/common/HorrizontalScroll.tsx
+++ b/components/common/HorrizontalScroll.tsx
@@ -65,17 +65,13 @@ export const HorizontalScroll = forwardRef<
}: {
item: T;
index: number;
- }) => (
-
- {renderItem(item, index)}
-
- );
+ }) => {renderItem(item, index)};
if (!data || loading) {
return (
-
-
+
+
);
}
diff --git a/components/common/InfiniteHorrizontalScroll.tsx b/components/common/InfiniteHorrizontalScroll.tsx
index cf522a87..8682e964 100644
--- a/components/common/InfiniteHorrizontalScroll.tsx
+++ b/components/common/InfiniteHorrizontalScroll.tsx
@@ -75,9 +75,8 @@ export function InfiniteHorizontalScroll({
if (accumulatedItems < totalItems) {
return lastPage?.Items?.length * pages.length;
- } else {
- return undefined;
}
+ return undefined;
},
initialPageParam: 0,
enabled: !!api && !!user?.Id,
@@ -118,9 +117,7 @@ export function InfiniteHorizontalScroll({
(
-
- {renderItem(item, index)}
-
+ {renderItem(item, index)}
)}
estimatedItemSize={height}
horizontal
diff --git a/components/common/ItemImage.tsx b/components/common/ItemImage.tsx
index 412d6b74..5268cca6 100644
--- a/components/common/ItemImage.tsx
+++ b/components/common/ItemImage.tsx
@@ -36,7 +36,7 @@ export const ItemImage: FC = ({
const source = useMemo(() => {
if (!api) {
- onError && onError();
+ onError?.();
return;
}
return getItemImage({
diff --git a/components/common/LargePoster.tsx b/components/common/LargePoster.tsx
index a42241d7..ab3b16fb 100644
--- a/components/common/LargePoster.tsx
+++ b/components/common/LargePoster.tsx
@@ -5,7 +5,7 @@ export const LargePoster: React.FC<{ url?: string | null }> = ({ url }) => {
if (!url)
return (
-
+
);
diff --git a/components/common/Text.tsx b/components/common/Text.tsx
index fa82a4dc..aac7dcf2 100644
--- a/components/common/Text.tsx
+++ b/components/common/Text.tsx
@@ -16,12 +16,12 @@ export function Text(
{...otherProps}
/>
);
- else
- return (
-
- );
+
+ return (
+
+ );
}
diff --git a/components/common/VerticalSkeleton.tsx b/components/common/VerticalSkeleton.tsx
index 45a87749..a4abcdd6 100644
--- a/components/common/VerticalSkeleton.tsx
+++ b/components/common/VerticalSkeleton.tsx
@@ -20,10 +20,10 @@ export const VerticalSkeleton: React.FC = ({ index, ...props }) => {
aspectRatio: "10/15",
}}
className='w-full bg-neutral-800 mb-2 rounded-lg'
- >
-
-
-
+ />
+
+
+
);
};
diff --git a/components/downloads/ActiveDownloads.tsx b/components/downloads/ActiveDownloads.tsx
index 7ab86a90..2cc0eecf 100644
--- a/components/downloads/ActiveDownloads.tsx
+++ b/components/downloads/ActiveDownloads.tsx
@@ -80,8 +80,6 @@ const DownloadCard = ({ process, ...props }: DownloadCardProps) => {
task.stop();
}
}
- } catch (e) {
- throw e;
} finally {
await removeProcess(id);
await queryClient.refetchQueries({ queryKey: ["jobs"] });
@@ -131,7 +129,7 @@ const DownloadCard = ({ process, ...props }: DownloadCardProps) => {
? `${Math.max(5, process.progress)}%`
: "5%",
}}
- >
+ />
)}
diff --git a/components/downloads/SeriesCard.tsx b/components/downloads/SeriesCard.tsx
index 877a5240..948807e7 100644
--- a/components/downloads/SeriesCard.tsx
+++ b/components/downloads/SeriesCard.tsx
@@ -31,7 +31,7 @@ export const SeriesCard: React.FC<{ items: BaseItemDto[] }> = ({ items }) => {
destructiveButtonIndex,
},
(selectedIndex) => {
- if (selectedIndex == destructiveButtonIndex) {
+ if (selectedIndex === destructiveButtonIndex) {
deleteSeries();
}
},
diff --git a/components/filters/FilterButton.tsx b/components/filters/FilterButton.tsx
index 1a1d7466..9715c17e 100644
--- a/components/filters/FilterButton.tsx
+++ b/components/filters/FilterButton.tsx
@@ -15,7 +15,7 @@ interface FilterButtonProps extends ViewProps {
queryFn: (params: any) => Promise;
searchFilter?: (item: T, query: string) => boolean;
renderItemLabel: (item: T) => React.ReactNode;
- multiple?: boolean,
+ multiple?: boolean;
icon?: "filter" | "sort";
}
diff --git a/components/filters/FilterSheet.tsx b/components/filters/FilterSheet.tsx
index ec69721b..8a8817a6 100644
--- a/components/filters/FilterSheet.tsx
+++ b/components/filters/FilterSheet.tsx
@@ -183,15 +183,13 @@ export const FilterSheet = ({
{
if (multiple) {
- if (!values.includes(item))
- set(values.concat(item))
- else set(values.filter(v => v !== item))
+ if (!values.includes(item)) set(values.concat(item));
+ else set(values.filter((v) => v !== item));
setTimeout(() => {
setOpen(false);
}, 250);
- }
- else {
+ } else {
if (!values.includes(item)) {
set([item]);
setTimeout(() => {
@@ -214,7 +212,7 @@ export const FilterSheet = ({
height: StyleSheet.hairlineWidth,
}}
className='h-1 divide-neutral-700 '
- >
+ />
))}
diff --git a/components/home/ScrollingCollectionList.tsx b/components/home/ScrollingCollectionList.tsx
index 31ff108b..a77085de 100644
--- a/components/home/ScrollingCollectionList.tsx
+++ b/components/home/ScrollingCollectionList.tsx
@@ -63,7 +63,7 @@ export const ScrollingCollectionList: React.FC = ({
>
{[1, 2, 3].map((i) => (
-
+
= ({
-
{value}
{appendValue}
diff --git a/components/jellyseerr/JellyseerrIndexPage.tsx b/components/jellyseerr/JellyseerrIndexPage.tsx
index e2467b31..2a1509b2 100644
--- a/components/jellyseerr/JellyseerrIndexPage.tsx
+++ b/components/jellyseerr/JellyseerrIndexPage.tsx
@@ -52,7 +52,7 @@ export const JellyserrIndexPage: React.FC = ({
} = useReactNavigationQuery({
queryKey: ["search", "jellyseerr", "discoverSettings", searchQuery],
queryFn: async () => jellyseerrApi?.discoverSettings(),
- enabled: !!jellyseerrApi && searchQuery.length == 0,
+ enabled: !!jellyseerrApi && searchQuery.length === 0,
});
const {
@@ -110,7 +110,7 @@ export const JellyserrIndexPage: React.FC = ({
(r) => r.mediaType === MediaType.MOVIE,
) as MovieResult[],
sortingType || [
- (m) => m.title.toLowerCase() == searchQuery.toLowerCase(),
+ (m) => m.title.toLowerCase() === searchQuery.toLowerCase(),
],
order || "desc",
),
@@ -124,7 +124,7 @@ export const JellyserrIndexPage: React.FC = ({
(r) => r.mediaType === MediaType.TV,
) as TvResult[],
sortingType || [
- (t) => t.name.toLowerCase() == searchQuery.toLowerCase(),
+ (t) => t.name.toLowerCase() === searchQuery.toLowerCase(),
],
order || "desc",
),
@@ -138,7 +138,7 @@ export const JellyserrIndexPage: React.FC = ({
(r) => r.mediaType === "person",
) as PersonResult[],
sortingType || [
- (p) => p.name.toLowerCase() == searchQuery.toLowerCase(),
+ (p) => p.name.toLowerCase() === searchQuery.toLowerCase(),
],
order || "desc",
),
diff --git a/components/jellyseerr/JellyseerrStatusIcon.tsx b/components/jellyseerr/JellyseerrStatusIcon.tsx
index 26452a91..6bed842e 100644
--- a/components/jellyseerr/JellyseerrStatusIcon.tsx
+++ b/components/jellyseerr/JellyseerrStatusIcon.tsx
@@ -62,7 +62,7 @@ const JellyseerrStatusIcon: React.FC = ({
return (
badgeIcon && (
-
+
({
>
-
- {HeaderContent && HeaderContent()}
-
+ {HeaderContent?.()}
- {MainContent && MainContent()}
+ {MainContent?.()}
- jellyseerrApi?.service(type == "movie" ? "radarr" : "sonarr"),
+ jellyseerrApi?.service(type === "movie" ? "radarr" : "sonarr"),
enabled: !!jellyseerrApi && !!jellyseerrUser,
refetchOnMount: "always",
});
diff --git a/components/jellyseerr/discover/GenreSlide.tsx b/components/jellyseerr/discover/GenreSlide.tsx
index 06b10a5a..2cac3813 100644
--- a/components/jellyseerr/discover/GenreSlide.tsx
+++ b/components/jellyseerr/discover/GenreSlide.tsx
@@ -28,7 +28,7 @@ const GenreSlide: React.FC = ({ slide, ...props }) => {
queryKey: ["jellyseerr", "discover", slide.type, slide.id],
queryFn: async () => {
return jellyseerrApi?.getGenreSliders(
- slide.type == DiscoverSliderType.MOVIE_GENRES
+ slide.type === DiscoverSliderType.MOVIE_GENRES
? Endpoints.MOVIE
: Endpoints.TV,
);
diff --git a/components/jellyseerr/discover/RecentRequestsSlide.tsx b/components/jellyseerr/discover/RecentRequestsSlide.tsx
index 7f88e40e..c4598661 100644
--- a/components/jellyseerr/discover/RecentRequestsSlide.tsx
+++ b/components/jellyseerr/discover/RecentRequestsSlide.tsx
@@ -23,7 +23,7 @@ const RequestCard: React.FC<{ request: MediaRequest }> = ({ request }) => {
request.media.tmdbId,
],
queryFn: async () => {
- return request.media.mediaType == MediaType.MOVIE
+ return request.media.mediaType === MediaType.MOVIE
? jellyseerrApi?.movieDetails(request.media.tmdbId)
: jellyseerrApi?.tvDetails(request.media.tmdbId);
},
diff --git a/components/jellyseerr/discover/Slide.tsx b/components/jellyseerr/discover/Slide.tsx
index 9e2298dc..74f78f13 100644
--- a/components/jellyseerr/discover/Slide.tsx
+++ b/components/jellyseerr/discover/Slide.tsx
@@ -35,7 +35,7 @@ const Slide = ({
return (
- {t("search." + DiscoverSliderType[slide.type].toString().toLowerCase())}
+ {t(`search.${DiscoverSliderType[slide.type].toString().toLowerCase()}`)}
= ({
);
const blurhash = useMemo(() => {
- const key = item.ImageTags?.["Primary"] as string;
- return item.ImageBlurHashes?.["Primary"]?.[key];
+ const key = item.ImageTags?.Primary as string;
+ return item.ImageBlurHashes?.Primary?.[key];
}, [item]);
return (
@@ -57,7 +57,7 @@ export const EpisodePoster: React.FC = ({
/>
{showProgress && progress > 0 && (
-
+
)}
);
diff --git a/components/posters/ItemPoster.tsx b/components/posters/ItemPoster.tsx
index b8605f97..95beb4d4 100644
--- a/components/posters/ItemPoster.tsx
+++ b/components/posters/ItemPoster.tsx
@@ -37,7 +37,7 @@ export const ItemPoster: React.FC = ({
/>
{showProgress && progress > 0 && (
-
+
)}
);
diff --git a/components/posters/JellyseerrPoster.tsx b/components/posters/JellyseerrPoster.tsx
index b25f8974..63f1fd7a 100644
--- a/components/posters/JellyseerrPoster.tsx
+++ b/components/posters/JellyseerrPoster.tsx
@@ -129,7 +129,7 @@ const JellyseerrPoster: React.FC = ({
posterSrc={posterSrc!}
mediaType={mediaType}
>
-
+
diff --git a/components/posters/MoviePoster.tsx b/components/posters/MoviePoster.tsx
index 61fa3b03..f9fc3ec4 100644
--- a/components/posters/MoviePoster.tsx
+++ b/components/posters/MoviePoster.tsx
@@ -31,8 +31,8 @@ const MoviePoster: React.FC = ({
);
const blurhash = useMemo(() => {
- const key = item.ImageTags?.["Primary"] as string;
- return item.ImageBlurHashes?.["Primary"]?.[key];
+ const key = item.ImageTags?.Primary as string;
+ return item.ImageBlurHashes?.Primary?.[key];
}, [item]);
return (
@@ -59,7 +59,7 @@ const MoviePoster: React.FC = ({
/>
{showProgress && progress > 0 && (
-
+
)}
);
diff --git a/components/posters/ParentPoster.tsx b/components/posters/ParentPoster.tsx
index 65cc4493..6c4b4da8 100644
--- a/components/posters/ParentPoster.tsx
+++ b/components/posters/ParentPoster.tsx
@@ -24,7 +24,7 @@ const ParentPoster: React.FC = ({ id }) => {
style={{
aspectRatio: "10/15",
}}
- >
+ />
);
return (
diff --git a/components/posters/Poster.tsx b/components/posters/Poster.tsx
index 77718ad0..d591cfdf 100644
--- a/components/posters/Poster.tsx
+++ b/components/posters/Poster.tsx
@@ -16,7 +16,7 @@ const Poster: React.FC = ({ id, url, blurhash }) => {
style={{
aspectRatio: "10/15",
}}
- >
+ />
);
return (
diff --git a/components/posters/SeriesPoster.tsx b/components/posters/SeriesPoster.tsx
index 893fae5a..2deba076 100644
--- a/components/posters/SeriesPoster.tsx
+++ b/components/posters/SeriesPoster.tsx
@@ -27,8 +27,8 @@ const SeriesPoster: React.FC = ({ item }) => {
}, [item]);
const blurhash = useMemo(() => {
- const key = item.ImageTags?.["Primary"] as string;
- return item.ImageBlurHashes?.["Primary"]?.[key];
+ const key = item.ImageTags?.Primary as string;
+ return item.ImageBlurHashes?.Primary?.[key];
}, [item]);
return (
diff --git a/components/search/LoadingSkeleton.tsx b/components/search/LoadingSkeleton.tsx
index 9df34938..d98a4829 100644
--- a/components/search/LoadingSkeleton.tsx
+++ b/components/search/LoadingSkeleton.tsx
@@ -35,11 +35,11 @@ export const LoadingSkeleton: React.FC = ({ isLoading }) => {
{[1, 2, 3].map((s) => (
-
+
{[1, 2, 3].map((i) => (
-
+
= ({
return (