import { FocusContext, setFocus, useFocusable, } from "@noriginmedia/norigin-spatial-navigation"; import { useIsMutating, useMutation, useQuery } from "@tanstack/react-query"; import { createFileRoute, useRouter } from "@tanstack/react-router"; import classNames from "classnames"; import { Key, Link, Lock, LogIn, LogOut, ScanQrCode, User, X } from "lucide-react"; import { useEffect, useRef, } from "react"; import { RommLoginDataSchema, RPC_URL } from "@shared/constants"; import toast from "react-hot-toast"; import { OptionSpace } from "../../components/options/OptionSpace"; import { useSettingsForm, useSettingsFormContext } from "../../components/options/SettingsAppForm"; import { Button } from "../../components/options/Button"; import { ContextDialog } from "@/mainview/components/ContextDialog"; import QRCode from "react-qr-code"; import { useJobStatus } from "@/mainview/scripts/utils"; import { useInterval } from "usehooks-ts"; import { TwitchIcon } from "@/mainview/scripts/brandIcons"; import { twitchLoginMutation, twitchLoginVerificationQuery, twitchLogoutMutation } from "@queries/settings"; import { rommGetOptionsQuery, rommLoggedInQuery, rommHostnameQuery, rommLoginMutation, rommLogoutMutation, rommQrLoginMutation, rommUsernameQuery, rommUserQuery, invalidateLogin } from "@queries/romm"; import { systemApi } from "@/mainview/scripts/clientApi"; export const Route = createFileRoute("/settings/accounts")({ component: RouteComponent, }); function LoginQR (data: { id: string, isOpen: boolean, cancel: () => void, url: string; endsAt: Date; startedAt: Date; code?: string; }) { const progressRef = useRef(null); useInterval(() => { if (progressRef.current) { const time = data.endsAt.getTime() - data.startedAt.getTime(); progressRef.current.value = ((data.endsAt.getTime() - new Date().getTime()) / time) * 100; } }, 1000); return data.cancel()} className="flex flex-col justify-center items-center gap-2"> {!!data.code &&

Code: {data.code}

}
; } function TwitchLogin () { const loginStatus = useQuery(twitchLoginVerificationQuery); const loginMutation = useMutation(twitchLoginMutation); const logoutMutation = useMutation({ ...twitchLogoutMutation, onSuccess: () => loginStatus.refetch() }); const { data: loginData, wsRef } = useJobStatus('twitch-login-job', { onEnded: () => loginStatus.refetch() }); return
{loginStatus.isSuccess ?
{loginStatus.data.login}
:
{loginStatus.isError || loginStatus.isRefetchError ? : }
} {loginStatus.isSuccess && } {!!loginData && wsRef.current?.send({ type: 'cancel' })} id='twitch-login-qr' isOpen={true} endsAt={loginData.expires_at} startedAt={loginData.started_at} />}
; } function LoginControls (data: {}) { const user = useQuery(rommUserQuery); const router = useRouter(); const loginMutation = useMutation(rommQrLoginMutation); const { data: statusValue, wsRef } = useJobStatus('login-job'); const { data: loginStatusData } = useQuery(rommLoggedInQuery); const context = useSettingsFormContext({}); const isMutatingRomm = useIsMutating({ mutationKey: ["romm", "auth"] }) > 0; const logoutMutation = useMutation({ ...rommLogoutMutation, onSuccess: async (d, v, r, c) => { await user.refetch(); await invalidateLogin(c.client); await router.navigate({ replace: true }); } }); return
{user.isSuccess ?

Logged In As:

{user.data?.username}
:
{user.isError ? : }
} {loginStatusData?.hasLogin && } {!!statusValue && { setFocus(`qr-login`); wsRef.current?.send({ type: 'cancel' }); }} url={statusValue?.url ?? ''} />}
; } function RouteComponent () { const { focus } = Route.useSearch(); const { ref, focusKey, focusSelf } = useFocusable({ focusKey: "accounts", preferredChildFocusKey: focus }); const { data: hostname } = useQuery(rommHostnameQuery); const { data: username } = useQuery(rommUsernameQuery); const loginForm = useSettingsForm({ defaultValues: { hostname: hostname ?? '', username: username ?? '', password: '' }, onSubmit: async ({ value }) => { await toast.promise(loginMutation.mutateAsync(value), { loading: "Logging In", success: "Logged In", error: e => e?.detail ?? "Error Logging In", }); loginForm.reset(); }, validators: { onChange: RommLoginDataSchema } }); const rommOnline = useQuery(rommGetOptionsQuery()); useEffect(() => { if (focus) { focusSelf({ instant: true }); } }, [focus]); const loginMutation = useMutation(rommLoginMutation); let indicator = ""; if (rommOnline.isError) { indicator = "status-error"; } else if (rommOnline.isSuccess) { indicator = "status-success"; } return ( Twitch Login for IGDB Metadata } id="twitch-login-space" className="justify-end border-0"> ); }