From e396d9844ceba3465340317a3b243ed58d12f19e Mon Sep 17 00:00:00 2001 From: Fishandchips321 Date: Sun, 22 Mar 2026 18:43:53 +0000 Subject: [PATCH] feat(jellyfn-auth): added crude error handling --- frontend/src/Lib/QuickConnect.ts | 26 ++++++++----- .../ServerManagement/ServerManagement.tsx | 38 ++++++++++++------- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/frontend/src/Lib/QuickConnect.ts b/frontend/src/Lib/QuickConnect.ts index c50771b..89e5251 100644 --- a/frontend/src/Lib/QuickConnect.ts +++ b/frontend/src/Lib/QuickConnect.ts @@ -1,4 +1,4 @@ -import axios from "axios"; +import axios, { AxiosError } from "axios"; const DeviceInfoString = "MediaBrowser Client=JellyGlass, Device=JellyGlass, DeviceId=JellyGlass, Version=1"; @@ -12,26 +12,32 @@ export interface QuickConnectAuth { AccessToken: string; } -export const BeginQuickConnect = async (url: string, callback: (apiToken: string) => void, isCancelled: () => boolean): Promise => { +export const BeginQuickConnect = async (url: string, callback: (apiToken: string) => void, isCancelled: () => boolean, onError: (e: AxiosError) => void): Promise => { const response = await axios.post(`${url}/QuickConnect/Initiate`, {}, { headers: { Authorization: DeviceInfoString } }); - setTimeout(() => { PollQuickConnect(url, response.data, callback, isCancelled) }); + setTimeout(() => { PollQuickConnect(url, response.data, callback, isCancelled, onError) }); return response.data.Code; } -const PollQuickConnect = async (url: string, info: QuickConnectInfo, callback: (apiToken: string) => void, isCancelled: () => boolean) => { +const PollQuickConnect = async (url: string, info: QuickConnectInfo, callback: (apiToken: string) => void, isCancelled: () => boolean, onError: (e: AxiosError) => void) => { if (isCancelled()) { return; } - const response = await axios.get(`${url}/QuickConnect/Connect?secret=${info.Secret}`, { headers: { Authorization: DeviceInfoString } }); + try { + const response = await axios.get(`${url}/QuickConnect/Connect?secret=${info.Secret}`, { headers: { Authorization: DeviceInfoString } }); - if (response.data.Authenticated) { - const authResponse = await axios.post(`${url}/Users/AuthenticateWithQuickConnect`, { Secret: response.data.Secret }) - callback(authResponse.data.AccessToken); + if (response.data.Authenticated) { + const authResponse = await axios.post(`${url}/Users/AuthenticateWithQuickConnect`, { Secret: response.data.Secret }) + callback(authResponse.data.AccessToken); + } + else { + setTimeout(() => { PollQuickConnect(url, response.data, callback, isCancelled, onError) }, 5000) + } } - else { - setTimeout(() => { PollQuickConnect(url, response.data, callback, isCancelled) }, 5000) + catch (e) { + console.log(e); + onError(e as AxiosError); } } \ No newline at end of file diff --git a/frontend/src/Pages/Admin/ServerManagement/ServerManagement.tsx b/frontend/src/Pages/Admin/ServerManagement/ServerManagement.tsx index 0707bd0..a24819c 100644 --- a/frontend/src/Pages/Admin/ServerManagement/ServerManagement.tsx +++ b/frontend/src/Pages/Admin/ServerManagement/ServerManagement.tsx @@ -1,14 +1,16 @@ import { useEffect, useState } from "react"; -import { Button, Form, Spinner, Table } from "react-bootstrap"; +import { Button, Form, Modal, Spinner, Table } from "react-bootstrap"; import { AddServer, getServerList, RemoveServer, type Server } from "../../../Lib/Servers"; import { useImmer } from "use-immer"; import styles from "../Management.module.scss"; import { BeginQuickConnect } from "../../../Lib/QuickConnect"; +import type { AxiosError } from "axios"; const ServerManagement = () => { const [servers, setServers] = useImmer | undefined>(undefined); - const [addCancelled, setAddCancelled] = useState(false); + const [isCancelled, setIsCancelled] = useState(false); + const [quickConnectCode, setQuickConnectCode] = useState(undefined); const [addServerInfo, setAddServerInfo] = useImmer({ url: "", @@ -39,24 +41,23 @@ const ServerManagement = () => { } const onQuickConnect = () => { - //start quick connect request - //show quick connect code to user (modal) - //poll quick connect state until it's authenticated - //fetch quick connect credentials - //onServerAdd(token); - BeginQuickConnect(addServerInfo.url, onServerAdd, () => addCancelled).then(quickConnectCode => { - //show modal with code - alert(`Your quick connect code is ${quickConnectCode}`); + setIsCancelled(false); + BeginQuickConnect(addServerInfo.url, onServerAdd, () => isCancelled, onQuickConnectError).then(code => { + setQuickConnectCode(code); }).catch(err => { - //alert user to error - //possibly clear fields? console.log(err); alert(err); }); } + const onQuickConnectError = (e: AxiosError) => { + setIsCancelled(true); + setQuickConnectCode(undefined); + alert(e); + } + const onServerAdd = (apiToken: string) => { - //hide quick connect modal + setQuickConnectCode(undefined); AddServer(addServerInfo.owner, addServerInfo.url, apiToken).then(result => { if (result.errored) { alert("Server was added, but is not working. Check the logs for details"); @@ -121,6 +122,17 @@ const ServerManagement = () => { } + { setQuickConnectCode(undefined); setIsCancelled(true); }}> + + Jellyfin quick connect code + + + Your quick connect code is {quickConnectCode} + + + + + ) }