mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-06-04 21:18:31 +01:00
The resolver field only needs to find the working URL — the Jellyseerr version requirement is irrelevant there and only polluted the UI. - jellyseerrProbe: validate reachability + that it's a jellyseerr (no version gate, no version-too-low outcome). - Drop the version-too-low reason from the whole resolver stack (types, resolve, hook, status text, i18n). - Min version 2.0.0 stays enforced in JellyseerrApi.test() at login: now writes an error log + toast, and uses numeric isVersionBelow (fixes the "2.10.0" < "2.0.0" string-compare bug).
66 lines
1.9 KiB
TypeScript
66 lines
1.9 KiB
TypeScript
import { useCallback, useEffect, useRef, useState } from "react";
|
|
import {
|
|
type ResolveFailureReason,
|
|
type ResolveOptions,
|
|
type ResolveResult,
|
|
resolveServerUrl,
|
|
} from "@/utils/serverUrl/resolve";
|
|
import type { ServerProbe } from "@/utils/serverUrl/types";
|
|
|
|
export type ServerUrlResolverState =
|
|
| { status: "idle" }
|
|
| { status: "resolving" }
|
|
| { status: "ok"; resolvedUrl: string; meta?: Record<string, unknown> }
|
|
| { status: "error"; reason: ResolveFailureReason };
|
|
|
|
/**
|
|
* Stateful wrapper around `resolveServerUrl` for screens.
|
|
*
|
|
* `resolve(input)` cancels any in-flight resolution, drives the state machine
|
|
* (idle → resolving → ok | error) and returns the raw result. Pass a stable
|
|
* (module-level) probe; memoize `options` if you supply one.
|
|
*/
|
|
export function useServerUrlResolver(
|
|
probe: ServerProbe,
|
|
options?: ResolveOptions,
|
|
) {
|
|
const [state, setState] = useState<ServerUrlResolverState>({
|
|
status: "idle",
|
|
});
|
|
const abortRef = useRef<AbortController | null>(null);
|
|
|
|
const resolve = useCallback(
|
|
async (input: string): Promise<ResolveResult> => {
|
|
abortRef.current?.abort();
|
|
const controller = new AbortController();
|
|
abortRef.current = controller;
|
|
setState({ status: "resolving" });
|
|
|
|
const result = await resolveServerUrl(input, probe, {
|
|
...options,
|
|
signal: controller.signal,
|
|
});
|
|
|
|
// Ignore results from a resolution that was superseded/cancelled.
|
|
if (!controller.signal.aborted) {
|
|
setState(
|
|
result.ok
|
|
? { status: "ok", resolvedUrl: result.url, meta: result.meta }
|
|
: { status: "error", reason: result.reason },
|
|
);
|
|
}
|
|
return result;
|
|
},
|
|
[probe, options],
|
|
);
|
|
|
|
const reset = useCallback(() => {
|
|
abortRef.current?.abort();
|
|
setState({ status: "idle" });
|
|
}, []);
|
|
|
|
useEffect(() => () => abortRef.current?.abort(), []);
|
|
|
|
return { ...state, resolve, reset };
|
|
}
|