mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-07-02 10:32:50 +01:00
fix(jellyseerr): address PR review feedback on TV connect flow
- validateJellyseerrSession: hit the authenticated /auth/me endpoint instead of the public /status, and only report "expired" on 401/403. Transient failures (offline, 5xx) are treated as valid so a flaky network no longer logs the user out. The helper no longer mutates persisted state. - SearchPage: clear the stale "connected" state via clearAllJellyseerData on an expired session, gate the Discover validation effect behind isFocused, cancel in-flight validation on unmount, and reset the connect prompt when the tab loses focus so it can show again. - settings.tv (seerr): sync the local server-URL field with settings so a late-arriving stored/plugin-locked URL isn't shown stale or overwritten. - useJellyseerr: add setJellyseerrUser/updateSettings to clearAllJellyseerData deps to avoid a stale closure. - TVJellyseerrSearchResults: scale poster/avatar dimensions and use the scaled vertical padding (per review). - translations: drop manual sv.json keys (Crowdin syncs from en.json). Claude-Session: https://claude.ai/code/session_016Hhu5DruGLPhdP4LAoy1Xd
This commit is contained in:
@@ -3,7 +3,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { Directory, Paths } from "expo-file-system";
|
||||
import { Image } from "expo-image";
|
||||
import { useAtom } from "jotai";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Alert, ScrollView, View } from "react-native";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
@@ -70,6 +70,13 @@ export default function SettingsTV() {
|
||||
);
|
||||
const [jellyseerrPassword, setJellyseerrPassword] = useState("");
|
||||
|
||||
// Settings load storage + plugin overrides after mount, and a plugin can lock
|
||||
// the URL at runtime. Keep the local field in sync with the effective value
|
||||
// so it never shows stale/empty text or overwrites a locked URL on blur.
|
||||
useEffect(() => {
|
||||
setJellyseerrServerUrl(settings.jellyseerrServerUrl || "");
|
||||
}, [settings.jellyseerrServerUrl]);
|
||||
|
||||
const isJellyseerrLocked =
|
||||
pluginSettings?.jellyseerrServerUrl?.locked === true;
|
||||
const isJellyseerrConnected = !!jellyseerrApi;
|
||||
|
||||
@@ -122,13 +122,19 @@ export default function SearchPage() {
|
||||
|
||||
const isFocused = useIsFocused();
|
||||
const { settings } = useSettings();
|
||||
const { jellyseerrApi } = useJellyseerr();
|
||||
const { jellyseerrApi, clearAllJellyseerData } = useJellyseerr();
|
||||
|
||||
// Prompt the user to connect when a Jellyseerr server is configured but no
|
||||
// session exists yet (only once per focus, and only while the tab is focused).
|
||||
// session exists yet (once per focus, and only while the tab is focused).
|
||||
const jellyseerrAlertedRef = useRef(false);
|
||||
useEffect(() => {
|
||||
if (!isFocused || !settings?.jellyseerrServerUrl || jellyseerrApi) return;
|
||||
// Reset when the tab loses focus so the prompt can show again next time
|
||||
// (e.g. after the user disconnects and returns).
|
||||
if (!isFocused) {
|
||||
jellyseerrAlertedRef.current = false;
|
||||
return;
|
||||
}
|
||||
if (!settings?.jellyseerrServerUrl || jellyseerrApi) return;
|
||||
if (jellyseerrAlertedRef.current) return;
|
||||
jellyseerrAlertedRef.current = true;
|
||||
Alert.alert(
|
||||
@@ -137,22 +143,36 @@ export default function SearchPage() {
|
||||
);
|
||||
}, [isFocused, settings?.jellyseerrServerUrl, jellyseerrApi, t]);
|
||||
|
||||
// Validate the Jellyseerr session when switching to Discover; warn if expired.
|
||||
// Validate the Jellyseerr session when switching to Discover; if the session
|
||||
// has expired, clear the stale "connected" state and prompt to reconnect.
|
||||
useEffect(() => {
|
||||
if (
|
||||
!isFocused ||
|
||||
searchType !== "Discover" ||
|
||||
!jellyseerrApi ||
|
||||
!settings?.jellyseerrServerUrl
|
||||
)
|
||||
return;
|
||||
let cancelled = false;
|
||||
validateJellyseerrSession(settings.jellyseerrServerUrl).then((status) => {
|
||||
if (status.valid) return;
|
||||
if (cancelled || status.valid || status.reason !== "expired") return;
|
||||
clearAllJellyseerData();
|
||||
Alert.alert(
|
||||
t("jellyseerr.session_expired"),
|
||||
t("jellyseerr.session_expired_connect_again"),
|
||||
);
|
||||
});
|
||||
}, [searchType, jellyseerrApi, settings?.jellyseerrServerUrl, t]);
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [
|
||||
isFocused,
|
||||
searchType,
|
||||
jellyseerrApi,
|
||||
settings?.jellyseerrServerUrl,
|
||||
clearAllJellyseerData,
|
||||
t,
|
||||
]);
|
||||
|
||||
const [jellyseerrOrderBy, setJellyseerrOrderBy] =
|
||||
useState<JellyseerrSearchSort>(
|
||||
|
||||
Reference in New Issue
Block a user