diff --git a/components/common/ServerUrlField.tsx b/components/common/ServerUrlField.tsx index e8fa6b5fe..122cd8afb 100644 --- a/components/common/ServerUrlField.tsx +++ b/components/common/ServerUrlField.tsx @@ -18,8 +18,6 @@ interface ServerUrlFieldProps { label?: string; hint?: string; placeholder?: string; - /** Shown in the "version too low" message. */ - minVersion?: string; editable?: boolean; resolveOptions?: ResolveOptions; } @@ -38,7 +36,6 @@ export function ServerUrlField({ label, hint, placeholder, - minVersion, editable = true, resolveOptions, }: ServerUrlFieldProps) { @@ -96,11 +93,7 @@ export function ServerUrlField({ clearButtonMode='never' /> - + ); } diff --git a/components/common/ServerUrlStatusText.tsx b/components/common/ServerUrlStatusText.tsx index 13c521272..e402289d6 100644 --- a/components/common/ServerUrlStatusText.tsx +++ b/components/common/ServerUrlStatusText.tsx @@ -10,11 +10,9 @@ import { Text } from "./Text"; */ export function ServerUrlStatusText({ state, - minVersion, className = "", }: { state: ServerUrlResolverState; - minVersion?: string; className?: string; }) { const { t } = useTranslation(); @@ -41,16 +39,11 @@ export function ServerUrlStatusText({ } const message = - state.reason === "version-too-low" - ? t("server_url.version_too_low", { - version: state.version ?? "?", - min: minVersion ?? "", - }) - : state.reason === "wrong-service" - ? t("server_url.wrong_service") - : state.reason === "invalid" - ? t("server_url.invalid_url") - : t("server_url.unreachable"); + state.reason === "wrong-service" + ? t("server_url.wrong_service") + : state.reason === "invalid" + ? t("server_url.invalid_url") + : t("server_url.unreachable"); return {message}; } diff --git a/components/settings/Jellyseerr.tsx b/components/settings/Jellyseerr.tsx index e0f65b0de..1129830c2 100644 --- a/components/settings/Jellyseerr.tsx +++ b/components/settings/Jellyseerr.tsx @@ -146,7 +146,6 @@ export const JellyseerrSettings = () => { onChangeText={setjellyseerrServerUrl} onResolved={(url) => setResolvedUrl(url)} probe={jellyseerrProbe} - minVersion='2.0.0' label={t("home.settings.plugins.jellyseerr.server_url")} hint={t("home.settings.plugins.jellyseerr.server_url_hint")} placeholder={t( diff --git a/hooks/useJellyseerr.ts b/hooks/useJellyseerr.ts index 4ae918d85..32c7b6c25 100644 --- a/hooks/useJellyseerr.ts +++ b/hooks/useJellyseerr.ts @@ -48,6 +48,7 @@ import type { TvDetails, } from "@/utils/jellyseerr/server/models/Tv"; import { writeErrorLog } from "@/utils/log"; +import { isVersionBelow } from "@/utils/serverUrl/semver"; interface SearchParams { query: string; @@ -141,10 +142,13 @@ export class JellyseerrApi { .then((response) => { const { status, headers, data } = response; if (inRange(status, 200, 299)) { - if (data.version < "2.0.0") { + if (data.version && isVersionBelow(data.version, "2.0.0")) { const error = t( "jellyseerr.toasts.jellyseer_does_not_meet_requirements", ); + writeErrorLog( + `Jellyseerr version ${data.version} is below the required 2.0.0`, + ); toast.error(error); throw Error(error); } diff --git a/hooks/useServerUrlResolver.ts b/hooks/useServerUrlResolver.ts index 736fa978e..2ef7aa9f9 100644 --- a/hooks/useServerUrlResolver.ts +++ b/hooks/useServerUrlResolver.ts @@ -11,7 +11,7 @@ export type ServerUrlResolverState = | { status: "idle" } | { status: "resolving" } | { status: "ok"; resolvedUrl: string; meta?: Record } - | { status: "error"; reason: ResolveFailureReason; version?: string }; + | { status: "error"; reason: ResolveFailureReason }; /** * Stateful wrapper around `resolveServerUrl` for screens. @@ -46,11 +46,7 @@ export function useServerUrlResolver( setState( result.ok ? { status: "ok", resolvedUrl: result.url, meta: result.meta } - : { - status: "error", - reason: result.reason, - version: result.version, - }, + : { status: "error", reason: result.reason }, ); } return result; diff --git a/translations/en.json b/translations/en.json index 0e8571e75..7b4c6adaf 100644 --- a/translations/en.json +++ b/translations/en.json @@ -5,7 +5,6 @@ "connected": "Connected to {{url}}", "unreachable": "Server unreachable", "wrong_service": "Reachable, but not the expected server", - "version_too_low": "Version {{version}} is too old (minimum {{min}})", "invalid_url": "Enter a valid address" }, "login": { diff --git a/utils/serverUrl/probes/jellyseerr.ts b/utils/serverUrl/probes/jellyseerr.ts index cf4ba20e8..5b01050bf 100644 --- a/utils/serverUrl/probes/jellyseerr.ts +++ b/utils/serverUrl/probes/jellyseerr.ts @@ -1,14 +1,11 @@ import axios from "axios"; -import { isVersionBelow } from "../semver"; import type { ServerProbe } from "../types"; -/** Jellyseerr/Overseerr minimum supported version. */ -const MIN_VERSION = "2.0.0"; - /** * Probe for a Jellyseerr server. `/api/v1/status` is jellyseerr/overseerr - * specific and unauthenticated, so it both proves reachability and confirms - * we hit the right service. + * specific and unauthenticated, so it both proves reachability and confirms we + * hit the right service. The minimum-version requirement is enforced at login + * time (see JellyseerrApi.test) — not surfaced here, to keep the field UI clean. */ export const jellyseerrProbe: ServerProbe = async (url, signal) => { try { @@ -19,22 +16,14 @@ export const jellyseerrProbe: ServerProbe = async (url, signal) => { if (status < 200 || status >= 300) return { status: "unreachable" }; - const version: string | undefined = - typeof data?.version === "string" ? data.version : undefined; - // A JSON body carrying version/commitTag identifies a real jellyseerr. - if ( - !version && - !(data && typeof data === "object" && "commitTag" in data) - ) { - return { status: "wrong-service" }; - } + const looksLikeJellyseerr = + !!data && + typeof data === "object" && + (typeof data.version === "string" || "commitTag" in data); + if (!looksLikeJellyseerr) return { status: "wrong-service" }; - if (version && isVersionBelow(version, MIN_VERSION)) { - return { status: "version-too-low", version }; - } - - return { status: "ok", meta: { version } }; + return { status: "ok", meta: { version: data.version } }; } catch { return { status: "unreachable" }; } diff --git a/utils/serverUrl/resolve.ts b/utils/serverUrl/resolve.ts index 8cf5b234b..8fa270140 100644 --- a/utils/serverUrl/resolve.ts +++ b/utils/serverUrl/resolve.ts @@ -4,13 +4,12 @@ import type { ServerProbe, ServerProbeOutcome } from "./types"; export type ResolveFailureReason = | "empty" | "invalid" - | "version-too-low" | "wrong-service" | "unreachable"; export type ResolveResult = | { ok: true; url: string; meta?: Record } - | { ok: false; reason: ResolveFailureReason; version?: string }; + | { ok: false; reason: ResolveFailureReason }; export interface ResolveOptions { /** Per-candidate probe timeout in ms. Default 5000. */ @@ -22,7 +21,6 @@ export interface ResolveOptions { // Order in which to surface a failure when no candidate validated: // the more specific/actionable the reason, the earlier it is reported. const FAILURE_PRIORITY = [ - "version-too-low", "wrong-service", "unreachable", ] as const satisfies ReadonlyArray; @@ -62,11 +60,7 @@ export async function resolveServerUrl( for (const reason of FAILURE_PRIORITY) { const hit = outcomes.find((outcome) => outcome.status === reason); if (hit) { - return { - ok: false, - reason, - version: hit.status === "version-too-low" ? hit.version : undefined, - }; + return { ok: false, reason }; } } return { ok: false, reason: "unreachable" }; diff --git a/utils/serverUrl/types.ts b/utils/serverUrl/types.ts index f95658924..45fd4985f 100644 --- a/utils/serverUrl/types.ts +++ b/utils/serverUrl/types.ts @@ -1,7 +1,6 @@ /** Result of probing a single candidate URL for a specific service. */ export type ServerProbeOutcome = | { status: "ok"; meta?: Record } - | { status: "version-too-low"; version?: string } | { status: "wrong-service" } | { status: "unreachable" };