import React, { useEffect, useState } from "react"; import { getQuickConnectApi } from "@jellyfin/sdk/lib/utils/api/quick-connect-api"; import { getUserApi } from "@jellyfin/sdk/lib/utils/api/user-api"; import { jellyfin, jellyfinApi, jellyfinUser, setJellyfinApi, setJellyfinUser } from "./app"; import styles from "./styles.module.css"; type View = "url" | "password" | "quick-connect" | "settings"; export default function SettingsModal() { const [url, setUrl] = useState(Spicetify.LocalStorage.get("jellyfin-url") || ""); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [view, setView] = useState(jellyfinUser ? "settings" : "url"); const [quickConnectCode, setQuickConnectCode] = useState(""); const createApi = async () => { const servers = await jellyfin.discovery.getRecommendedServerCandidates(url); const best = jellyfin.discovery.findBestServer(servers); if (!best) { Spicetify.showNotification("Failed to connect to server!", true); return; } const api = jellyfin.createApi(best.address); Spicetify.LocalStorage.set("jellyfin-url", url); setJellyfinApi(api); setView("password"); }; const login = async () => { if (!jellyfinApi) return; const userApi = getUserApi(jellyfinApi); const auth = await userApi.authenticateUserByName({ authenticateUserByName: { Username: username, Pw: password } }); if (!auth.data.AccessToken) { Spicetify.showNotification("Failed to login!", true); return; } jellyfinApi.accessToken = auth.data.AccessToken; Spicetify.LocalStorage.set("jellyfin-token", auth.data.AccessToken); const user = await getUserApi(jellyfinApi).getCurrentUser(); if (user.data.Id) setJellyfinUser(user.data.Id); setView("settings"); }; const logout = () => { Spicetify.LocalStorage.remove("jellyfin-token"); setView("url"); }; useEffect(() => { if (view !== "quick-connect") return; if (!jellyfinApi) return; const quickConnectApi = getQuickConnectApi(jellyfinApi); let interval: NodeJS.Timeout; (async () => { const enabled = await quickConnectApi.getQuickConnectEnabled(); if (!enabled.data) { Spicetify.showNotification("Quick Connect is not enabled on this server!", true); setView("password"); return; } const init = await quickConnectApi.initiateQuickConnect(); const secret = init.data.Secret!; setQuickConnectCode(init.data.Code!); interval = setInterval(async () => { try { const state = await quickConnectApi.getQuickConnectState({ secret }); if (!state.data.Authenticated) return; clearInterval(interval); const auth = await getUserApi(jellyfinApi!).authenticateWithQuickConnect({ quickConnectDto: { Secret: secret }, }); if (!auth.data.AccessToken) { Spicetify.showNotification("Failed to login with Quick Connect!", true); return; } jellyfinApi!.accessToken = auth.data.AccessToken; Spicetify.LocalStorage.set("jellyfin-token", auth.data.AccessToken); const user = await getUserApi(jellyfinApi!).getCurrentUser(); if (user.data.Id) setJellyfinUser(user.data.Id); setView("settings"); } catch { clearInterval(interval); Spicetify.showNotification("Quick Connect polling failed!", true); setView("password"); } }, 2000); })(); return () => clearInterval(interval); }, [view]); if (view === "settings") return (

You're logged in!


); if (view === "url") return (
setUrl(e.target.value)} />

); return (
{view === "quick-connect" ? (
{Array.from({ length: 6 }).map((_, i) => (
{quickConnectCode[i]}
))}
) : ( <>
setUsername(e.target.value)} />
setPassword(e.target.value)} />
)}
); }