fix: Jellyseerr discovery crash (#1032)

This commit is contained in:
stenlan
2025-09-03 21:41:35 +02:00
committed by GitHub
parent 6308375438
commit c778956a52
48 changed files with 90 additions and 120 deletions

View File

@@ -12,7 +12,7 @@ import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings";
export default function page() {
const [settings, updateSettings, pluginSettings] = useSettings(null);
const { settings, updateSettings, pluginSettings } = useSettings();
const user = useAtomValue(userAtom);
const api = useAtomValue(apiAtom);

View File

@@ -3,7 +3,7 @@ import { JellyseerrSettings } from "@/components/settings/Jellyseerr";
import { useSettings } from "@/utils/atoms/settings";
export default function page() {
const [_settings, _updateSettings, pluginSettings] = useSettings(null);
const { pluginSettings } = useSettings();
return (
<DisabledSetting

View File

@@ -21,7 +21,7 @@ export default function page() {
const { t } = useTranslation();
const [settings, updateSettings, pluginSettings] = useSettings(null);
const { settings, updateSettings, pluginSettings } = useSettings();
const queryClient = useQueryClient();
const [value, setValue] = useState<string>(settings?.marlinServerUrl || "");

View File

@@ -15,7 +15,7 @@ import { COMPANY_LOGO_IMAGE_FILTER } from "@/utils/jellyseerr/src/components/Dis
export default function page() {
const local = useLocalSearchParams();
const { jellyseerrApi } = useJellyseerr();
const { jellyseerrApi, isJellyseerrMovieOrTvResult } = useJellyseerr();
const { companyId, image, type } = local as unknown as {
companyId: string;
@@ -53,7 +53,10 @@ export default function page() {
uniqBy(
data?.pages
?.filter((p) => p?.results.length)
.flatMap((p) => p?.results ?? []),
.flatMap(
(p) =>
p?.results.filter((r) => isJellyseerrMovieOrTvResult(r)) ?? [],
),
"id",
) ?? [],
[data],
@@ -98,9 +101,7 @@ export default function page() {
}}
/>
}
renderItem={(item, _index) => (
<JellyseerrPoster item={item as MovieResult | TvResult} />
)}
renderItem={(item, _index) => <JellyseerrPoster item={item} />}
/>
);
}

View File

@@ -8,14 +8,10 @@ import ParallaxSlideShow from "@/components/jellyseerr/ParallaxSlideShow";
import JellyseerrPoster from "@/components/posters/JellyseerrPoster";
import { Endpoints, useJellyseerr } from "@/hooks/useJellyseerr";
import { DiscoverSliderType } from "@/utils/jellyseerr/server/constants/discover";
import {
type MovieResult,
type TvResult,
} from "@/utils/jellyseerr/server/models/Search";
export default function page() {
const local = useLocalSearchParams();
const { jellyseerrApi } = useJellyseerr();
const { jellyseerrApi, isJellyseerrMovieOrTvResult } = useJellyseerr();
const { genreId, name, type } = local as unknown as {
genreId: string;
@@ -51,7 +47,10 @@ export default function page() {
uniqBy(
data?.pages
?.filter((p) => p?.results.length)
.flatMap((p) => p?.results ?? []),
.flatMap(
(p) =>
p?.results.filter((r) => isJellyseerrMovieOrTvResult(r)) ?? [],
),
"id",
) ?? [],
[data],
@@ -62,7 +61,7 @@ export default function page() {
jellyseerrApi
? flatData.map((r) =>
jellyseerrApi.imageProxy(
(r as TvResult | MovieResult).backdropPath,
r.backdropPath,
"w1920_and_h800_multi_faces",
),
)
@@ -92,9 +91,7 @@ export default function page() {
{name}
</Text>
}
renderItem={(item, _index) => (
<JellyseerrPoster item={item as MovieResult | TvResult} />
)}
renderItem={(item, _index) => <JellyseerrPoster item={item} />}
/>
);
}

View File

@@ -10,10 +10,6 @@ import { OverviewText } from "@/components/OverviewText";
import JellyseerrPoster from "@/components/posters/JellyseerrPoster";
import { useJellyseerr } from "@/hooks/useJellyseerr";
import type { PersonCreditCast } from "@/utils/jellyseerr/server/models/Person";
import type {
MovieResult,
TvResult,
} from "@/utils/jellyseerr/server/models/Search";
export default function page() {
const local = useLocalSearchParams();
@@ -106,9 +102,7 @@ export default function page() {
MainContent={() => (
<OverviewText text={data?.details?.biography} className='mt-4' />
)}
renderItem={(item, _index) => (
<JellyseerrPoster item={item as MovieResult | TvResult} />
)}
renderItem={(item, _index) => <JellyseerrPoster item={item} />}
/>
);
}

View File

@@ -9,7 +9,7 @@ const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import { useTranslation } from "react-i18next";
export default function IndexLayout() {
const [settings, updateSettings, pluginSettings] = useSettings(null);
const { settings, updateSettings, pluginSettings } = useSettings();
const { t } = useTranslation();

View File

@@ -19,7 +19,7 @@ export default function index() {
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
const queryClient = useQueryClient();
const [settings] = useSettings(null);
const { settings } = useSettings();
const { t } = useTranslation();

View File

@@ -71,7 +71,7 @@ export default function search() {
const [api] = useAtom(apiAtom);
const [settings] = useSettings(null);
const { settings } = useSettings();
const { jellyseerrApi } = useJellyseerr();
const [jellyseerrOrderBy, setJellyseerrOrderBy] =
useState<JellyseerrSearchSort>(

View File

@@ -27,7 +27,7 @@ export const NativeTabs = withLayoutContext<
>(Navigator);
export default function TabLayout() {
const [settings] = useSettings(null);
const { settings } = useSettings();
const { t } = useTranslation();
const router = useRouter();

View File

@@ -97,7 +97,7 @@ export default function page() {
/** Playback position in ticks. */
playbackPosition?: string;
}>();
const [_settings] = useSettings(null);
useSettings();
const offline = offlineStr === "true";
const playbackManager = usePlaybackManager();
@@ -748,7 +748,6 @@ export default function page() {
setAspectRatio={setAspectRatio}
setScaleFactor={setScaleFactor}
isVlc
api={api}
downloadedFiles={downloadedFiles}
/>
)}

View File

@@ -230,7 +230,7 @@ const queryClient = new QueryClient({
});
function Layout() {
const [settings] = useSettings(null);
const { settings } = useSettings();
const [user] = useAtom(userAtom);
const [api] = useAtom(apiAtom);
const appState = useRef(AppState.currentState);

View File

@@ -61,7 +61,7 @@ export const DownloadItems: React.FC<DownloadProps> = ({
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
const [queue, _setQueue] = useAtom(queueAtom);
const [settings] = useSettings(null);
const { settings } = useSettings();
const [downloadUnwatchedOnly, setDownloadUnwatchedOnly] = useState(false);
const { processes, startBackgroundDownload, getDownloadedItems } =

View File

@@ -54,7 +54,7 @@ interface ItemContentProps {
export const ItemContent: React.FC<ItemContentProps> = React.memo(
({ item, isOffline }) => {
const [api] = useAtom(apiAtom);
const [settings] = useSettings(null);
const { settings } = useSettings();
const { orientation } = useOrientation();
const navigation = useNavigation();
const insets = useSafeAreaInsets();

View File

@@ -67,7 +67,7 @@ export const PlayButton: React.FC<Props> = ({
const startColor = useSharedValue(colorAtom);
const widthProgress = useSharedValue(0);
const colorChangeProgress = useSharedValue(0);
const [settings, updateSettings] = useSettings(null);
const { settings, updateSettings } = useSettings();
const lightHapticFeedback = useHaptic("light");
const goToPlayer = useCallback(

View File

@@ -44,7 +44,7 @@ export const PlayButton: React.FC<Props> = ({
const startColor = useSharedValue(colorAtom);
const widthProgress = useSharedValue(0);
const colorChangeProgress = useSharedValue(0);
const [settings] = useSettings(null);
const { settings } = useSettings();
const lightHapticFeedback = useHaptic("light");
const goToPlayer = useCallback(

View File

@@ -10,6 +10,7 @@ import {
Permission,
} from "@/utils/jellyseerr/server/lib/permissions";
import type { MovieDetails } from "@/utils/jellyseerr/server/models/Movie";
import { PersonCreditCast } from "@/utils/jellyseerr/server/models/Person";
import type {
MovieResult,
TvResult,
@@ -17,7 +18,7 @@ import type {
import type { TvDetails } from "@/utils/jellyseerr/server/models/Tv";
interface Props extends TouchableOpacityProps {
result?: MovieResult | TvResult | MovieDetails | TvDetails;
result?: MovieResult | TvResult | MovieDetails | TvDetails | PersonCreditCast;
mediaTitle: string;
releaseYear: number;
canRequest: boolean;

View File

@@ -26,7 +26,7 @@ import { itemRouter } from "../common/TouchableItemRouter";
interface Props extends ViewProps {}
export const LargeMovieCarousel: React.FC<Props> = ({ ...props }) => {
const [settings] = useSettings(null);
const { settings } = useSettings();
const ref = React.useRef<ICarouselInstance>(null);
const progress = useSharedValue<number>(0);

View File

@@ -11,16 +11,12 @@ import {
useJellyseerr,
} from "@/hooks/useJellyseerr";
import { DiscoverSliderType } from "@/utils/jellyseerr/server/constants/discover";
import type {
MovieResult,
TvResult,
} from "@/utils/jellyseerr/server/models/Search";
const MovieTvSlide: React.FC<SlideProps & ViewProps> = ({
slide,
...props
}) => {
const { jellyseerrApi } = useJellyseerr();
const { jellyseerrApi, isJellyseerrMovieOrTvResult } = useJellyseerr();
const { data, fetchNextPage, hasNextPage } = useInfiniteQuery({
queryKey: ["jellyseerr", "discover", slide.id],
@@ -69,7 +65,9 @@ const MovieTvSlide: React.FC<SlideProps & ViewProps> = ({
uniqBy(
data?.pages
?.filter((p) => p?.results.length)
.flatMap((p) => p?.results),
.flatMap((p) =>
p?.results.filter((r) => isJellyseerrMovieOrTvResult(r)),
),
"id",
),
[data],
@@ -86,12 +84,7 @@ const MovieTvSlide: React.FC<SlideProps & ViewProps> = ({
onEndReached={() => {
if (hasNextPage) fetchNextPage();
}}
renderItem={(item) => (
<JellyseerrPoster
item={item as MovieResult | TvResult}
key={item?.id}
/>
)}
renderItem={(item) => <JellyseerrPoster item={item} key={item?.id} />}
/>
)
);

View File

@@ -41,7 +41,7 @@ const icons: Record<CollectionType, IconName> = {
export const LibraryItemCard: React.FC<Props> = ({ library, ...props }) => {
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
const [settings] = useSettings(null);
const { settings } = useSettings();
const { t } = useTranslation();

View File

@@ -20,6 +20,7 @@ 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";
import type { MovieDetails } from "@/utils/jellyseerr/server/models/Movie";
import { PersonCreditCast } from "@/utils/jellyseerr/server/models/Person";
import type {
MovieResult,
TvResult,
@@ -27,7 +28,7 @@ import type {
import type { TvDetails } from "@/utils/jellyseerr/server/models/Tv";
interface Props extends ViewProps {
item?: MovieResult | TvResult | MovieDetails | TvDetails;
item?: MovieResult | TvResult | MovieDetails | TvDetails | PersonCreditCast;
horizontal?: boolean;
showDownloadInfo?: boolean;
mediaRequest?: MediaRequest;

View File

@@ -12,7 +12,7 @@ interface Props extends ViewProps {}
export const AppLanguageSelector: React.FC<Props> = () => {
const isTv = Platform.isTV;
const [settings, updateSettings] = useSettings(null);
const { settings, updateSettings } = useSettings();
const { t } = useTranslation();
if (isTv) return null;

View File

@@ -17,7 +17,7 @@ export const AudioToggles: React.FC<Props> = ({ ...props }) => {
const isTv = Platform.isTV;
const media = useMedia();
const [_, __, pluginSettings] = useSettings(null);
const { pluginSettings } = useSettings();
const { settings, updateSettings } = media;
const cultures = media.cultures;
const { t } = useTranslation();

View File

@@ -4,7 +4,7 @@ import { ListGroup } from "../list/ListGroup";
import { ListItem } from "../list/ListItem";
export const ChromecastSettings: React.FC = ({ ...props }) => {
const [settings, updateSettings] = useSettings(null);
const { settings, updateSettings } = useSettings();
return (
<View {...props}>
<ListGroup title={"Chromecast"}>

View File

@@ -7,7 +7,7 @@ import { ListGroup } from "../list/ListGroup";
import { ListItem } from "../list/ListItem";
export const Dashboard = () => {
const [settings, _updateSettings] = useSettings(null);
const { settings } = useSettings();
const { sessions = [] } = useSessions({} as useSessionsProps);
const router = useRouter();

View File

@@ -7,7 +7,7 @@ import { ListGroup } from "../list/ListGroup";
import { ListItem } from "../list/ListItem";
export default function DownloadSettings({ ...props }) {
const [settings, updateSettings, pluginSettings] = useSettings(null);
const { settings, updateSettings, pluginSettings } = useSettings();
const { t } = useTranslation();
const allDisabled = useMemo(

View File

@@ -13,7 +13,7 @@ interface Props extends ViewProps {}
export const GestureControls: React.FC<Props> = ({ ...props }) => {
const { t } = useTranslation();
const [settings, updateSettings, pluginSettings] = useSettings(null);
const { settings, updateSettings, pluginSettings } = useSettings();
const disabled = useMemo(
() =>

View File

@@ -64,13 +64,7 @@ export const HomeIndex = () => {
const user = useAtomValue(userAtom);
const [loading, setLoading] = useState(false);
const [
settings,
_updateSettings,
_pluginSettings,
_setPluginSettings,
refreshStreamyfinPluginSettings,
] = useSettings(null);
const { settings, refreshStreamyfinPluginSettings } = useSettings();
const navigation = useNavigation();

View File

@@ -20,7 +20,7 @@ export const JellyseerrSettings = () => {
const { t } = useTranslation();
const [user] = useAtom(userAtom);
const [settings, updateSettings, _pluginSettings] = useSettings(null);
const { settings, updateSettings } = useSettings();
const [jellyseerrPassword, setJellyseerrPassword] = useState<
string | undefined

View File

@@ -28,7 +28,7 @@ export const useMedia = () => {
};
export const MediaProvider = ({ children }: { children: ReactNode }) => {
const [settings, updateSettings] = useSettings(null);
const { settings, updateSettings } = useSettings();
const api = useAtomValue(apiAtom);
const queryClient = useQueryClient();

View File

@@ -13,7 +13,7 @@ interface Props extends ViewProps {}
export const MediaToggles: React.FC<Props> = ({ ...props }) => {
const { t } = useTranslation();
const [settings, updateSettings, pluginSettings] = useSettings(null);
const { settings, updateSettings, pluginSettings } = useSettings();
const disabled = useMemo(
() =>

View File

@@ -23,7 +23,7 @@ import { ListItem } from "../list/ListItem";
export const OtherSettings: React.FC = () => {
const router = useRouter();
const [settings, updateSettings, pluginSettings] = useSettings(null);
const { settings, updateSettings, pluginSettings } = useSettings();
const { t } = useTranslation();

View File

@@ -6,7 +6,7 @@ import { ListGroup } from "../list/ListGroup";
import { ListItem } from "../list/ListItem";
export const PluginSettings = () => {
const [settings, _updateSettings] = useSettings(null);
const { settings } = useSettings();
const router = useRouter();

View File

@@ -20,7 +20,7 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
const isTv = Platform.isTV;
const media = useMedia();
const [_, __, pluginSettings] = useSettings(null);
const { pluginSettings } = useSettings();
const { settings, updateSettings } = media;
const cultures = media.cultures;
const { t } = useTranslation();

View File

@@ -88,7 +88,7 @@ export const BottomControls: FC<BottomControlsProps> = ({
trickplayInfo,
time,
}) => {
const [settings] = useSettings(null);
const { settings } = useSettings();
const insets = useSafeAreaInsets();
return (

View File

@@ -30,7 +30,7 @@ export const CenterControls: FC<CenterControlsProps> = ({
handleSkipBackward,
handleSkipForward,
}) => {
const [settings] = useSettings(null);
const { settings } = useSettings();
const insets = useSafeAreaInsets();
return (

View File

@@ -16,7 +16,7 @@ export interface ContinueWatchingOverlayProps {
const ContinueWatchingOverlay: React.FC<ContinueWatchingOverlayProps> = ({
goToNextItem,
}) => {
const [settings] = useSettings(null);
const { settings } = useSettings();
const router = useRouter();
return settings.autoPlayEpisodeCount >=

View File

@@ -116,7 +116,7 @@ export const Controls: FC<Props> = ({
api = null,
downloadedFiles = undefined,
}) => {
const [settings, updateSettings] = useSettings(api);
const { settings, updateSettings } = useSettings();
const router = useRouter();
const lightHapticFeedback = useHaptic("light");

View File

@@ -31,7 +31,7 @@ export const GestureOverlay = ({
onSkipForward,
onSkipBackward,
}: Props) => {
const [settings] = useSettings(null);
const { settings } = useSettings();
const lightHaptic = useHaptic("light");
const [feedback, setFeedback] = useState<FeedbackState>({

View File

@@ -70,7 +70,7 @@ export const HeaderControls: FC<HeaderControlsProps> = ({
setVideoAspectRatio,
setVideoScaleFactor,
}) => {
const [settings] = useSettings(null);
const { settings } = useSettings();
const router = useRouter();
const insets = useSafeAreaInsets();
const { width: screenWidth } = useWindowDimensions();

View File

@@ -20,7 +20,7 @@ export function useVideoNavigation({
seek,
play,
}: UseVideoNavigationProps) {
const [settings] = useSettings(null);
const { settings } = useSettings();
const lightHapticFeedback = useHaptic("light");
const wasPlayingRef = useRef(false);

View File

@@ -14,7 +14,7 @@ export type HapticFeedbackType =
| "error";
export const useHaptic = (feedbackType: HapticFeedbackType = "selection") => {
const [settings] = useSettings(null);
const { settings } = useSettings();
const isTv = Platform.isTV;
const isDisabled =
isTv ||

View File

@@ -14,7 +14,7 @@ import { useQueryClient } from "@tanstack/react-query";
import { t } from "i18next";
import { useCallback, useMemo } from "react";
import { toast } from "sonner-native";
import { defaultValues, Settings } from "@/utils/atoms/settings";
import { useSettings } from "@/utils/atoms/settings";
import type { RTRating } from "@/utils/jellyseerr/server/api/rating/rottentomatoes";
import {
IssueStatus,
@@ -40,6 +40,7 @@ import type { UserResultsResponse } from "@/utils/jellyseerr/server/interfaces/a
import type { MovieDetails } from "@/utils/jellyseerr/server/models/Movie";
import type {
CombinedCredit,
PersonCreditCast,
PersonDetails,
} from "@/utils/jellyseerr/server/models/Person";
import type {
@@ -416,10 +417,8 @@ export class JellyseerrApi {
const jellyseerrUserAtom = atom(storage.get<JellyseerrUser>(JELLYSEERR_USER));
export const useJellyseerr = (
settings: Settings = defaultValues,
updateSettings: (update: Partial<Settings>) => void = () => {},
) => {
export const useJellyseerr = () => {
const { settings, updateSettings } = useSettings();
const [jellyseerrUser, setJellyseerrUser] = useAtom(jellyseerrUserAtom);
const queryClient = useQueryClient();
@@ -468,49 +467,47 @@ export const useJellyseerr = (
[jellyseerrApi],
);
const isJellyseerrResult = (
const isJellyseerrMovieOrTvResult = (
items: any | null | undefined,
): items is Results => {
): items is MovieResult | TvResult => {
return (
items &&
Object.hasOwn(items, "mediaType") &&
Object.values(MediaType).includes(items.mediaType as MediaType)
(items.mediaType === MediaType.MOVIE || items.mediaType === MediaType.TV)
);
};
const getTitle = (
item?: TvResult | TvDetails | MovieResult | MovieDetails,
item?: TvResult | TvDetails | MovieResult | MovieDetails | PersonCreditCast,
) => {
return isJellyseerrResult(item)
return isJellyseerrMovieOrTvResult(item)
? item.mediaType === MediaType.MOVIE
? item?.title
: item?.name
: item?.mediaInfo.mediaType === MediaType.MOVIE
: item?.mediaInfo?.mediaType === MediaType.MOVIE
? (item as MovieDetails)?.title
: (item as TvDetails)?.name;
};
const getYear = (
item?: TvResult | TvDetails | MovieResult | MovieDetails,
item?: TvResult | TvDetails | MovieResult | MovieDetails | PersonCreditCast,
) => {
return new Date(
(isJellyseerrResult(item)
(isJellyseerrMovieOrTvResult(item)
? item.mediaType === MediaType.MOVIE
? item?.releaseDate
: item?.firstAirDate
: item?.mediaInfo.mediaType === MediaType.MOVIE
: item?.mediaInfo?.mediaType === MediaType.MOVIE
? (item as MovieDetails)?.releaseDate
: (item as TvDetails)?.firstAirDate) || "",
)?.getFullYear?.();
};
const getMediaType = (
item?: TvResult | TvDetails | MovieResult | MovieDetails,
item?: TvResult | TvDetails | MovieResult | MovieDetails | PersonCreditCast,
): MediaType => {
return isJellyseerrResult(item)
? item.mediaType === "movie"
? MediaType.MOVIE
: MediaType.TV
return isJellyseerrMovieOrTvResult(item)
? (item.mediaType as MediaType)
: item?.mediaInfo?.mediaType;
};
@@ -528,7 +525,7 @@ export const useJellyseerr = (
jellyseerrUser,
setJellyseerrUser,
clearAllJellyseerData,
isJellyseerrResult,
isJellyseerrMovieOrTvResult,
getTitle,
getYear,
getMediaType,

View File

@@ -87,7 +87,7 @@ function useDownloadProvider() {
const { saveSeriesPrimaryImage } = useDownloadHelper();
const { saveImage } = useImageStorage();
const [processes, setProcesses] = useAtom<JobStatus[]>(processesAtom);
const [settings] = useSettings(null);
const { settings } = useSettings();
const successHapticFeedback = useHaptic("success");
/// Cant use the background downloader callback. As its not triggered if size is unknown.

View File

@@ -79,17 +79,8 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
const [user, setUser] = useAtom(userAtom);
const [isPolling, setIsPolling] = useState<boolean>(false);
const [secret, setSecret] = useState<string | null>(null);
const [
_settings,
_updateSettings,
_pluginSettings,
setPluginSettings,
refreshStreamyfinPluginSettings,
] = useSettings(api);
const { clearAllJellyseerData, setJellyseerrUser } = useJellyseerr(
_settings || {},
_updateSettings,
);
const { setPluginSettings, refreshStreamyfinPluginSettings } = useSettings();
const { clearAllJellyseerData, setJellyseerrUser } = useJellyseerr();
const headers = useMemo(() => {
if (!deviceId) return {};

View File

@@ -9,6 +9,7 @@ import {
hasPermission,
Permission,
} from "@/utils/jellyseerr/server/lib/permissions";
import { PersonCreditCast } from "@/utils/jellyseerr/server/models/Person";
import type {
MovieResult,
TvResult,
@@ -18,7 +19,7 @@ import type { MovieDetails } from "../jellyseerr/server/models/Movie";
import type { TvDetails } from "../jellyseerr/server/models/Tv";
export const useJellyseerrCanRequest = (
item?: MovieResult | TvResult | MovieDetails | TvDetails,
item?: MovieResult | TvResult | MovieDetails | TvDetails | PersonCreditCast,
) => {
const { jellyseerrUser } = useJellyseerr();

View File

@@ -56,7 +56,7 @@ export const useJobProcessor = () => {
const [queue, setQueue] = useAtom(queueAtom);
const [running, setRunning] = useAtom(runningAtom);
const [processes] = useAtom<JobStatus[]>(processesAtom);
const [settings] = useSettings(null);
const { settings } = useSettings();
useEffect(() => {
if (

View File

@@ -1,4 +1,3 @@
import type { Api } from "@jellyfin/sdk";
import {
type BaseItemKind,
type CultureDto,
@@ -7,11 +6,12 @@ import {
type SortOrder,
SubtitlePlaybackMode,
} from "@jellyfin/sdk/lib/generated-client";
import { atom, useAtom } from "jotai";
import { atom, useAtom, useAtomValue } from "jotai";
import { useCallback, useEffect, useMemo } from "react";
import { Platform } from "react-native";
import { BITRATES, type Bitrate } from "@/components/BitrateSelector";
import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { apiAtom } from "@/providers/JellyfinProvider";
import { writeInfoLog } from "@/utils/log";
import { storage } from "../mmkv";
@@ -278,7 +278,8 @@ export const pluginSettingsAtom = atom<PluginLockableSettings | undefined>(
loadPluginSettings(),
);
export const useSettings = (api: Api | null) => {
export const useSettings = () => {
const api = useAtomValue(apiAtom);
const [_settings, setSettings] = useAtom(settingsAtom);
const [pluginSettings, _setPluginSettings] = useAtom(pluginSettingsAtom);
@@ -302,11 +303,11 @@ export const useSettings = (api: Api | null) => {
return;
}
const settings = await api.getStreamyfinPluginConfig().then(
({ data }: any) => {
({ data }) => {
writeInfoLog("Got plugin settings", data?.settings);
return data?.settings;
},
(_err: any) => undefined,
(_err) => undefined,
);
setPluginSettings(settings);
return settings;
@@ -367,11 +368,11 @@ export const useSettings = (api: Api | null) => {
};
}, [_settings, pluginSettings]);
return [
return {
settings,
updateSettings,
pluginSettings,
setPluginSettings,
refreshStreamyfinPluginSettings,
] as const;
};
};