From f211a9ce7a00f8c4c24b22014fa5475ddaa3e7a7 Mon Sep 17 00:00:00 2001
From: Uruk
Date: Mon, 12 Jan 2026 09:26:19 +0100
Subject: [PATCH] refactor: rename Jellyseerr to Seerr throughout codebase
Updates branding and naming conventions to use "Seerr" instead of "Jellyseerr" across all files, components, hooks, and translations.
Renames files, functions, classes, variables, and UI text to reflect the new naming convention while maintaining identical functionality. Updates asset references including logo and screenshot images.
Changes API class name, storage keys, atom names, and all related utilities to use "Seerr" prefix. Modifies translation keys and user-facing text to match the rebrand.
---
.github/copilot-instructions.md | 2 +-
README.md | 2 +-
app/(auth)/(tabs)/(home)/_layout.tsx | 4 +-
.../plugins/{jellyseerr => seerr}/page.tsx | 8 +-
.../company/[companyId].tsx | 29 ++-
.../{jellyseerr => seerr}/genre/[genreId].tsx | 32 ++--
.../{jellyseerr => seerr}/page.tsx | 87 ++++-----
.../person/[personId].tsx | 39 ++--
app/(auth)/(tabs)/(search)/_layout.tsx | 8 +-
app/(auth)/(tabs)/(search)/index.tsx | 43 ++---
.../{jellyseerr-logo.svg => seerr-logo.svg} | 0
assets/images/{jellyseerr.PNG => seerr.PNG} | Bin
components/IntroSheet.tsx | 6 +-
components/Ratings.tsx | 14 +-
...eerrItemRouter.tsx => SeerrItemRouter.tsx} | 4 +-
components/music/MusicAlbumCard.tsx | 5 +-
components/music/MusicAlbumRowCard.tsx | 5 +-
components/music/MusicArtistCard.tsx | 5 +-
components/music/MusicPlaylistCard.tsx | 5 +-
components/music/TrackOptionsSheet.tsx | 10 +-
.../{JellyseerrPoster.tsx => SeerrPoster.tsx} | 41 ++--
components/search/DiscoverFilters.tsx | 48 +++--
components/{jellyseerr => seerr}/Cast.tsx | 6 +-
.../{jellyseerr => seerr}/DetailFacts.tsx | 36 ++--
.../{jellyseerr => seerr}/GridSkeleton.tsx | 0
.../ParallaxSlideShow.tsx | 0
.../{jellyseerr => seerr}/PersonPoster.tsx | 10 +-
.../{jellyseerr => seerr}/RequestModal.tsx | 60 +++---
.../SeerrIndexPage.tsx} | 82 ++++----
.../SeerrMediaIcon.tsx} | 10 +-
.../SeerrStatusIcon.tsx} | 4 +-
.../discover/CompanySlide.tsx | 15 +-
.../discover/Discover.tsx | 8 +-
.../discover/GenericSlideCard.tsx | 0
.../discover/GenreSlide.tsx | 18 +-
.../discover/MovieTvSlide.tsx | 24 +--
.../discover/RecentRequestsSlide.tsx | 32 ++--
.../{jellyseerr => seerr}/discover/Slide.tsx | 0
...JellyseerrSeasons.tsx => SeerrSeasons.tsx} | 50 +++--
components/settings/Jellyseerr.tsx | 181 ------------------
components/settings/PluginSettings.tsx | 2 +-
components/settings/Seerr.tsx | 174 +++++++++++++++++
hooks/{useJellyseerr.ts => useSeerr.ts} | 116 ++++++-----
providers/JellyfinProvider.tsx | 16 +-
translations/en.json | 16 +-
.../useSeerrCanRequest.ts} | 18 +-
utils/atoms/settings.ts | 4 +-
47 files changed, 599 insertions(+), 680 deletions(-)
rename app/(auth)/(tabs)/(home)/settings/plugins/{jellyseerr => seerr}/page.tsx (74%)
rename app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/{jellyseerr => seerr}/company/[companyId].tsx (75%)
rename app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/{jellyseerr => seerr}/genre/[genreId].tsx (67%)
rename app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/{jellyseerr => seerr}/page.tsx (87%)
rename app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/{jellyseerr => seerr}/person/[personId].tsx (70%)
rename assets/icons/{jellyseerr-logo.svg => seerr-logo.svg} (100%)
rename assets/images/{jellyseerr.PNG => seerr.PNG} (100%)
rename components/common/{JellyseerrItemRouter.tsx => SeerrItemRouter.tsx} (92%)
rename components/posters/{JellyseerrPoster.tsx => SeerrPoster.tsx} (84%)
rename components/{jellyseerr => seerr}/Cast.tsx (88%)
rename components/{jellyseerr => seerr}/DetailFacts.tsx (84%)
rename components/{jellyseerr => seerr}/GridSkeleton.tsx (100%)
rename components/{jellyseerr => seerr}/ParallaxSlideShow.tsx (100%)
rename components/{jellyseerr => seerr}/PersonPoster.tsx (78%)
rename components/{jellyseerr => seerr}/RequestModal.tsx (89%)
rename components/{jellyseerr/JellyseerrIndexPage.tsx => seerr/SeerrIndexPage.tsx} (65%)
rename components/{jellyseerr/JellyseerrMediaIcon.tsx => seerr/SeerrMediaIcon.tsx} (82%)
rename components/{jellyseerr/JellyseerrStatusIcon.tsx => seerr/SeerrStatusIcon.tsx} (96%)
rename components/{jellyseerr => seerr}/discover/CompanySlide.tsx (74%)
rename components/{jellyseerr => seerr}/discover/Discover.tsx (87%)
rename components/{jellyseerr => seerr}/discover/GenericSlideCard.tsx (100%)
rename components/{jellyseerr => seerr}/discover/GenreSlide.tsx (78%)
rename components/{jellyseerr => seerr}/discover/MovieTvSlide.tsx (76%)
rename components/{jellyseerr => seerr}/discover/RecentRequestsSlide.tsx (70%)
rename components/{jellyseerr => seerr}/discover/Slide.tsx (100%)
rename components/series/{JellyseerrSeasons.tsx => SeerrSeasons.tsx} (88%)
delete mode 100644 components/settings/Jellyseerr.tsx
create mode 100644 components/settings/Seerr.tsx
rename hooks/{useJellyseerr.ts => useSeerr.ts} (82%)
rename utils/{_jellyseerr/useJellyseerrCanRequest.ts => _seerr/useSeerrCanRequest.ts} (83%)
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 2111dd2e..1037334b 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -3,7 +3,7 @@
## Project Overview
Streamyfin is a cross-platform Jellyfin video streaming client built with Expo (React Native).
-It supports mobile (iOS/Android) and TV platforms, integrates with Jellyfin and Jellyseerr APIs,
+It supports mobile (iOS/Android) and TV platforms, integrates with Jellyfin and Seerr APIs,
and provides seamless media streaming with offline capabilities and Chromecast support.
## Main Technologies
diff --git a/README.md b/README.md
index 44a8863c..26f8e2fa 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@
-
+
diff --git a/app/(auth)/(tabs)/(home)/_layout.tsx b/app/(auth)/(tabs)/(home)/_layout.tsx
index a7e059ed..761e868c 100644
--- a/app/(auth)/(tabs)/(home)/_layout.tsx
+++ b/app/(auth)/(tabs)/(home)/_layout.tsx
@@ -222,9 +222,9 @@ export default function IndexLayout() {
}}
/>
-
+
);
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/jellyseerr/company/[companyId].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/seerr/company/[companyId].tsx
similarity index 75%
rename from app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/jellyseerr/company/[companyId].tsx
rename to app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/seerr/company/[companyId].tsx
index fdcd786c..359ebfd1 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/jellyseerr/company/[companyId].tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/seerr/company/[companyId].tsx
@@ -3,9 +3,9 @@ import { Image } from "expo-image";
import { useLocalSearchParams } from "expo-router";
import { uniqBy } from "lodash";
import { useMemo } from "react";
-import ParallaxSlideShow from "@/components/jellyseerr/ParallaxSlideShow";
-import JellyseerrPoster from "@/components/posters/JellyseerrPoster";
-import { Endpoints, useJellyseerr } from "@/hooks/useJellyseerr";
+import SeerrPoster from "@/components/posters/SeerrPoster";
+import ParallaxSlideShow from "@/components/seerr/ParallaxSlideShow";
+import { Endpoints, useSeerr } from "@/hooks/useSeerr";
import { DiscoverSliderType } from "@/utils/jellyseerr/server/constants/discover";
import {
type MovieResult,
@@ -13,9 +13,9 @@ import {
} from "@/utils/jellyseerr/server/models/Search";
import { COMPANY_LOGO_IMAGE_FILTER } from "@/utils/jellyseerr/src/components/Discover/NetworkSlider";
-export default function page() {
+export default function CompanyPage() {
const local = useLocalSearchParams();
- const { jellyseerrApi, isJellyseerrMovieOrTvResult } = useJellyseerr();
+ const { seerrApi, isSeerrMovieOrTvResult } = useSeerr();
const { companyId, image, type } = local as unknown as {
companyId: string;
@@ -25,12 +25,12 @@ export default function page() {
};
const { data, fetchNextPage, hasNextPage, isLoading } = useInfiniteQuery({
- queryKey: ["jellyseerr", "company", type, companyId],
+ queryKey: ["seerr", "company", type, companyId],
queryFn: async ({ pageParam }) => {
const params: any = {
page: Number(pageParam),
};
- return jellyseerrApi?.discover(
+ return seerrApi?.discover(
`${
Number(type) === DiscoverSliderType.NETWORKS
? Endpoints.DISCOVER_TV_NETWORK
@@ -39,7 +39,7 @@ export default function page() {
params,
);
},
- enabled: !!jellyseerrApi && !!companyId,
+ enabled: !!seerrApi && !!companyId,
initialPageParam: 1,
getNextPageParam: (lastPage, pages) =>
(lastPage?.page || pages?.findLast((p) => p?.results.length)?.page || 1) +
@@ -53,8 +53,7 @@ export default function page() {
data?.pages
?.filter((p) => p?.results.length)
.flatMap(
- (p) =>
- p?.results.filter((r) => isJellyseerrMovieOrTvResult(r)) ?? [],
+ (p) => p?.results.filter((r) => isSeerrMovieOrTvResult(r)) ?? [],
),
"id",
) ?? [],
@@ -63,15 +62,15 @@ export default function page() {
const backdrops = useMemo(
() =>
- jellyseerrApi
+ seerrApi
? flatData.map((r) =>
- jellyseerrApi.imageProxy(
+ seerrApi.imageProxy(
(r as TvResult | MovieResult).backdropPath,
"w1920_and_h800_multi_faces",
),
)
: [],
- [jellyseerrApi, flatData],
+ [seerrApi, flatData],
);
return (
@@ -92,7 +91,7 @@ export default function page() {
key={companyId}
className='bottom-1 w-1/2'
source={{
- uri: jellyseerrApi?.imageProxy(image, COMPANY_LOGO_IMAGE_FILTER),
+ uri: seerrApi?.imageProxy(image, COMPANY_LOGO_IMAGE_FILTER),
}}
cachePolicy={"memory-disk"}
contentFit='contain'
@@ -101,7 +100,7 @@ export default function page() {
}}
/>
}
- renderItem={(item, _index) => }
+ renderItem={(item, _index) => }
/>
);
}
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/jellyseerr/genre/[genreId].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/seerr/genre/[genreId].tsx
similarity index 67%
rename from app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/jellyseerr/genre/[genreId].tsx
rename to app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/seerr/genre/[genreId].tsx
index 7ea00808..a61cff40 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/jellyseerr/genre/[genreId].tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/seerr/genre/[genreId].tsx
@@ -3,15 +3,15 @@ import { useLocalSearchParams } from "expo-router";
import { uniqBy } from "lodash";
import { useMemo } from "react";
import { Text } from "@/components/common/Text";
-import { textShadowStyle } from "@/components/jellyseerr/discover/GenericSlideCard";
-import ParallaxSlideShow from "@/components/jellyseerr/ParallaxSlideShow";
-import JellyseerrPoster from "@/components/posters/JellyseerrPoster";
-import { Endpoints, useJellyseerr } from "@/hooks/useJellyseerr";
+import SeerrPoster from "@/components/posters/SeerrPoster";
+import { textShadowStyle } from "@/components/seerr/discover/GenericSlideCard";
+import ParallaxSlideShow from "@/components/seerr/ParallaxSlideShow";
+import { Endpoints, useSeerr } from "@/hooks/useSeerr";
import { DiscoverSliderType } from "@/utils/jellyseerr/server/constants/discover";
-export default function page() {
+export default function GenrePage() {
const local = useLocalSearchParams();
- const { jellyseerrApi, isJellyseerrMovieOrTvResult } = useJellyseerr();
+ const { seerrApi, isSeerrMovieOrTvResult } = useSeerr();
const { genreId, name, type } = local as unknown as {
genreId: string;
@@ -20,21 +20,21 @@ export default function page() {
};
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
- queryKey: ["jellyseerr", "company", type, genreId],
+ queryKey: ["seerr", "company", type, genreId],
queryFn: async ({ pageParam }) => {
const params: any = {
page: Number(pageParam),
genre: genreId,
};
- return jellyseerrApi?.discover(
+ return seerrApi?.discover(
type === DiscoverSliderType.MOVIE_GENRES
? Endpoints.DISCOVER_MOVIES
: Endpoints.DISCOVER_TV,
params,
);
},
- enabled: !!jellyseerrApi && !!genreId,
+ enabled: !!seerrApi && !!genreId,
initialPageParam: 1,
getNextPageParam: (lastPage, pages) =>
(lastPage?.page || pages?.findLast((p) => p?.results.length)?.page || 1) +
@@ -48,8 +48,7 @@ export default function page() {
data?.pages
?.filter((p) => p?.results.length)
.flatMap(
- (p) =>
- p?.results.filter((r) => isJellyseerrMovieOrTvResult(r)) ?? [],
+ (p) => p?.results.filter((r) => isSeerrMovieOrTvResult(r)) ?? [],
),
"id",
) ?? [],
@@ -58,15 +57,12 @@ export default function page() {
const backdrops = useMemo(
() =>
- jellyseerrApi
+ seerrApi
? flatData.map((r) =>
- jellyseerrApi.imageProxy(
- r.backdropPath,
- "w1920_and_h800_multi_faces",
- ),
+ seerrApi.imageProxy(r.backdropPath, "w1920_and_h800_multi_faces"),
)
: [],
- [jellyseerrApi, flatData],
+ [seerrApi, flatData],
);
return (
@@ -91,7 +87,7 @@ export default function page() {
{name}
}
- renderItem={(item, _index) => }
+ renderItem={(item, _index) => }
/>
);
}
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/jellyseerr/page.tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/seerr/page.tsx
similarity index 87%
rename from app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/jellyseerr/page.tsx
rename to app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/seerr/page.tsx
index 2f0af594..901f5032 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/jellyseerr/page.tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/seerr/page.tsx
@@ -18,18 +18,18 @@ import { toast } from "sonner-native";
import { Button } from "@/components/Button";
import { Text } from "@/components/common/Text";
import { GenreTags } from "@/components/GenreTags";
-import Cast from "@/components/jellyseerr/Cast";
-import DetailFacts from "@/components/jellyseerr/DetailFacts";
-import RequestModal from "@/components/jellyseerr/RequestModal";
import { OverviewText } from "@/components/OverviewText";
import { ParallaxScrollView } from "@/components/ParallaxPage";
import { PlatformDropdown } from "@/components/PlatformDropdown";
-import { JellyserrRatings } from "@/components/Ratings";
-import JellyseerrSeasons from "@/components/series/JellyseerrSeasons";
+import { SeerrRatings } from "@/components/Ratings";
+import Cast from "@/components/seerr/Cast";
+import DetailFacts from "@/components/seerr/DetailFacts";
+import RequestModal from "@/components/seerr/RequestModal";
+import SeerrSeasons from "@/components/series/SeerrSeasons";
import { ItemActions } from "@/components/series/SeriesActions";
import useRouter from "@/hooks/useAppRouter";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
-import { useJellyseerrCanRequest } from "@/utils/_jellyseerr/useJellyseerrCanRequest";
+import { useSeerr } from "@/hooks/useSeerr";
+import { useSeerrCanRequest } from "@/utils/_seerr/useSeerrCanRequest";
import { ANIME_KEYWORD_ID } from "@/utils/jellyseerr/server/api/themoviedb/constants";
import {
type IssueType,
@@ -68,7 +68,7 @@ const Page: React.FC = () => {
} & Partial;
const navigation = useNavigation();
- const { jellyseerrApi, jellyseerrUser, requestMedia } = useJellyseerr();
+ const { seerrApi, seerrUser, requestMedia } = useSeerr();
const [issueType, setIssueType] = useState();
const [issueMessage, setIssueMessage] = useState();
@@ -83,8 +83,8 @@ const Page: React.FC = () => {
isLoading,
refetch,
} = useQuery({
- enabled: !!jellyseerrApi && !!result && !!result.id,
- queryKey: ["jellyseerr", "detail", mediaType, result.id],
+ enabled: !!seerrApi && !!result && !!result.id,
+ queryKey: ["seerr", "detail", mediaType, result.id],
staleTime: 0,
refetchOnMount: true,
refetchOnReconnect: true,
@@ -93,21 +93,18 @@ const Page: React.FC = () => {
refetchInterval: 0,
queryFn: async () => {
return mediaType === MediaType.MOVIE
- ? jellyseerrApi?.movieDetails(result.id!)
- : jellyseerrApi?.tvDetails(result.id!);
+ ? seerrApi?.movieDetails(result.id!)
+ : seerrApi?.tvDetails(result.id!);
},
});
const [canRequest, hasAdvancedRequestPermission] =
- useJellyseerrCanRequest(details);
+ useSeerrCanRequest(details);
const canManageRequests = useMemo(() => {
- if (!jellyseerrUser) return false;
- return hasPermission(
- Permission.MANAGE_REQUESTS,
- jellyseerrUser.permissions,
- );
- }, [jellyseerrUser]);
+ if (!seerrUser) return false;
+ return hasPermission(Permission.MANAGE_REQUESTS, seerrUser.permissions);
+ }, [seerrUser]);
const pendingRequest = useMemo(() => {
return details?.mediaInfo?.requests?.find(
@@ -119,27 +116,27 @@ const Page: React.FC = () => {
if (!pendingRequest?.id) return;
try {
- await jellyseerrApi?.approveRequest(pendingRequest.id);
- toast.success(t("jellyseerr.toasts.request_approved"));
+ await seerrApi?.approveRequest(pendingRequest.id);
+ toast.success(t("seerr.toasts.request_approved"));
refetch();
} catch (error) {
- toast.error(t("jellyseerr.toasts.failed_to_approve_request"));
+ toast.error(t("seerr.toasts.failed_to_approve_request"));
console.error("Failed to approve request:", error);
}
- }, [jellyseerrApi, pendingRequest, refetch, t]);
+ }, [seerrApi, pendingRequest, refetch, t]);
const handleDeclineRequest = useCallback(async () => {
if (!pendingRequest?.id) return;
try {
- await jellyseerrApi?.declineRequest(pendingRequest.id);
- toast.success(t("jellyseerr.toasts.request_declined"));
+ await seerrApi?.declineRequest(pendingRequest.id);
+ toast.success(t("seerr.toasts.request_declined"));
refetch();
} catch (error) {
- toast.error(t("jellyseerr.toasts.failed_to_decline_request"));
+ toast.error(t("seerr.toasts.failed_to_decline_request"));
console.error("Failed to decline request:", error);
}
- }, [jellyseerrApi, pendingRequest, refetch, t]);
+ }, [seerrApi, pendingRequest, refetch, t]);
const renderBackdrop = useCallback(
(props: BottomSheetBackdropProps) => (
@@ -154,7 +151,7 @@ const Page: React.FC = () => {
const submitIssue = useCallback(() => {
if (result.id && issueType && issueMessage && details) {
- jellyseerrApi
+ seerrApi
?.submitIssue(details.mediaInfo.id, Number(issueType), issueMessage)
.then(() => {
setIssueType(undefined);
@@ -162,7 +159,7 @@ const Page: React.FC = () => {
bottomSheetModalRef?.current?.close();
});
}
- }, [jellyseerrApi, details, result, issueType, issueMessage]);
+ }, [seerrApi, details, result, issueType, issueMessage]);
const handleIssueModalDismiss = useCallback(() => {
setIssueTypeDropdownOpen(false);
@@ -214,7 +211,7 @@ const Page: React.FC = () => {
const issueTypeOptionGroups = useMemo(
() => [
{
- title: t("jellyseerr.types"),
+ title: t("seerr.types"),
options: Object.entries(IssueTypeName)
.reverse()
.map(([key, value]) => ({
@@ -265,7 +262,7 @@ const Page: React.FC = () => {
height: "100%",
}}
source={{
- uri: jellyseerrApi?.imageProxy(
+ uri: seerrApi?.imageProxy(
result.backdropPath,
"w1920_and_h800_multi_faces",
),
@@ -295,7 +292,7 @@ const Page: React.FC = () => {
- {
/>
) : canRequest ? (
) : (
details?.mediaInfo?.jellyfinMediaId && (
@@ -353,7 +350,7 @@ const Page: React.FC = () => {
}}
>
- {t("jellyseerr.report_issue_button")}
+ {t("seerr.report_issue_button")}
)}
@@ -389,12 +386,12 @@ const Page: React.FC = () => {
- {t("jellyseerr.requested_by", {
+ {t("seerr.requested_by", {
user:
pendingRequest.requestedBy?.displayName ||
pendingRequest.requestedBy?.username ||
pendingRequest.requestedBy?.jellyfinUsername ||
- t("jellyseerr.unknown_user"),
+ t("seerr.unknown_user"),
})}
@@ -415,7 +412,7 @@ const Page: React.FC = () => {
borderStyle: "solid",
}}
>
- {t("jellyseerr.approve")}
+ {t("seerr.approve")}
@@ -442,7 +439,7 @@ const Page: React.FC = () => {
{mediaType === MediaType.TV && (
- {
- {t("jellyseerr.whats_wrong")}
+ {t("seerr.whats_wrong")}
- {t("jellyseerr.issue_type")}
+ {t("seerr.issue_type")}
{
{issueType
? IssueTypeName[issueType]
- : t("jellyseerr.select_an_issue")}
+ : t("seerr.select_an_issue")}
}
- title={t("jellyseerr.types")}
+ title={t("seerr.types")}
open={issueTypeDropdownOpen}
onOpenChange={setIssueTypeDropdownOpen}
/>
@@ -522,7 +519,7 @@ const Page: React.FC = () => {
maxLength={254}
style={{ color: "white" }}
clearButtonMode='always'
- placeholder={t("jellyseerr.describe_the_issue")}
+ placeholder={t("seerr.describe_the_issue")}
placeholderTextColor='#9CA3AF'
// Issue with multiline + Textinput inside a portal
// https://github.com/callstack/react-native-paper/issues/1668
@@ -532,7 +529,7 @@ const Page: React.FC = () => {
diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/jellyseerr/person/[personId].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/seerr/person/[personId].tsx
similarity index 70%
rename from app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/jellyseerr/person/[personId].tsx
rename to app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/seerr/person/[personId].tsx
index a29e1280..41b5ef8f 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/jellyseerr/person/[personId].tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/seerr/person/[personId].tsx
@@ -5,31 +5,27 @@ import { orderBy, uniqBy } from "lodash";
import { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { Text } from "@/components/common/Text";
-import ParallaxSlideShow from "@/components/jellyseerr/ParallaxSlideShow";
import { OverviewText } from "@/components/OverviewText";
-import JellyseerrPoster from "@/components/posters/JellyseerrPoster";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
+import SeerrPoster from "@/components/posters/SeerrPoster";
+import ParallaxSlideShow from "@/components/seerr/ParallaxSlideShow";
+import { useSeerr } from "@/hooks/useSeerr";
import type { PersonCreditCast } from "@/utils/jellyseerr/server/models/Person";
-export default function page() {
+export default function PersonPage() {
const local = useLocalSearchParams();
const { t } = useTranslation();
- const {
- jellyseerrApi,
- jellyseerrRegion: region,
- jellyseerrLocale: locale,
- } = useJellyseerr();
+ const { seerrApi, seerrRegion: region, seerrLocale: locale } = useSeerr();
const { personId } = local as { personId: string };
const { data } = useQuery({
- queryKey: ["jellyseerr", "person", personId],
+ queryKey: ["seerr", "person", personId],
queryFn: async () => ({
- details: await jellyseerrApi?.personDetails(personId),
- combinedCredits: await jellyseerrApi?.personCombinedCredits(personId),
+ details: await seerrApi?.personDetails(personId),
+ combinedCredits: await seerrApi?.personCombinedCredits(personId),
}),
- enabled: !!jellyseerrApi && !!personId,
+ enabled: !!seerrApi && !!personId,
});
const castedRoles: PersonCreditCast[] = useMemo(
@@ -46,22 +42,19 @@ export default function page() {
);
const backdrops = useMemo(
() =>
- jellyseerrApi
+ seerrApi
? castedRoles.map((c) =>
- jellyseerrApi.imageProxy(
- c.backdropPath,
- "w1920_and_h800_multi_faces",
- ),
+ seerrApi.imageProxy(c.backdropPath, "w1920_and_h800_multi_faces"),
)
: [],
- [jellyseerrApi, data?.combinedCredits],
+ [seerrApi, data?.combinedCredits],
);
return (
item.id.toString()}
logo={
{data?.details?.name}
- {t("jellyseerr.born")}{" "}
+ {t("seerr.born")}{" "}
{data?.details?.birthday &&
new Date(data.details.birthday).toLocaleDateString(
`${locale}-${region}`,
@@ -103,7 +96,7 @@ export default function page() {
MainContent={() => (
)}
- renderItem={(item, _index) => }
+ renderItem={(item, _index) => }
/>
);
}
diff --git a/app/(auth)/(tabs)/(search)/_layout.tsx b/app/(auth)/(tabs)/(search)/_layout.tsx
index f4d34978..b008c04d 100644
--- a/app/(auth)/(tabs)/(search)/_layout.tsx
+++ b/app/(auth)/(tabs)/(search)/_layout.tsx
@@ -33,17 +33,17 @@ export default function SearchLayout() {
headerShadowVisible: false,
}}
/>
-
+
diff --git a/app/(auth)/(tabs)/(search)/index.tsx b/app/(auth)/(tabs)/(search)/index.tsx
index 751b1df1..cff07dd4 100644
--- a/app/(auth)/(tabs)/(search)/index.tsx
+++ b/app/(auth)/(tabs)/(search)/index.tsx
@@ -26,18 +26,18 @@ import { Input } from "@/components/common/Input";
import { Text } from "@/components/common/Text";
import { TouchableItemRouter } from "@/components/common/TouchableItemRouter";
import { ItemCardText } from "@/components/ItemCardText";
-import {
- JellyseerrSearchSort,
- JellyserrIndexPage,
-} from "@/components/jellyseerr/JellyseerrIndexPage";
import MoviePoster from "@/components/posters/MoviePoster";
import SeriesPoster from "@/components/posters/SeriesPoster";
import { DiscoverFilters } from "@/components/search/DiscoverFilters";
import { LoadingSkeleton } from "@/components/search/LoadingSkeleton";
import { SearchItemWrapper } from "@/components/search/SearchItemWrapper";
import { SearchTabButtons } from "@/components/search/SearchTabButtons";
+import {
+ SeerrIndexPage,
+ SeerrSearchSort,
+} from "@/components/seerr/SeerrIndexPage";
import useRouter from "@/hooks/useAppRouter";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
+import { useSeerr } from "@/hooks/useSeerr";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings";
import { eventBus } from "@/utils/eventBus";
@@ -55,7 +55,7 @@ const exampleSearches = [
"The Mandalorian",
];
-export default function search() {
+export default function SearchPage() {
const params = useLocalSearchParams();
const insets = useSafeAreaInsets();
const router = useRouter();
@@ -93,16 +93,11 @@ export default function search() {
const [api] = useAtom(apiAtom);
const { settings } = useSettings();
- const { jellyseerrApi } = useJellyseerr();
- const [jellyseerrOrderBy, setJellyseerrOrderBy] =
- useState(
- JellyseerrSearchSort[
- JellyseerrSearchSort.DEFAULT
- ] as unknown as JellyseerrSearchSort,
- );
- const [jellyseerrSortOrder, setJellyseerrSortOrder] = useState<
- "asc" | "desc"
- >("desc");
+ const { seerrApi } = useSeerr();
+ const [seerrOrderBy, setSeerrOrderBy] = useState(
+ SeerrSearchSort[SeerrSearchSort.DEFAULT] as unknown as SeerrSearchSort,
+ );
+ const [seerrSortOrder, setSeerrSortOrder] = useState<"asc" | "desc">("desc");
const searchEngine = useMemo(() => {
return settings?.searchEngine || "Jellyfin";
@@ -474,7 +469,7 @@ export default function search() {
className='flex flex-col'
style={{ paddingTop: Platform.OS === "android" ? 10 : 0 }}
>
- {jellyseerrApi && (
+ {seerrApi && (
)}
@@ -754,10 +749,10 @@ export default function search() {
/>
) : (
-
)}
diff --git a/assets/icons/jellyseerr-logo.svg b/assets/icons/seerr-logo.svg
similarity index 100%
rename from assets/icons/jellyseerr-logo.svg
rename to assets/icons/seerr-logo.svg
diff --git a/assets/images/jellyseerr.PNG b/assets/images/seerr.PNG
similarity index 100%
rename from assets/images/jellyseerr.PNG
rename to assets/images/seerr.PNG
diff --git a/components/IntroSheet.tsx b/components/IntroSheet.tsx
index ea1a23a2..7317b7e8 100644
--- a/components/IntroSheet.tsx
+++ b/components/IntroSheet.tsx
@@ -89,16 +89,16 @@ export const IntroSheet = forwardRef((_, ref) => {
- Jellyseerr
+ Seerr
- {t("home.intro.jellyseerr_feature_description")}
+ {t("home.intro.seerr_feature_description")}
diff --git a/components/Ratings.tsx b/components/Ratings.tsx
index 5741233f..e091c64c 100644
--- a/components/Ratings.tsx
+++ b/components/Ratings.tsx
@@ -4,7 +4,7 @@ import { useQuery } from "@tanstack/react-query";
import { Image } from "expo-image";
import { useMemo } from "react";
import { View, type ViewProps } from "react-native";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
+import { useSeerr } from "@/hooks/useSeerr";
import { MediaType } from "@/utils/jellyseerr/server/constants/media";
import type { MovieDetails } from "@/utils/jellyseerr/server/models/Movie";
import type {
@@ -55,23 +55,23 @@ export const Ratings: React.FC = ({ item, ...props }) => {
);
};
-export const JellyserrRatings: React.FC<{
+export const SeerrRatings: React.FC<{
result: MovieResult | TvResult | TvDetails | MovieDetails;
}> = ({ result }) => {
- const { jellyseerrApi, getMediaType } = useJellyseerr();
+ const { seerrApi, getMediaType } = useSeerr();
const mediaType = useMemo(() => getMediaType(result), [result]);
const { data, isLoading } = useQuery({
- queryKey: ["jellyseerr", result.id, mediaType, "ratings"],
+ queryKey: ["seerr", result.id, mediaType, "ratings"],
queryFn: async () => {
return mediaType === MediaType.MOVIE
- ? jellyseerrApi?.movieRatings(result.id)
- : jellyseerrApi?.tvRatings(result.id);
+ ? seerrApi?.movieRatings(result.id)
+ : seerrApi?.tvRatings(result.id);
},
staleTime: (5).minutesToMilliseconds(),
retry: false,
- enabled: !!jellyseerrApi,
+ enabled: !!seerrApi,
});
return (
diff --git a/components/common/JellyseerrItemRouter.tsx b/components/common/SeerrItemRouter.tsx
similarity index 92%
rename from components/common/JellyseerrItemRouter.tsx
rename to components/common/SeerrItemRouter.tsx
index f6878bc5..184ef490 100644
--- a/components/common/JellyseerrItemRouter.tsx
+++ b/components/common/SeerrItemRouter.tsx
@@ -21,7 +21,7 @@ interface Props extends TouchableOpacityProps {
mediaType: MediaType;
}
-export const TouchableJellyseerrRouter: React.FC> = ({
+export const TouchableSeerrRouter: React.FC> = ({
result,
mediaTitle,
releaseYear,
@@ -43,7 +43,7 @@ export const TouchableJellyseerrRouter: React.FC> = ({
if (!result) return;
router.push({
- pathname: `/(auth)/(tabs)/${from}/jellyseerr/page`,
+ pathname: `/(auth)/(tabs)/${from}/seerr/page`,
// @ts-expect-error
params: {
...result,
diff --git a/components/music/MusicAlbumCard.tsx b/components/music/MusicAlbumCard.tsx
index 1a747c8e..11e78610 100644
--- a/components/music/MusicAlbumCard.tsx
+++ b/components/music/MusicAlbumCard.tsx
@@ -23,10 +23,7 @@ export const MusicAlbumCard: React.FC = ({ album, width = 130 }) => {
);
const handlePress = useCallback(() => {
- router.push({
- pathname: "/music/album/[albumId]",
- params: { albumId: album.Id! },
- });
+ router.push(`/music/album/${album.Id}`);
}, [router, album.Id]);
return (
diff --git a/components/music/MusicAlbumRowCard.tsx b/components/music/MusicAlbumRowCard.tsx
index 6612a392..e794a793 100644
--- a/components/music/MusicAlbumRowCard.tsx
+++ b/components/music/MusicAlbumRowCard.tsx
@@ -24,10 +24,7 @@ export const MusicAlbumRowCard: React.FC = ({ album }) => {
);
const handlePress = useCallback(() => {
- router.push({
- pathname: "/music/album/[albumId]",
- params: { albumId: album.Id! },
- });
+ router.push(`/music/album/${album.Id}`);
}, [router, album.Id]);
return (
diff --git a/components/music/MusicArtistCard.tsx b/components/music/MusicArtistCard.tsx
index c98e3fce..a9bfc61b 100644
--- a/components/music/MusicArtistCard.tsx
+++ b/components/music/MusicArtistCard.tsx
@@ -25,10 +25,7 @@ export const MusicArtistCard: React.FC = ({ artist }) => {
);
const handlePress = useCallback(() => {
- router.push({
- pathname: "/music/artist/[artistId]",
- params: { artistId: artist.Id! },
- });
+ router.push(`/music/artist/${artist.Id}`);
}, [router, artist.Id]);
return (
diff --git a/components/music/MusicPlaylistCard.tsx b/components/music/MusicPlaylistCard.tsx
index 93caf7a4..50671715 100644
--- a/components/music/MusicPlaylistCard.tsx
+++ b/components/music/MusicPlaylistCard.tsx
@@ -61,10 +61,7 @@ export const MusicPlaylistCard: React.FC = ({ playlist }) => {
const hasDownloads = downloadStatus.downloaded > 0;
const handlePress = useCallback(() => {
- router.push({
- pathname: "/music/playlist/[playlistId]",
- params: { playlistId: playlist.Id! },
- });
+ router.push(`/music/playlist/${playlist.Id}`);
}, [router, playlist.Id]);
return (
diff --git a/components/music/TrackOptionsSheet.tsx b/components/music/TrackOptionsSheet.tsx
index a0b78472..b5de1379 100644
--- a/components/music/TrackOptionsSheet.tsx
+++ b/components/music/TrackOptionsSheet.tsx
@@ -197,10 +197,7 @@ export const TrackOptionsSheet: React.FC = ({
const artistId = track?.ArtistItems?.[0]?.Id;
if (artistId) {
setOpen(false);
- router.push({
- pathname: "/music/artist/[artistId]",
- params: { artistId },
- });
+ router.push(`/music/artist/${artistId}`);
}
}, [track?.ArtistItems, router, setOpen]);
@@ -208,10 +205,7 @@ export const TrackOptionsSheet: React.FC = ({
const albumId = track?.AlbumId || track?.ParentId;
if (albumId) {
setOpen(false);
- router.push({
- pathname: "/music/album/[albumId]",
- params: { albumId },
- });
+ router.push(`/music/album/${albumId}`);
}
}, [track?.AlbumId, track?.ParentId, router, setOpen]);
diff --git a/components/posters/JellyseerrPoster.tsx b/components/posters/SeerrPoster.tsx
similarity index 84%
rename from components/posters/JellyseerrPoster.tsx
rename to components/posters/SeerrPoster.tsx
index d7b1fcdb..399ac386 100644
--- a/components/posters/JellyseerrPoster.tsx
+++ b/components/posters/SeerrPoster.tsx
@@ -7,15 +7,15 @@ import Animated, {
useSharedValue,
withTiming,
} from "react-native-reanimated";
-import { TouchableJellyseerrRouter } from "@/components/common/JellyseerrItemRouter";
+import { TouchableSeerrRouter } from "@/components/common/SeerrItemRouter";
import { Text } from "@/components/common/Text";
import { Tag, Tags } from "@/components/GenreTags";
-import { textShadowStyle } from "@/components/jellyseerr/discover/GenericSlideCard";
-import JellyseerrMediaIcon from "@/components/jellyseerr/JellyseerrMediaIcon";
-import JellyseerrStatusIcon from "@/components/jellyseerr/JellyseerrStatusIcon";
+import { textShadowStyle } from "@/components/seerr/discover/GenericSlideCard";
+import SeerrMediaIcon from "@/components/seerr/SeerrMediaIcon";
+import SeerrStatusIcon from "@/components/seerr/SeerrStatusIcon";
import { Colors } from "@/constants/Colors";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
-import { useJellyseerrCanRequest } from "@/utils/_jellyseerr/useJellyseerrCanRequest";
+import { useSeerr } from "@/hooks/useSeerr";
+import { useSeerrCanRequest } from "@/utils/_seerr/useSeerrCanRequest";
import { MediaStatus } from "@/utils/jellyseerr/server/constants/media";
import type MediaRequest from "@/utils/jellyseerr/server/entity/MediaRequest";
import type { DownloadingItem } from "@/utils/jellyseerr/server/lib/downloadtracker";
@@ -34,13 +34,13 @@ interface Props extends ViewProps {
mediaRequest?: MediaRequest;
}
-const JellyseerrPoster: React.FC = ({
+const SeerrPoster: React.FC = ({
item,
horizontal,
showDownloadInfo,
mediaRequest,
}) => {
- const { jellyseerrApi, getTitle, getYear, getMediaType } = useJellyseerr();
+ const { seerrApi, getTitle, getYear, getMediaType } = useSeerr();
const loadingOpacity = useSharedValue(1);
const imageOpacity = useSharedValue(0);
const { t } = useTranslation();
@@ -56,16 +56,13 @@ const JellyseerrPoster: React.FC = ({
const backdropSrc = useMemo(
() =>
- jellyseerrApi?.imageProxy(
- item?.backdropPath,
- "w1920_and_h800_multi_faces",
- ),
- [item, jellyseerrApi, horizontal],
+ seerrApi?.imageProxy(item?.backdropPath, "w1920_and_h800_multi_faces"),
+ [item, seerrApi, horizontal],
);
const posterSrc = useMemo(
- () => jellyseerrApi?.imageProxy(item?.posterPath, "w300_and_h450_face"),
- [item, jellyseerrApi, horizontal],
+ () => seerrApi?.imageProxy(item?.posterPath, "w300_and_h450_face"),
+ [item, seerrApi, horizontal],
);
const title = useMemo(() => getTitle(item), [item]);
@@ -75,7 +72,7 @@ const JellyseerrPoster: React.FC = ({
const size = useMemo(() => (horizontal ? "h-28" : "w-28"), [horizontal]);
const ratio = useMemo(() => (horizontal ? "15/10" : "10/15"), [horizontal]);
- const [canRequest] = useJellyseerrCanRequest(item);
+ const [canRequest] = useSeerrCanRequest(item);
const is4k = useMemo(() => mediaRequest?.is4k === true, [mediaRequest]);
@@ -109,7 +106,7 @@ const JellyseerrPoster: React.FC = ({
second,
third,
fourth,
- t("home.settings.plugins.jellyseerr.plus_n_more", { n: rest.length }),
+ t("home.settings.plugins.seerr.plus_n_more", { n: rest.length }),
];
}
return seasons;
@@ -121,7 +118,7 @@ const JellyseerrPoster: React.FC = ({
}, [mediaRequest, is4k]);
return (
- = ({
)}
>
)}
-
-
@@ -201,8 +198,8 @@ const JellyseerrPoster: React.FC = ({
{releaseYear || ""}
-
+
);
};
-export default JellyseerrPoster;
+export default SeerrPoster;
diff --git a/components/search/DiscoverFilters.tsx b/components/search/DiscoverFilters.tsx
index 2e844c88..7a3a2a60 100644
--- a/components/search/DiscoverFilters.tsx
+++ b/components/search/DiscoverFilters.tsx
@@ -1,19 +1,19 @@
import { Button, ContextMenu, Host, Picker } from "@expo/ui/swift-ui";
import { Platform, View } from "react-native";
import { FilterButton } from "@/components/filters/FilterButton";
-import { JellyseerrSearchSort } from "@/components/jellyseerr/JellyseerrIndexPage";
+import { SeerrSearchSort } from "@/components/seerr/SeerrIndexPage";
interface DiscoverFiltersProps {
searchFilterId: string;
orderFilterId: string;
- jellyseerrOrderBy: JellyseerrSearchSort;
- setJellyseerrOrderBy: (value: JellyseerrSearchSort) => void;
- jellyseerrSortOrder: "asc" | "desc";
- setJellyseerrSortOrder: (value: "asc" | "desc") => void;
+ seerrOrderBy: SeerrSearchSort;
+ setSeerrOrderBy: (value: SeerrSearchSort) => void;
+ seerrSortOrder: "asc" | "desc";
+ setSeerrSortOrder: (value: "asc" | "desc") => void;
t: (key: string) => string;
}
-const sortOptions = Object.keys(JellyseerrSearchSort).filter((v) =>
+const sortOptions = Object.keys(SeerrSearchSort).filter((v) =>
Number.isNaN(Number(v)),
);
@@ -22,10 +22,10 @@ const orderOptions = ["asc", "desc"] as const;
export const DiscoverFilters: React.FC = ({
searchFilterId,
orderFilterId,
- jellyseerrOrderBy,
- setJellyseerrOrderBy,
- jellyseerrSortOrder,
- setJellyseerrSortOrder,
+ seerrOrderBy,
+ setSeerrOrderBy,
+ seerrSortOrder,
+ setSeerrSortOrder,
t,
}) => {
if (Platform.OS === "ios") {
@@ -52,16 +52,16 @@ export const DiscoverFilters: React.FC = ({
- t(`home.settings.plugins.jellyseerr.order_by.${item}`),
+ t(`home.settings.plugins.seerr.order_by.${item}`),
)}
variant='menu'
selectedIndex={sortOptions.indexOf(
- jellyseerrOrderBy as unknown as string,
+ seerrOrderBy as unknown as string,
)}
onOptionSelected={(event: any) => {
const index = event.nativeEvent.index;
- setJellyseerrOrderBy(
- sortOptions[index] as unknown as JellyseerrSearchSort,
+ setSeerrOrderBy(
+ sortOptions[index] as unknown as SeerrSearchSort,
);
}}
/>
@@ -69,10 +69,10 @@ export const DiscoverFilters: React.FC = ({
label={t("library.filters.sort_order")}
options={orderOptions.map((item) => t(`library.filters.${item}`))}
variant='menu'
- selectedIndex={orderOptions.indexOf(jellyseerrSortOrder)}
+ selectedIndex={orderOptions.indexOf(seerrSortOrder)}
onOptionSelected={(event: any) => {
const index = event.nativeEvent.index;
- setJellyseerrSortOrder(orderOptions[index]);
+ setSeerrSortOrder(orderOptions[index]);
}}
/>
@@ -86,17 +86,15 @@ export const DiscoverFilters: React.FC = ({
- Object.keys(JellyseerrSearchSort).filter((v) =>
- Number.isNaN(Number(v)),
- )
+ Object.keys(SeerrSearchSort).filter((v) => Number.isNaN(Number(v)))
}
- set={(value) => setJellyseerrOrderBy(value[0])}
- values={[jellyseerrOrderBy]}
+ set={(value) => setSeerrOrderBy(value[0])}
+ values={[seerrOrderBy]}
title={t("library.filters.sort_by")}
renderItemLabel={(item) =>
- t(`home.settings.plugins.jellyseerr.order_by.${item}`)
+ t(`home.settings.plugins.seerr.order_by.${item}`)
}
disableSearch={true}
/>
@@ -104,8 +102,8 @@ export const DiscoverFilters: React.FC = ({
id={orderFilterId}
queryKey='jellysearr_search'
queryFn={async () => ["asc", "desc"]}
- set={(value) => setJellyseerrSortOrder(value[0])}
- values={[jellyseerrSortOrder]}
+ set={(value) => setSeerrSortOrder(value[0])}
+ values={[seerrSortOrder]}
title={t("library.filters.sort_order")}
renderItemLabel={(item) => t(`library.filters.${item}`)}
disableSearch={true}
diff --git a/components/jellyseerr/Cast.tsx b/components/seerr/Cast.tsx
similarity index 88%
rename from components/jellyseerr/Cast.tsx
rename to components/seerr/Cast.tsx
index 99440bd8..9063ac65 100644
--- a/components/jellyseerr/Cast.tsx
+++ b/components/seerr/Cast.tsx
@@ -3,7 +3,7 @@ import type React from "react";
import { useTranslation } from "react-i18next";
import { View, type ViewProps } from "react-native";
import { Text } from "@/components/common/Text";
-import PersonPoster from "@/components/jellyseerr/PersonPoster";
+import PersonPoster from "@/components/seerr/PersonPoster";
import type { MovieDetails } from "@/utils/jellyseerr/server/models/Movie";
import type { TvDetails } from "@/utils/jellyseerr/server/models/Tv";
@@ -15,9 +15,7 @@ const CastSlide: React.FC<
details?.credits?.cast &&
details?.credits?.cast?.length > 0 && (
-
- {t("jellyseerr.cast")}
-
+ {t("seerr.cast")}
= ({
const DetailFacts: React.FC<
{ details?: MovieDetails | TvDetails } & ViewProps
> = ({ details, className, ...props }) => {
- const { jellyseerrRegion: region, jellyseerrLocale: locale } =
- useJellyseerr();
+ const { seerrRegion: region, seerrLocale: locale } = useSeerr();
const { t } = useTranslation();
const releases = useMemo(
@@ -138,21 +137,21 @@ const DetailFacts: React.FC<
return (
details && (
- {t("jellyseerr.details")}
+ {t("seerr.details")}
-
+
{details.keywords.some(
(keyword) => keyword.id === ANIME_KEYWORD_ID,
- ) && }
+ ) && }
(
{r.type === 3 ? (
@@ -178,16 +177,13 @@ const DetailFacts: React.FC<
))}
/>
-
-
-
-
-
+
+
+
+
+
(
@@ -196,17 +192,17 @@ const DetailFacts: React.FC<
))}
/>
n.name,
)}
/>
n.name)}
/>
s.name)}
/>
diff --git a/components/jellyseerr/GridSkeleton.tsx b/components/seerr/GridSkeleton.tsx
similarity index 100%
rename from components/jellyseerr/GridSkeleton.tsx
rename to components/seerr/GridSkeleton.tsx
diff --git a/components/jellyseerr/ParallaxSlideShow.tsx b/components/seerr/ParallaxSlideShow.tsx
similarity index 100%
rename from components/jellyseerr/ParallaxSlideShow.tsx
rename to components/seerr/ParallaxSlideShow.tsx
diff --git a/components/jellyseerr/PersonPoster.tsx b/components/seerr/PersonPoster.tsx
similarity index 78%
rename from components/jellyseerr/PersonPoster.tsx
rename to components/seerr/PersonPoster.tsx
index e926b093..821cf52c 100644
--- a/components/jellyseerr/PersonPoster.tsx
+++ b/components/seerr/PersonPoster.tsx
@@ -4,7 +4,7 @@ import { TouchableOpacity, View, type ViewProps } from "react-native";
import { Text } from "@/components/common/Text";
import Poster from "@/components/posters/Poster";
import useRouter from "@/hooks/useAppRouter";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
+import { useSeerr } from "@/hooks/useSeerr";
interface Props {
id: string;
@@ -20,7 +20,7 @@ const PersonPoster: React.FC = ({
subName,
...props
}) => {
- const { jellyseerrApi } = useJellyseerr();
+ const { seerrApi } = useSeerr();
const router = useRouter();
const segments = useSegments();
const from = (segments as string[])[2] || "(home)";
@@ -28,14 +28,12 @@ const PersonPoster: React.FC = ({
if (from === "(home)" || from === "(search)" || from === "(libraries)")
return (
- router.push(`/(auth)/(tabs)/${from}/jellyseerr/person/${id}`)
- }
+ onPress={() => router.push(`/(auth)/(tabs)/${from}/seerr/person/${id}`)}
>
{name}
{subName && {subName}}
diff --git a/components/jellyseerr/RequestModal.tsx b/components/seerr/RequestModal.tsx
similarity index 89%
rename from components/jellyseerr/RequestModal.tsx
rename to components/seerr/RequestModal.tsx
index 5bc44177..97e04619 100644
--- a/components/jellyseerr/RequestModal.tsx
+++ b/components/seerr/RequestModal.tsx
@@ -12,7 +12,7 @@ import { View, type ViewProps } from "react-native";
import { Button } from "@/components/Button";
import { Text } from "@/components/common/Text";
import { PlatformDropdown } from "@/components/PlatformDropdown";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
+import { useSeerr } from "@/hooks/useSeerr";
import type {
QualityProfile,
RootFolder,
@@ -41,11 +41,11 @@ const RequestModal = forwardRef<
{ id, title, requestBody, type, isAnime = false, onRequested, onDismiss },
ref,
) => {
- const { jellyseerrApi, jellyseerrUser, requestMedia } = useJellyseerr();
+ const { seerrApi, seerrUser, requestMedia } = useSeerr();
const [requestOverrides, setRequestOverrides] = useState({
mediaId: Number(id),
mediaType: type,
- userId: jellyseerrUser?.id,
+ userId: seerrUser?.id,
});
const [qualityProfileOpen, setQualityProfileOpen] = useState(false);
@@ -65,18 +65,17 @@ const RequestModal = forwardRef<
}, [onDismiss]);
const { data: serviceSettings } = useQuery({
- queryKey: ["jellyseerr", "request", type, "service"],
+ queryKey: ["seerr", "request", type, "service"],
queryFn: async () =>
- jellyseerrApi?.service(type === "movie" ? "radarr" : "sonarr"),
- enabled: !!jellyseerrApi && !!jellyseerrUser,
+ seerrApi?.service(type === "movie" ? "radarr" : "sonarr"),
+ enabled: !!seerrApi && !!seerrUser,
refetchOnMount: "always",
});
const { data: users } = useQuery({
- queryKey: ["jellyseerr", "users"],
- queryFn: async () =>
- jellyseerrApi?.user({ take: 1000, sort: "displayname" }),
- enabled: !!jellyseerrApi && !!jellyseerrUser,
+ queryKey: ["seerr", "users"],
+ queryFn: async () => seerrApi?.user({ take: 1000, sort: "displayname" }),
+ enabled: !!seerrApi && !!seerrUser,
refetchOnMount: "always",
});
@@ -87,7 +86,7 @@ const RequestModal = forwardRef<
const { data: defaultServiceDetails } = useQuery({
queryKey: [
- "jellyseerr",
+ "seerr",
"request",
type,
"service",
@@ -99,12 +98,12 @@ const RequestModal = forwardRef<
...prev,
serverId: defaultService?.id,
}));
- return jellyseerrApi?.serviceDetails(
+ return seerrApi?.serviceDetails(
type === "movie" ? "radarr" : "sonarr",
defaultService!.id,
);
},
- enabled: !!jellyseerrApi && !!jellyseerrUser && !!defaultService,
+ enabled: !!seerrApi && !!seerrUser && !!defaultService,
refetchOnMount: "always",
});
@@ -148,9 +147,9 @@ const RequestModal = forwardRef<
return undefined;
}
if (requestBody.seasons.length > 1) {
- return t("jellyseerr.season_all");
+ return t("seerr.season_all");
}
- return t("jellyseerr.season_number", {
+ return t("seerr.season_number", {
season_number: requestBody.seasons[0],
});
}, [requestBody?.seasons]);
@@ -245,8 +244,7 @@ const RequestModal = forwardRef<
type: "radio" as const,
label: user.displayName,
value: user.id.toString(),
- selected:
- (requestOverrides.userId || jellyseerrUser?.id) === user.id,
+ selected: (requestOverrides.userId || seerrUser?.id) === user.id,
onPress: () =>
setRequestOverrides((prev) => ({
...prev,
@@ -255,7 +253,7 @@ const RequestModal = forwardRef<
})) || [],
},
],
- [users, jellyseerrUser, requestOverrides.userId],
+ [users, seerrUser, requestOverrides.userId],
);
const request = useCallback(() => {
@@ -268,7 +266,7 @@ const RequestModal = forwardRef<
...requestOverrides,
};
- writeDebugLog("Sending Jellyseerr advanced request", body);
+ writeDebugLog("Sending Seerr advanced request", body);
requestMedia(
seasonTitle ? `${title}, ${seasonTitle}` : title,
@@ -308,7 +306,7 @@ const RequestModal = forwardRef<
- {t("jellyseerr.advanced")}
+ {t("seerr.advanced")}
{seasonTitle && (
{seasonTitle}
@@ -319,7 +317,7 @@ const RequestModal = forwardRef<
<>
- {t("jellyseerr.quality_profile")}
+ {t("seerr.quality_profile")}
}
- title={t("jellyseerr.quality_profile")}
+ title={t("seerr.quality_profile")}
open={qualityProfileOpen}
onOpenChange={setQualityProfileOpen}
/>
@@ -343,7 +341,7 @@ const RequestModal = forwardRef<
- {t("jellyseerr.root_folder")}
+ {t("seerr.root_folder")}
}
- title={t("jellyseerr.root_folder")}
+ title={t("seerr.root_folder")}
open={rootFolderOpen}
onOpenChange={setRootFolderOpen}
/>
@@ -376,7 +374,7 @@ const RequestModal = forwardRef<
- {t("jellyseerr.tags")}
+ {t("seerr.tags")}
}
- title={t("jellyseerr.tags")}
+ title={t("seerr.tags")}
open={tagsOpen}
onOpenChange={setTagsOpen}
/>
@@ -403,7 +401,7 @@ const RequestModal = forwardRef<
- {t("jellyseerr.request_as")}
+ {t("seerr.request_as")}
u.id ===
- (requestOverrides.userId || jellyseerrUser?.id),
- )?.displayName || jellyseerrUser!.displayName}
+ (requestOverrides.userId || seerrUser?.id),
+ )?.displayName || seerrUser!.displayName}
}
- title={t("jellyseerr.request_as")}
+ title={t("seerr.request_as")}
open={usersOpen}
onOpenChange={setUsersOpen}
/>
@@ -427,7 +425,7 @@ const RequestModal = forwardRef<
)}
diff --git a/components/jellyseerr/JellyseerrIndexPage.tsx b/components/seerr/SeerrIndexPage.tsx
similarity index 65%
rename from components/jellyseerr/JellyseerrIndexPage.tsx
rename to components/seerr/SeerrIndexPage.tsx
index 42fd223b..6ef54fa6 100644
--- a/components/jellyseerr/JellyseerrIndexPage.tsx
+++ b/components/seerr/SeerrIndexPage.tsx
@@ -8,8 +8,8 @@ import {
useSharedValue,
withTiming,
} from "react-native-reanimated";
-import Discover from "@/components/jellyseerr/discover/Discover";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
+import Discover from "@/components/seerr/discover/Discover";
+import { useSeerr } from "@/hooks/useSeerr";
import { MediaType } from "@/utils/jellyseerr/server/constants/media";
import type {
MovieResult,
@@ -18,57 +18,57 @@ import type {
} from "@/utils/jellyseerr/server/models/Search";
import { useReactNavigationQuery } from "@/utils/useReactNavigationQuery";
import { Text } from "../common/Text";
-import JellyseerrPoster from "../posters/JellyseerrPoster";
+import SeerrPoster from "../posters/SeerrPoster";
import { LoadingSkeleton } from "../search/LoadingSkeleton";
import { SearchItemWrapper } from "../search/SearchItemWrapper";
import PersonPoster from "./PersonPoster";
interface Props extends ViewProps {
searchQuery: string;
- sortType?: JellyseerrSearchSort;
+ sortType?: SeerrSearchSort;
order?: "asc" | "desc";
}
-export enum JellyseerrSearchSort {
+export enum SeerrSearchSort {
DEFAULT = 0,
VOTE_COUNT_AND_AVERAGE = 1,
POPULARITY = 2,
}
-export const JellyserrIndexPage: React.FC = ({
+export const SeerrIndexPage: React.FC = ({
searchQuery,
sortType,
order,
}) => {
- const { jellyseerrApi } = useJellyseerr();
+ const { seerrApi } = useSeerr();
const opacity = useSharedValue(1);
const { t } = useTranslation();
const {
- data: jellyseerrDiscoverSettings,
+ data: seerrDiscoverSettings,
isFetching: f1,
isLoading: l1,
} = useReactNavigationQuery({
- queryKey: ["search", "jellyseerr", "discoverSettings", searchQuery],
- queryFn: async () => jellyseerrApi?.discoverSettings(),
- enabled: !!jellyseerrApi && searchQuery.length === 0,
+ queryKey: ["search", "seerr", "discoverSettings", searchQuery],
+ queryFn: async () => seerrApi?.discoverSettings(),
+ enabled: !!seerrApi && searchQuery.length === 0,
});
const {
- data: jellyseerrResults,
+ data: seerrResults,
isFetching: f2,
isLoading: l2,
} = useReactNavigationQuery({
- queryKey: ["search", "jellyseerr", "results", searchQuery],
+ queryKey: ["search", "seerr", "results", searchQuery],
queryFn: async () => {
const params = {
query: new URLSearchParams(searchQuery || "").toString(),
};
return await Promise.all([
- jellyseerrApi?.search({ ...params, page: 1 }),
- jellyseerrApi?.search({ ...params, page: 2 }),
- jellyseerrApi?.search({ ...params, page: 3 }),
- jellyseerrApi?.search({ ...params, page: 4 }),
+ seerrApi?.search({ ...params, page: 1 }),
+ seerrApi?.search({ ...params, page: 2 }),
+ seerrApi?.search({ ...params, page: 3 }),
+ seerrApi?.search({ ...params, page: 4 }),
]).then((all) =>
uniqBy(
all.flatMap((v) => v?.results || []),
@@ -76,7 +76,7 @@ export const JellyserrIndexPage: React.FC = ({
),
);
},
- enabled: !!jellyseerrApi && searchQuery.length > 0,
+ enabled: !!seerrApi && searchQuery.length > 0,
});
useAnimatedReaction(
@@ -92,20 +92,20 @@ export const JellyserrIndexPage: React.FC = ({
const sortingType = useMemo(() => {
if (!sortType) return;
- switch (Number(JellyseerrSearchSort[sortType])) {
- case JellyseerrSearchSort.VOTE_COUNT_AND_AVERAGE:
+ switch (Number(SeerrSearchSort[sortType])) {
+ case SeerrSearchSort.VOTE_COUNT_AND_AVERAGE:
return ["voteCount", "voteAverage"];
- case JellyseerrSearchSort.POPULARITY:
+ case SeerrSearchSort.POPULARITY:
return ["voteCount", "popularity"];
default:
return undefined;
}
}, [sortType, order]);
- const jellyseerrMovieResults = useMemo(
+ const seerrMovieResults = useMemo(
() =>
orderBy(
- jellyseerrResults?.filter(
+ seerrResults?.filter(
(r) => r.mediaType === MediaType.MOVIE,
) as MovieResult[],
sortingType || [
@@ -113,41 +113,37 @@ export const JellyserrIndexPage: React.FC = ({
],
order || "desc",
),
- [jellyseerrResults, sortingType, order],
+ [seerrResults, sortingType, order],
);
- const jellyseerrTvResults = useMemo(
+ const seerrTvResults = useMemo(
() =>
orderBy(
- jellyseerrResults?.filter(
- (r) => r.mediaType === MediaType.TV,
- ) as TvResult[],
+ seerrResults?.filter((r) => r.mediaType === MediaType.TV) as TvResult[],
sortingType || [
(t) => t.name.toLowerCase() === searchQuery.toLowerCase(),
],
order || "desc",
),
- [jellyseerrResults, sortingType, order],
+ [seerrResults, sortingType, order],
);
- const jellyseerrPersonResults = useMemo(
+ const seerrPersonResults = useMemo(
() =>
orderBy(
- jellyseerrResults?.filter(
- (r) => r.mediaType === "person",
- ) as PersonResult[],
+ seerrResults?.filter((r) => r.mediaType === "person") as PersonResult[],
sortingType || [
(p) => p.name.toLowerCase() === searchQuery.toLowerCase(),
],
order || "desc",
),
- [jellyseerrResults, sortingType, order],
+ [seerrResults, sortingType, order],
);
if (!searchQuery.length)
return (
-
+
);
@@ -155,9 +151,9 @@ export const JellyserrIndexPage: React.FC = ({
- {!jellyseerrMovieResults?.length &&
- !jellyseerrTvResults?.length &&
- !jellyseerrPersonResults?.length &&
+ {!seerrMovieResults?.length &&
+ !seerrTvResults?.length &&
+ !seerrPersonResults?.length &&
!f1 &&
!f2 &&
!l1 &&
@@ -175,21 +171,21 @@ export const JellyserrIndexPage: React.FC = ({
(
-
+
)}
/>
(
-
+
)}
/>
(
= ({ mediaType, className, ...props }) => {
+const SeerrMediaIcon: React.FC<{ mediaType: "tv" | "movie" } & ViewProps> = ({
+ mediaType,
+ className,
+ ...props
+}) => {
const style = useMemo(
() =>
mediaType === MediaType.MOVIE
@@ -29,4 +31,4 @@ const JellyseerrMediaIcon: React.FC<
);
};
-export default JellyseerrMediaIcon;
+export default SeerrMediaIcon;
diff --git a/components/jellyseerr/JellyseerrStatusIcon.tsx b/components/seerr/SeerrStatusIcon.tsx
similarity index 96%
rename from components/jellyseerr/JellyseerrStatusIcon.tsx
rename to components/seerr/SeerrStatusIcon.tsx
index e9b37af5..414fea62 100644
--- a/components/jellyseerr/JellyseerrStatusIcon.tsx
+++ b/components/seerr/SeerrStatusIcon.tsx
@@ -9,7 +9,7 @@ interface Props {
onPress?: () => void;
}
-const JellyseerrStatusIcon: React.FC = ({
+const SeerrStatusIcon: React.FC = ({
mediaStatus,
showRequestIcon,
onPress,
@@ -74,4 +74,4 @@ const JellyseerrStatusIcon: React.FC = ({
);
};
-export default JellyseerrStatusIcon;
+export default SeerrStatusIcon;
diff --git a/components/jellyseerr/discover/CompanySlide.tsx b/components/seerr/discover/CompanySlide.tsx
similarity index 74%
rename from components/jellyseerr/discover/CompanySlide.tsx
rename to components/seerr/discover/CompanySlide.tsx
index abba1d31..58e614fa 100644
--- a/components/jellyseerr/discover/CompanySlide.tsx
+++ b/components/seerr/discover/CompanySlide.tsx
@@ -2,10 +2,10 @@ import { useSegments } from "expo-router";
import type React from "react";
import { useCallback } from "react";
import { TouchableOpacity, type ViewProps } from "react-native";
-import GenericSlideCard from "@/components/jellyseerr/discover/GenericSlideCard";
-import Slide, { type SlideProps } from "@/components/jellyseerr/discover/Slide";
+import GenericSlideCard from "@/components/seerr/discover/GenericSlideCard";
+import Slide, { type SlideProps } from "@/components/seerr/discover/Slide";
import useRouter from "@/hooks/useAppRouter";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
+import { useSeerr } from "@/hooks/useSeerr";
import {
COMPANY_LOGO_IMAGE_FILTER,
type Network,
@@ -16,14 +16,14 @@ const CompanySlide: React.FC<
{ data: Network[] | Studio[] } & SlideProps & ViewProps
> = ({ slide, data, ...props }) => {
const segments = useSegments();
- const { jellyseerrApi } = useJellyseerr();
+ const { seerrApi } = useSeerr();
const router = useRouter();
const from = (segments as string[])[2] || "(home)";
const navigate = useCallback(
({ id, image, name }: Network | Studio) =>
router.push({
- pathname: `/(auth)/(tabs)/${from}/jellyseerr/company/${id}` as any,
+ pathname: `/(auth)/(tabs)/${from}/seerr/company/${id}` as any,
params: { id, image, name, type: slide.type },
}),
[slide],
@@ -40,10 +40,7 @@ const CompanySlide: React.FC<
)}
diff --git a/components/jellyseerr/discover/Discover.tsx b/components/seerr/discover/Discover.tsx
similarity index 87%
rename from components/jellyseerr/discover/Discover.tsx
rename to components/seerr/discover/Discover.tsx
index 67e5bf3c..7a926eec 100644
--- a/components/jellyseerr/discover/Discover.tsx
+++ b/components/seerr/discover/Discover.tsx
@@ -2,10 +2,10 @@ import { sortBy } from "lodash";
import type React from "react";
import { useMemo } from "react";
import { View } from "react-native";
-import CompanySlide from "@/components/jellyseerr/discover/CompanySlide";
-import GenreSlide from "@/components/jellyseerr/discover/GenreSlide";
-import MovieTvSlide from "@/components/jellyseerr/discover/MovieTvSlide";
-import RecentRequestsSlide from "@/components/jellyseerr/discover/RecentRequestsSlide";
+import CompanySlide from "@/components/seerr/discover/CompanySlide";
+import GenreSlide from "@/components/seerr/discover/GenreSlide";
+import MovieTvSlide from "@/components/seerr/discover/MovieTvSlide";
+import RecentRequestsSlide from "@/components/seerr/discover/RecentRequestsSlide";
import { DiscoverSliderType } from "@/utils/jellyseerr/server/constants/discover";
import type DiscoverSlider from "@/utils/jellyseerr/server/entity/DiscoverSlider";
import { networks } from "@/utils/jellyseerr/src/components/Discover/NetworkSlider";
diff --git a/components/jellyseerr/discover/GenericSlideCard.tsx b/components/seerr/discover/GenericSlideCard.tsx
similarity index 100%
rename from components/jellyseerr/discover/GenericSlideCard.tsx
rename to components/seerr/discover/GenericSlideCard.tsx
diff --git a/components/jellyseerr/discover/GenreSlide.tsx b/components/seerr/discover/GenreSlide.tsx
similarity index 78%
rename from components/jellyseerr/discover/GenreSlide.tsx
rename to components/seerr/discover/GenreSlide.tsx
index 31248540..e65534d0 100644
--- a/components/jellyseerr/discover/GenreSlide.tsx
+++ b/components/seerr/discover/GenreSlide.tsx
@@ -3,39 +3,39 @@ import { useSegments } from "expo-router";
import type React from "react";
import { useCallback } from "react";
import { TouchableOpacity, type ViewProps } from "react-native";
-import GenericSlideCard from "@/components/jellyseerr/discover/GenericSlideCard";
-import Slide, { type SlideProps } from "@/components/jellyseerr/discover/Slide";
+import GenericSlideCard from "@/components/seerr/discover/GenericSlideCard";
+import Slide, { type SlideProps } from "@/components/seerr/discover/Slide";
import useRouter from "@/hooks/useAppRouter";
-import { Endpoints, useJellyseerr } from "@/hooks/useJellyseerr";
+import { Endpoints, useSeerr } from "@/hooks/useSeerr";
import { DiscoverSliderType } from "@/utils/jellyseerr/server/constants/discover";
import type { GenreSliderItem } from "@/utils/jellyseerr/server/interfaces/api/discoverInterfaces";
import { genreColorMap } from "@/utils/jellyseerr/src/components/Discover/constants";
const GenreSlide: React.FC = ({ slide, ...props }) => {
const segments = useSegments();
- const { jellyseerrApi } = useJellyseerr();
+ const { seerrApi } = useSeerr();
const router = useRouter();
const from = (segments as string[])[2] || "(home)";
const navigate = useCallback(
(genre: GenreSliderItem) =>
router.push({
- pathname: `/(auth)/(tabs)/${from}/jellyseerr/genre/${genre.id}` as any,
+ pathname: `/(auth)/(tabs)/${from}/seerr/genre/${genre.id}` as any,
params: { type: slide.type, name: genre.name },
}),
[slide],
);
const { data } = useQuery({
- queryKey: ["jellyseerr", "discover", slide.type, slide.id],
+ queryKey: ["seerr", "discover", slide.type, slide.id],
queryFn: async () => {
- return jellyseerrApi?.getGenreSliders(
+ return seerrApi?.getGenreSliders(
slide.type === DiscoverSliderType.MOVIE_GENRES
? Endpoints.MOVIE
: Endpoints.TV,
);
},
- enabled: !!jellyseerrApi,
+ enabled: !!seerrApi,
});
return (
@@ -53,7 +53,7 @@ const GenreSlide: React.FC = ({ slide, ...props }) => {
title={item.name}
colors={["transparent", "transparent"]}
contentFit={"cover"}
- url={jellyseerrApi?.imageProxy(
+ url={seerrApi?.imageProxy(
item.backdrops?.[0],
`w780_filter(duotone,${
genreColorMap[item.id] ?? genreColorMap[0]
diff --git a/components/jellyseerr/discover/MovieTvSlide.tsx b/components/seerr/discover/MovieTvSlide.tsx
similarity index 76%
rename from components/jellyseerr/discover/MovieTvSlide.tsx
rename to components/seerr/discover/MovieTvSlide.tsx
index a82f48a3..6291bab1 100644
--- a/components/jellyseerr/discover/MovieTvSlide.tsx
+++ b/components/seerr/discover/MovieTvSlide.tsx
@@ -3,23 +3,19 @@ import { uniqBy } from "lodash";
import type React from "react";
import { useMemo } from "react";
import type { ViewProps } from "react-native";
-import Slide, { type SlideProps } from "@/components/jellyseerr/discover/Slide";
-import JellyseerrPoster from "@/components/posters/JellyseerrPoster";
-import {
- type DiscoverEndpoint,
- Endpoints,
- useJellyseerr,
-} from "@/hooks/useJellyseerr";
+import SeerrPoster from "@/components/posters/SeerrPoster";
+import Slide, { type SlideProps } from "@/components/seerr/discover/Slide";
+import { type DiscoverEndpoint, Endpoints, useSeerr } from "@/hooks/useSeerr";
import { DiscoverSliderType } from "@/utils/jellyseerr/server/constants/discover";
const MovieTvSlide: React.FC = ({
slide,
...props
}) => {
- const { jellyseerrApi, isJellyseerrMovieOrTvResult } = useJellyseerr();
+ const { seerrApi, isSeerrMovieOrTvResult } = useSeerr();
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
- queryKey: ["jellyseerr", "discover", slide.id],
+ queryKey: ["seerr", "discover", slide.id],
queryFn: async ({ pageParam }) => {
let endpoint: DiscoverEndpoint | undefined;
let params: any = {
@@ -50,13 +46,13 @@ const MovieTvSlide: React.FC = ({
break;
}
- return endpoint ? jellyseerrApi?.discover(endpoint, params) : null;
+ return endpoint ? seerrApi?.discover(endpoint, params) : null;
},
initialPageParam: 1,
getNextPageParam: (lastPage, pages) =>
(lastPage?.page || pages?.findLast((p) => p?.results.length)?.page || 1) +
1,
- enabled: !!jellyseerrApi,
+ enabled: !!seerrApi,
staleTime: 0,
});
@@ -65,9 +61,7 @@ const MovieTvSlide: React.FC = ({
uniqBy(
data?.pages
?.filter((p) => p?.results.length)
- .flatMap((p) =>
- p?.results.filter((r) => isJellyseerrMovieOrTvResult(r)),
- ),
+ .flatMap((p) => p?.results.filter((r) => isSeerrMovieOrTvResult(r))),
"id",
),
[data],
@@ -84,7 +78,7 @@ const MovieTvSlide: React.FC = ({
onEndReached={() => {
if (hasNextPage) fetchNextPage();
}}
- renderItem={(item) => }
+ renderItem={(item) => }
/>
)
);
diff --git a/components/jellyseerr/discover/RecentRequestsSlide.tsx b/components/seerr/discover/RecentRequestsSlide.tsx
similarity index 70%
rename from components/jellyseerr/discover/RecentRequestsSlide.tsx
rename to components/seerr/discover/RecentRequestsSlide.tsx
index 71b5fc21..12cdef40 100644
--- a/components/jellyseerr/discover/RecentRequestsSlide.tsx
+++ b/components/seerr/discover/RecentRequestsSlide.tsx
@@ -1,9 +1,9 @@
import { useQuery } from "@tanstack/react-query";
import type React from "react";
import type { ViewProps } from "react-native";
-import Slide, { type SlideProps } from "@/components/jellyseerr/discover/Slide";
-import JellyseerrPoster from "@/components/posters/JellyseerrPoster";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
+import SeerrPoster from "@/components/posters/SeerrPoster";
+import Slide, { type SlideProps } from "@/components/seerr/discover/Slide";
+import { useSeerr } from "@/hooks/useSeerr";
import { MediaType } from "@/utils/jellyseerr/server/constants/media";
import type MediaRequest from "@/utils/jellyseerr/server/entity/MediaRequest";
import type { NonFunctionProperties } from "@/utils/jellyseerr/server/interfaces/api/common";
@@ -16,36 +16,36 @@ type ExtendedMediaRequest = NonFunctionProperties & {
const RequestCard: React.FC<{ request: ExtendedMediaRequest }> = ({
request,
}) => {
- const { jellyseerrApi } = useJellyseerr();
+ const { seerrApi } = useSeerr();
const { data: details } = useQuery({
queryKey: [
- "jellyseerr",
+ "seerr",
"detail",
request.media.mediaType,
request.media.tmdbId,
],
queryFn: async () => {
return request.media.mediaType === MediaType.MOVIE
- ? jellyseerrApi?.movieDetails(request.media.tmdbId)
- : jellyseerrApi?.tvDetails(request.media.tmdbId);
+ ? seerrApi?.movieDetails(request.media.tmdbId)
+ : seerrApi?.tvDetails(request.media.tmdbId);
},
- enabled: !!jellyseerrApi,
+ enabled: !!seerrApi,
refetchOnMount: true,
staleTime: 0,
});
const { data: refreshedRequest } = useQuery({
- queryKey: ["jellyseerr", "requests", request.media.mediaType, request.id],
- queryFn: async () => jellyseerrApi?.getRequest(request.id),
- enabled: !!jellyseerrApi,
+ queryKey: ["seerr", "requests", request.media.mediaType, request.id],
+ queryFn: async () => seerrApi?.getRequest(request.id),
+ enabled: !!seerrApi,
refetchOnMount: true,
refetchInterval: 5000,
staleTime: 0,
});
return (
- = ({
slide,
...props
}) => {
- const { jellyseerrApi } = useJellyseerr();
+ const { seerrApi } = useSeerr();
const { data: requests } = useQuery({
- queryKey: ["jellyseerr", "recent_requests"],
- queryFn: async () => jellyseerrApi?.requests(),
- enabled: !!jellyseerrApi,
+ queryKey: ["seerr", "recent_requests"],
+ queryFn: async () => seerrApi?.requests(),
+ enabled: !!seerrApi,
refetchOnMount: true,
staleTime: 0,
});
diff --git a/components/jellyseerr/discover/Slide.tsx b/components/seerr/discover/Slide.tsx
similarity index 100%
rename from components/jellyseerr/discover/Slide.tsx
rename to components/seerr/discover/Slide.tsx
diff --git a/components/series/JellyseerrSeasons.tsx b/components/series/SeerrSeasons.tsx
similarity index 88%
rename from components/series/JellyseerrSeasons.tsx
rename to components/series/SeerrSeasons.tsx
index 3b130683..ff1f0b6d 100644
--- a/components/series/JellyseerrSeasons.tsx
+++ b/components/series/SeerrSeasons.tsx
@@ -14,11 +14,11 @@ import { Alert, TouchableOpacity, View } from "react-native";
import { HorizontalScroll } from "@/components/common/HorizontalScroll";
import { Text } from "@/components/common/Text";
import { Tags } from "@/components/GenreTags";
-import { dateOpts } from "@/components/jellyseerr/DetailFacts";
-import { textShadowStyle } from "@/components/jellyseerr/discover/GenericSlideCard";
-import JellyseerrStatusIcon from "@/components/jellyseerr/JellyseerrStatusIcon";
import { RoundButton } from "@/components/RoundButton";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
+import { dateOpts } from "@/components/seerr/DetailFacts";
+import { textShadowStyle } from "@/components/seerr/discover/GenericSlideCard";
+import SeerrStatusIcon from "@/components/seerr/SeerrStatusIcon";
+import { useSeerr } from "@/hooks/useSeerr";
import {
MediaStatus,
MediaType,
@@ -30,15 +30,15 @@ import type { MovieDetails } from "@/utils/jellyseerr/server/models/Movie";
import type { TvDetails } from "@/utils/jellyseerr/server/models/Tv";
import { Loader } from "../Loader";
-const JellyseerrSeasonEpisodes: React.FC<{
+const SeerrSeasonEpisodes: React.FC<{
details: TvDetails;
seasonNumber: number;
}> = ({ details, seasonNumber }) => {
- const { jellyseerrApi } = useJellyseerr();
+ const { seerrApi } = useSeerr();
const { data: seasonWithEpisodes, isLoading } = useQuery({
- queryKey: ["jellyseerr", details.id, "season", seasonNumber],
- queryFn: async () => jellyseerrApi?.tvSeason(details.id, seasonNumber),
+ queryKey: ["seerr", details.id, "season", seasonNumber],
+ queryFn: async () => seerrApi?.tvSeason(details.id, seasonNumber),
enabled: details.seasons.filter((s) => s.seasonNumber !== 0).length > 0,
});
@@ -57,11 +57,7 @@ const JellyseerrSeasonEpisodes: React.FC<{
};
const RenderItem = ({ item }: any) => {
- const {
- jellyseerrApi,
- jellyseerrRegion: region,
- jellyseerrLocale: locale,
- } = useJellyseerr();
+ const { seerrApi, seerrRegion: region, seerrLocale: locale } = useSeerr();
const [imageError, setImageError] = useState(false);
const upcomingAirDate = useMemo(() => {
@@ -83,7 +79,7 @@ const RenderItem = ({ item }: any) => {
key={item.id}
id={item.id}
source={{
- uri: jellyseerrApi?.imageProxy(item.stillPath),
+ uri: seerrApi?.imageProxy(item.stillPath),
}}
cachePolicy={"memory-disk"}
contentFit='cover'
@@ -131,7 +127,7 @@ const RenderItem = ({ item }: any) => {
);
};
-const JellyseerrSeasons: React.FC<{
+const SeerrSeasons: React.FC<{
isLoading: boolean;
details?: TvDetails;
hasAdvancedRequest?: boolean;
@@ -148,7 +144,7 @@ const JellyseerrSeasons: React.FC<{
hasAdvancedRequest,
onAdvancedRequest,
}) => {
- const { jellyseerrApi, requestMedia } = useJellyseerr();
+ const { seerrApi, requestMedia } = useSeerr();
const [seasonStates, setSeasonStates] = useState<{ [key: number]: boolean }>(
{},
);
@@ -181,7 +177,7 @@ const JellyseerrSeasons: React.FC<{
);
const requestAll = useCallback(() => {
- if (details && jellyseerrApi) {
+ if (details && seerrApi) {
const body: MediaRequestBody = {
mediaId: details.id,
mediaType: MediaType.TV,
@@ -198,7 +194,7 @@ const JellyseerrSeasons: React.FC<{
requestMedia(details.name, body, refetch);
}
}, [
- jellyseerrApi,
+ seerrApi,
seasons,
details,
hasAdvancedRequest,
@@ -210,15 +206,15 @@ const JellyseerrSeasons: React.FC<{
const promptRequestAll = useCallback(
() =>
Alert.alert(
- t("jellyseerr.confirm"),
- t("jellyseerr.are_you_sure_you_want_to_request_all_seasons"),
+ t("seerr.confirm"),
+ t("seerr.are_you_sure_you_want_to_request_all_seasons"),
[
{
- text: t("jellyseerr.cancel"),
+ text: t("seerr.cancel"),
style: "cancel",
},
{
- text: t("jellyseerr.yes"),
+ text: t("seerr.yes"),
onPress: requestAll,
},
],
@@ -301,10 +297,10 @@ const JellyseerrSeasons: React.FC<{
{
const canRequest = season.status === MediaStatus.UNKNOWN;
return (
-
requestSeason(canRequest, season.seasonNumber)
@@ -326,7 +322,7 @@ const JellyseerrSeasons: React.FC<{
{seasonStates?.[season.seasonNumber] && (
- {
- const { jellyseerrUser, setJellyseerrUser, clearAllJellyseerData } =
- useJellyseerr();
-
- const { t } = useTranslation();
-
- const [user] = useAtom(userAtom);
- const { settings, updateSettings } = useSettings();
-
- const [jellyseerrPassword, setJellyseerrPassword] = useState<
- string | undefined
- >(undefined);
-
- const [jellyseerrServerUrl, setjellyseerrServerUrl] = useState<
- string | undefined
- >(settings?.jellyseerrServerUrl || undefined);
-
- const loginToJellyseerrMutation = useMutation({
- mutationFn: async () => {
- if (!jellyseerrServerUrl && !settings?.jellyseerrServerUrl)
- throw new Error("Missing server url");
- if (!user?.Name)
- throw new Error("Missing required information for login");
- const jellyseerrTempApi = new JellyseerrApi(
- jellyseerrServerUrl || settings.jellyseerrServerUrl || "",
- );
- const testResult = await jellyseerrTempApi.test();
- if (!testResult.isValid) throw new Error("Invalid server url");
- return jellyseerrTempApi.login(user.Name, jellyseerrPassword || "");
- },
- onSuccess: (user) => {
- setJellyseerrUser(user);
- updateSettings({ jellyseerrServerUrl });
- },
- onError: () => {
- toast.error(t("jellyseerr.failed_to_login"));
- },
- onSettled: () => {
- setJellyseerrPassword(undefined);
- },
- });
-
- const clearData = () => {
- clearAllJellyseerData().finally(() => {
- setJellyseerrUser(undefined);
- setJellyseerrPassword(undefined);
- setjellyseerrServerUrl(undefined);
- });
- };
-
- return (
-
-
- {jellyseerrUser ? (
- <>
-
-
-
-
-
-
-
-
-
-
-
- >
- ) : (
-
-
- {t("home.settings.plugins.jellyseerr.jellyseerr_warning")}
-
-
- {t("home.settings.plugins.jellyseerr.server_url")}
-
-
-
- {t("home.settings.plugins.jellyseerr.server_url_hint")}
-
-
-
-
-
- {t("home.settings.plugins.jellyseerr.password")}
-
-
-
-
-
- )}
-
-
- );
-};
diff --git a/components/settings/PluginSettings.tsx b/components/settings/PluginSettings.tsx
index 1b21cf98..e6a6d310 100644
--- a/components/settings/PluginSettings.tsx
+++ b/components/settings/PluginSettings.tsx
@@ -19,7 +19,7 @@ export const PluginSettings = () => {
className='mb-4'
>
router.push("/settings/plugins/jellyseerr/page")}
+ onPress={() => router.push("/settings/plugins/seerr/page")}
title={"Seerr"}
showArrow
/>
diff --git a/components/settings/Seerr.tsx b/components/settings/Seerr.tsx
new file mode 100644
index 00000000..1ad87e7f
--- /dev/null
+++ b/components/settings/Seerr.tsx
@@ -0,0 +1,174 @@
+import { useMutation } from "@tanstack/react-query";
+import { useAtom } from "jotai";
+import { useState } from "react";
+import { useTranslation } from "react-i18next";
+import { View } from "react-native";
+import { toast } from "sonner-native";
+import { SeerrApi, useSeerr } from "@/hooks/useSeerr";
+import { userAtom } from "@/providers/JellyfinProvider";
+import { useSettings } from "@/utils/atoms/settings";
+import { Button } from "../Button";
+import { Input } from "../common/Input";
+import { Text } from "../common/Text";
+import { ListGroup } from "../list/ListGroup";
+import { ListItem } from "../list/ListItem";
+
+export const SeerrSettings = () => {
+ const { seerrUser, setSeerrUser, clearAllSeerrData } = useSeerr();
+
+ const { t } = useTranslation();
+
+ const [user] = useAtom(userAtom);
+ const { settings, updateSettings } = useSettings();
+
+ const [seerrPassword, setSeerrPassword] = useState(
+ undefined,
+ );
+
+ const [seerrServerUrl, setSeerrServerUrl] = useState(
+ settings?.seerrServerUrl || undefined,
+ );
+
+ const loginToSeerrMutation = useMutation({
+ mutationFn: async () => {
+ if (!seerrServerUrl && !settings?.seerrServerUrl)
+ throw new Error("Missing server url");
+ if (!user?.Name)
+ throw new Error("Missing required information for login");
+ const seerrTempApi = new SeerrApi(
+ seerrServerUrl || settings.seerrServerUrl || "",
+ );
+ const testResult = await seerrTempApi.test();
+ if (!testResult.isValid) throw new Error("Invalid server url");
+ return seerrTempApi.login(user.Name, seerrPassword || "");
+ },
+ onSuccess: (user) => {
+ setSeerrUser(user);
+ updateSettings({ seerrServerUrl });
+ },
+ onError: () => {
+ toast.error(t("seerr.failed_to_login"));
+ },
+ onSettled: () => {
+ setSeerrPassword(undefined);
+ },
+ });
+
+ const clearData = () => {
+ clearAllSeerrData().finally(() => {
+ setSeerrUser(undefined);
+ setSeerrPassword(undefined);
+ setSeerrServerUrl(undefined);
+ });
+ };
+
+ return (
+
+
+ {seerrUser ? (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+ >
+ ) : (
+
+
+ {t("home.settings.plugins.seerr.seerr_warning")}
+
+
+ {t("home.settings.plugins.seerr.server_url")}
+
+
+
+ {t("home.settings.plugins.seerr.server_url_hint")}
+
+
+
+
+
+ {t("home.settings.plugins.seerr.password")}
+
+
+
+
+
+ )}
+
+
+ );
+};
diff --git a/hooks/useJellyseerr.ts b/hooks/useSeerr.ts
similarity index 82%
rename from hooks/useJellyseerr.ts
rename to hooks/useSeerr.ts
index d1d511fb..55a242a9 100644
--- a/hooks/useJellyseerr.ts
+++ b/hooks/useSeerr.ts
@@ -2,7 +2,7 @@ import axios, { type AxiosError, type AxiosInstance } from "axios";
import { atom } from "jotai";
import { useAtom } from "jotai/index";
import { inRange } from "lodash";
-import type { User as JellyseerrUser } from "@/utils/jellyseerr/server/entity/User";
+import type { User as SeerrUser } from "@/utils/jellyseerr/server/entity/User";
import type {
MovieResult,
Results,
@@ -62,12 +62,12 @@ interface SearchResults {
results: Results[];
}
-const JELLYSEERR_USER = "JELLYSEERR_USER";
-const JELLYSEERR_COOKIES = "JELLYSEERR_COOKIES";
+const SEERR_USER = "SEERR_USER";
+const SEERR_COOKIES = "SEERR_COOKIES";
-export const clearJellyseerrStorageData = () => {
- storage.remove(JELLYSEERR_USER);
- storage.remove(JELLYSEERR_COOKIES);
+export const clearSeerrStorageData = () => {
+ storage.remove(SEERR_USER);
+ storage.remove(SEERR_COOKIES);
};
export enum Endpoints {
@@ -111,7 +111,7 @@ export type TestResult =
isValid: false;
};
-export class JellyseerrApi {
+export class SeerrApi {
axios: AxiosInstance;
constructor(baseUrl: string) {
@@ -126,8 +126,8 @@ export class JellyseerrApi {
}
async test(): Promise {
- const user = storage.get(JELLYSEERR_USER);
- const cookies = storage.get(JELLYSEERR_COOKIES);
+ const user = storage.get(SEERR_USER);
+ const cookies = storage.get(SEERR_COOKIES);
if (user && cookies) {
return Promise.resolve({
@@ -142,15 +142,13 @@ export class JellyseerrApi {
const { status, headers, data } = response;
if (inRange(status, 200, 299)) {
if (data.version < "2.0.0") {
- const error = t(
- "jellyseerr.toasts.jellyseer_does_not_meet_requirements",
- );
+ const error = t("seerr.toasts.seer_does_not_meet_requirements");
toast.error(error);
throw Error(error);
}
storage.setAny(
- JELLYSEERR_COOKIES,
+ SEERR_COOKIES,
headers["set-cookie"]?.flatMap((c) => c.split("; ")) ?? [],
);
return {
@@ -158,7 +156,7 @@ export class JellyseerrApi {
requiresPass: true,
};
}
- toast.error(t("jellyseerr.toasts.jellyseerr_test_failed"));
+ toast.error(t("seerr.toasts.seerr_test_failed"));
writeErrorLog(
`Seerr returned a ${status} for url:\n${response.config.url}`,
response.data,
@@ -169,7 +167,7 @@ export class JellyseerrApi {
};
})
.catch((e) => {
- const msg = t("jellyseerr.toasts.failed_to_test_jellyseerr_server_url");
+ const msg = t("seerr.toasts.failed_to_test_seerr_server_url");
toast.error(msg);
console.error(msg, e);
return {
@@ -179,9 +177,9 @@ export class JellyseerrApi {
});
}
- async login(username: string, password: string): Promise {
+ async login(username: string, password: string): Promise {
return this.axios
- ?.post(Endpoints.API_V1 + Endpoints.AUTH_JELLYFIN, {
+ ?.post(Endpoints.API_V1 + Endpoints.AUTH_JELLYFIN, {
username,
password,
email: username,
@@ -189,7 +187,7 @@ export class JellyseerrApi {
.then((response) => {
const user = response?.data;
if (!user) throw Error("Login failed");
- storage.setAny(JELLYSEERR_USER, user);
+ storage.setAny(SEERR_USER, user);
return user;
});
}
@@ -364,7 +362,7 @@ export class JellyseerrApi {
const issue = response.data;
if (issue.status === IssueStatus.OPEN) {
- toast.success(t("jellyseerr.toasts.issue_submitted"));
+ toast.success(t("seerr.toasts.issue_submitted"));
}
return issue;
});
@@ -392,7 +390,7 @@ export class JellyseerrApi {
const cookies = response.headers["set-cookie"];
if (cookies) {
storage.setAny(
- JELLYSEERR_COOKIES,
+ SEERR_COOKIES,
response.headers["set-cookie"]?.flatMap((c) => c.split("; ")),
);
}
@@ -404,7 +402,7 @@ export class JellyseerrApi {
error.response?.data,
);
if (error.response?.status === 403) {
- clearJellyseerrStorageData();
+ clearSeerrStorageData();
}
return Promise.reject(error);
},
@@ -412,7 +410,7 @@ export class JellyseerrApi {
this.axios.interceptors.request.use(
async (config) => {
- const cookies = storage.get(JELLYSEERR_COOKIES);
+ const cookies = storage.get(SEERR_COOKIES);
if (cookies) {
const headerName = this.axios.defaults.xsrfHeaderName!;
const xsrfToken = cookies
@@ -431,59 +429,55 @@ export class JellyseerrApi {
}
}
-const jellyseerrUserAtom = atom(storage.get(JELLYSEERR_USER));
+const seerrUserAtom = atom(storage.get(SEERR_USER));
-export const useJellyseerr = () => {
+export const useSeerr = () => {
const { settings, updateSettings } = useSettings();
- const [jellyseerrUser, setJellyseerrUser] = useAtom(jellyseerrUserAtom);
+ const [seerrUser, setSeerrUser] = useAtom(seerrUserAtom);
const queryClient = useNetworkAwareQueryClient();
- const jellyseerrApi = useMemo(() => {
- const cookies = storage.get(JELLYSEERR_COOKIES);
- if (settings?.jellyseerrServerUrl && cookies && jellyseerrUser) {
- return new JellyseerrApi(settings?.jellyseerrServerUrl);
+ const seerrApi = useMemo(() => {
+ const cookies = storage.get(SEERR_COOKIES);
+ if (settings?.seerrServerUrl && cookies && seerrUser) {
+ return new SeerrApi(settings?.seerrServerUrl);
}
return undefined;
- }, [settings?.jellyseerrServerUrl, jellyseerrUser]);
+ }, [settings?.seerrServerUrl, seerrUser]);
- const clearAllJellyseerData = useCallback(async () => {
- clearJellyseerrStorageData();
- setJellyseerrUser(undefined);
- updateSettings({ jellyseerrServerUrl: undefined });
+ const clearAllSeerrData = useCallback(async () => {
+ clearSeerrStorageData();
+ setSeerrUser(undefined);
+ updateSettings({ seerrServerUrl: undefined });
}, []);
const requestMedia = useCallback(
(title: string, request: MediaRequestBody, onSuccess?: () => void) => {
- jellyseerrApi?.request?.(request)?.then(async (mediaRequest) => {
+ seerrApi?.request?.(request)?.then(async (mediaRequest) => {
await queryClient.invalidateQueries({
- queryKey: ["search", "jellyseerr"],
+ queryKey: ["search", "seerr"],
});
switch (mediaRequest.status) {
case MediaRequestStatus.PENDING:
case MediaRequestStatus.APPROVED:
- toast.success(
- t("jellyseerr.toasts.requested_item", { item: title }),
- );
+ toast.success(t("seerr.toasts.requested_item", { item: title }));
onSuccess?.();
break;
case MediaRequestStatus.DECLINED:
- toast.error(
- t("jellyseerr.toasts.you_dont_have_permission_to_request"),
- );
+ toast.error(t("seerr.toasts.you_dont_have_permission_to_request"));
break;
case MediaRequestStatus.FAILED:
toast.error(
- t("jellyseerr.toasts.something_went_wrong_requesting_media"),
+ t("seerr.toasts.something_went_wrong_requesting_media"),
);
break;
}
});
},
- [jellyseerrApi],
+ [seerrApi],
);
- const isJellyseerrMovieOrTvResult = (
+ const isSeerrMovieOrTvResult = (
items: any | null | undefined,
): items is MovieResult | TvResult => {
return (
@@ -496,7 +490,7 @@ export const useJellyseerr = () => {
const getTitle = (
item?: TvResult | TvDetails | MovieResult | MovieDetails | PersonCreditCast,
) => {
- return isJellyseerrMovieOrTvResult(item)
+ return isSeerrMovieOrTvResult(item)
? item.mediaType === MediaType.MOVIE
? item?.title
: item?.name
@@ -509,7 +503,7 @@ export const useJellyseerr = () => {
item?: TvResult | TvDetails | MovieResult | MovieDetails | PersonCreditCast,
) => {
return new Date(
- (isJellyseerrMovieOrTvResult(item)
+ (isSeerrMovieOrTvResult(item)
? item.mediaType === MediaType.MOVIE
? item?.releaseDate
: item?.firstAirDate
@@ -522,32 +516,32 @@ export const useJellyseerr = () => {
const getMediaType = (
item?: TvResult | TvDetails | MovieResult | MovieDetails | PersonCreditCast,
): MediaType => {
- return isJellyseerrMovieOrTvResult(item)
+ return isSeerrMovieOrTvResult(item)
? (item.mediaType as MediaType)
: item?.mediaInfo?.mediaType;
};
- const jellyseerrRegion = useMemo(
+ const seerrRegion = useMemo(
// streamingRegion and discoverRegion exists. region doesn't
- () => jellyseerrUser?.settings?.discoverRegion || "US",
- [jellyseerrUser],
+ () => seerrUser?.settings?.discoverRegion || "US",
+ [seerrUser],
);
- const jellyseerrLocale = useMemo(() => {
- return jellyseerrUser?.settings?.locale || "en";
- }, [jellyseerrUser]);
+ const seerrLocale = useMemo(() => {
+ return seerrUser?.settings?.locale || "en";
+ }, [seerrUser]);
return {
- jellyseerrApi,
- jellyseerrUser,
- setJellyseerrUser,
- clearAllJellyseerData,
- isJellyseerrMovieOrTvResult,
+ seerrApi,
+ seerrUser,
+ setSeerrUser,
+ clearAllSeerrData,
+ isSeerrMovieOrTvResult,
getTitle,
getYear,
getMediaType,
- jellyseerrRegion,
- jellyseerrLocale,
+ seerrRegion,
+ seerrLocale,
requestMedia,
};
};
diff --git a/providers/JellyfinProvider.tsx b/providers/JellyfinProvider.tsx
index da75dcd1..616e5d4e 100644
--- a/providers/JellyfinProvider.tsx
+++ b/providers/JellyfinProvider.tsx
@@ -23,7 +23,7 @@ import { getDeviceName } from "react-native-device-info";
import uuid from "react-native-uuid";
import useRouter from "@/hooks/useAppRouter";
import { useInterval } from "@/hooks/useInterval";
-import { JellyseerrApi, useJellyseerr } from "@/hooks/useJellyseerr";
+import { SeerrApi, useSeerr } from "@/hooks/useSeerr";
import { useSettings } from "@/utils/atoms/settings";
import { writeErrorLog, writeInfoLog } from "@/utils/log";
import { storage } from "@/utils/mmkv";
@@ -113,7 +113,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
const [isPolling, setIsPolling] = useState(false);
const [secret, setSecret] = useState(null);
const { setPluginSettings, refreshStreamyfinPluginSettings } = useSettings();
- const { clearAllJellyseerData, setJellyseerrUser } = useJellyseerr();
+ const { clearAllSeerrData, setSeerrUser } = useSeerr();
const headers = useMemo(() => {
if (!deviceId) return {};
@@ -290,13 +290,13 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
}
const recentPluginSettings = await refreshStreamyfinPluginSettings();
- if (recentPluginSettings?.jellyseerrServerUrl?.value) {
- const jellyseerrApi = new JellyseerrApi(
- recentPluginSettings.jellyseerrServerUrl.value,
+ if (recentPluginSettings?.seerrServerUrl?.value) {
+ const seerrApi = new SeerrApi(
+ recentPluginSettings.seerrServerUrl.value,
);
- await jellyseerrApi.test().then((result) => {
+ await seerrApi.test().then((result) => {
if (result.isValid && result.requiresPass) {
- jellyseerrApi.login(username, password).then(setJellyseerrUser);
+ seerrApi.login(username, password).then(setSeerrUser);
}
});
}
@@ -349,7 +349,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
setUser(null);
setApi(null);
setPluginSettings(undefined);
- await clearAllJellyseerData();
+ await clearAllSeerrData();
// Note: We keep saved credentials for quick switching back
},
onError: (error) => {
diff --git a/translations/en.json b/translations/en.json
index 27e38ddb..c6652310 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -96,7 +96,7 @@
"a_free_and_open_source_client_for_jellyfin": "A Free and Open-Source Client for Jellyfin",
"features_title": "Features",
"features_description": "Streamyfin offers many features and integrates with a wide array of software which you can find in the settings menu, including:",
- "jellyseerr_feature_description": "Connect to your Seerr instance and request movies directly in the app.",
+ "seerr_feature_description": "Connect to your Seerr instance and request movies directly in the app.",
"downloads_feature_title": "Downloads",
"downloads_feature_description": "Download movies and TV shows to view offline.",
"chromecast_feature_description": "Cast movies and TV shows to your Chromecast devices.",
@@ -326,8 +326,8 @@
},
"plugins": {
"plugins_title": "Plugins",
- "jellyseerr": {
- "jellyseerr_warning": "This integration is in early development. Features may change.",
+ "seerr": {
+ "seerr_warning": "This integration is in early development. Features may change.",
"server_url": "Server URL",
"server_url_hint": "Example: http(s)://your-host.url\n(add port if required)",
"server_url_placeholder": "Seerr URL",
@@ -339,7 +339,7 @@
"movie_quota_days": "Movie Quota Days",
"tv_quota_limit": "TV Quota Limit",
"tv_quota_days": "TV Quota Days",
- "reset_jellyseerr_config_button": "Reset Seerr Config",
+ "reset_seerr_config_button": "Reset Seerr Config",
"unlimited": "Unlimited",
"plus_n_more": "+{{n}} more",
"order_by": {
@@ -675,7 +675,7 @@
"for_kids": "For Kids",
"news": "News"
},
- "jellyseerr": {
+ "seerr": {
"confirm": "Confirm",
"cancel": "Cancel",
"yes": "Yes",
@@ -719,9 +719,9 @@
"requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User",
"toasts": {
- "jellyseer_does_not_meet_requirements": "Seerr server does not meet minimum version requirements! Please update to at least 2.0.0",
- "jellyseerr_test_failed": "Seerr test failed. Please try again.",
- "failed_to_test_jellyseerr_server_url": "Failed to test Seerr server URL",
+ "seer_does_not_meet_requirements": "Seerr server does not meet minimum version requirements! Please update to at least 2.0.0",
+ "seerr_test_failed": "Seerr test failed. Please try again.",
+ "failed_to_test_seerr_server_url": "Failed to test Seerr server URL",
"issue_submitted": "Issue Submitted!",
"requested_item": "Requested {{item}}!",
"you_dont_have_permission_to_request": "You don't have permission to request!",
diff --git a/utils/_jellyseerr/useJellyseerrCanRequest.ts b/utils/_seerr/useSeerrCanRequest.ts
similarity index 83%
rename from utils/_jellyseerr/useJellyseerrCanRequest.ts
rename to utils/_seerr/useSeerrCanRequest.ts
index 2cd67a33..15e395db 100644
--- a/utils/_jellyseerr/useJellyseerrCanRequest.ts
+++ b/utils/_seerr/useSeerrCanRequest.ts
@@ -1,5 +1,5 @@
import { useMemo } from "react";
-import { useJellyseerr } from "@/hooks/useJellyseerr";
+import { useSeerr } from "@/hooks/useSeerr";
import {
MediaRequestStatus,
MediaStatus,
@@ -18,13 +18,13 @@ import type MediaRequest from "../jellyseerr/server/entity/MediaRequest";
import type { MovieDetails } from "../jellyseerr/server/models/Movie";
import type { TvDetails } from "../jellyseerr/server/models/Tv";
-export const useJellyseerrCanRequest = (
+export const useSeerrCanRequest = (
item?: MovieResult | TvResult | MovieDetails | TvDetails | PersonCreditCast,
) => {
- const { jellyseerrUser } = useJellyseerr();
+ const { seerrUser } = useSeerr();
const canRequest = useMemo(() => {
- if (!jellyseerrUser || !item) return false;
+ if (!seerrUser || !item) return false;
const canNotRequest =
item?.mediaInfo?.requests?.some(
@@ -46,22 +46,22 @@ export const useJellyseerrCanRequest = (
? Permission.REQUEST_MOVIE
: Permission.REQUEST_TV,
],
- jellyseerrUser.permissions,
+ seerrUser.permissions,
{ type: "or" },
);
return userHasPermission && !canNotRequest;
- }, [item, jellyseerrUser]);
+ }, [item, seerrUser]);
const hasAdvancedRequestPermission = useMemo(() => {
- if (!jellyseerrUser) return false;
+ if (!seerrUser) return false;
return hasPermission(
[Permission.REQUEST_ADVANCED, Permission.MANAGE_REQUESTS],
- jellyseerrUser.permissions,
+ seerrUser.permissions,
{ type: "or" },
);
- }, [jellyseerrUser]);
+ }, [seerrUser]);
return [canRequest, hasAdvancedRequestPermission];
};
diff --git a/utils/atoms/settings.ts b/utils/atoms/settings.ts
index 28f7d1b4..ecfd7a74 100644
--- a/utils/atoms/settings.ts
+++ b/utils/atoms/settings.ts
@@ -174,7 +174,7 @@ export type Settings = {
disableHapticFeedback: boolean;
subtitleSize: number;
safeAreaInControlsEnabled: boolean;
- jellyseerrServerUrl?: string;
+ seerrServerUrl?: string;
useKefinTweaks: boolean;
hiddenLibraries?: string[];
enableH265ForChromecast: boolean;
@@ -259,7 +259,7 @@ export const defaultValues: Settings = {
disableHapticFeedback: false,
subtitleSize: 100, // Scale value * 100, so 100 = 1.0x
safeAreaInControlsEnabled: true,
- jellyseerrServerUrl: undefined,
+ seerrServerUrl: undefined,
useKefinTweaks: false,
hiddenLibraries: [],
enableH265ForChromecast: false,