import { FocusContext, FocusDetails, useFocusable, } from "@noriginmedia/norigin-spatial-navigation"; import { QueriesResults, useIsMutating, useMutation, useQuery, UseQueryResult } from "@tanstack/react-query"; import { createFileRoute, useSearch } from "@tanstack/react-router"; import classNames from "classnames"; import { DoorOpen, Key, Link, Lock, User } from "lucide-react"; import { ChangeEventHandler, createContext, FocusEventHandler, HTMLInputTypeAttribute, JSX, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react"; import { client } from "../.."; import { SettingsType } from "../../../shared/constants"; import { getCurrentUserApiUsersMeGetOptions, loginApiLoginPostMutation, logoutApiLogoutPostMutation, statsApiStatsGetOptions, } from "../../../clients/romm/@tanstack/react-query.gen"; import { useToasters } from "../../contexts/ToasterContext"; import { UserSchema } from "../../../clients/romm"; import toast from "react-hot-toast"; import { twMerge } from "tailwind-merge"; export const Route = createFileRoute("/settings/accounts")({ component: RouteComponent, }); const OptionContext = createContext( {} as { focused: boolean; focus: (focusDetails?: FocusDetails | undefined) => void; eventTarget: EventTarget; }, ); function useOptionContext (params?: { onOptionEnterPress?: () => void; }) { const context = useContext(OptionContext); useEffect(() => { if (params?.onOptionEnterPress) { context.eventTarget.addEventListener( "onEnterPress", params.onOptionEnterPress, ); } return () => { if (params?.onOptionEnterPress) { context.eventTarget.removeEventListener( "onEnterPress", params.onOptionEnterPress, ); } }; }, [context.eventTarget]); return context; } function OptionSpace (data: { id?: string; className?: string; focusable?: boolean; children: JSX.Element; label?: string | JSX.Element; }) { const eventTarget = useMemo(() => new EventTarget(), []); const { ref, focused, focusSelf, focusKey, hasFocusedChild } = useFocusable({ focusKey: data.id, focusable: data.focusable !== false, trackChildren: true, onEnterPress () { eventTarget.dispatchEvent(new CustomEvent("onEnterPress")); }, }); return (
  • {typeof data.label === "string" ? ( ) : ( data.label )} {data.children}
  • ); } function OptionInput (data: { name: string; type: HTMLInputTypeAttribute; className?: string; placeholder?: string; icon?: JSX.Element; value?: string; onBlur?: FocusEventHandler; onChange?: ChangeEventHandler; }) { const inputRef = useRef(null); const option = useOptionContext({ onOptionEnterPress () { inputRef.current?.focus(); }, }); return ( ); } type KeysWithValueAssignableTo = { [K in keyof T]: Exclude extends Value ? K : never; }[keyof T]; function Option (data: { label: string; id: KeysWithValueAssignableTo; type: HTMLInputTypeAttribute; placeholder?: string; icon?: JSX.Element; }) { const [dirty, setDirty] = useState(false); const [localValue, setLocalValue] = useState(); useQuery({ enabled: !!data.id, queryKey: ["setting", data.id], queryFn: async () => { const value = (await client.api.settings({ id: data.id! }).get()).data?.value; if (!dirty) { setLocalValue(String(value)); } return value; }, }); const setSettingMultation = useMutation({ mutationKey: ["setting", data.id], mutationFn: (value: any) => client.api.settings({ id: data.id! }).post({ value }).then(d => d.status) }); const handleSave = useCallback(() => { if (dirty) { setDirty(false); setSettingMultation.mutate(localValue); } }, [dirty, setDirty, localValue]); return ( { setLocalValue(e.currentTarget.value); setDirty(true); }} value={localValue} /> ); } function Button (data: { children?: any, disabled?: boolean, type: "reset" | "button" | "submit" | undefined; } & InteractParams & FocusParams) { const { ref, focused } = useFocusable({ focusKey: data.type, onEnterPress: data.onAction, onFocus: data.onFocus }); return ; } function LoginControls (data: { user: UseQueryResult; }) { const isMutatingRomm = useIsMutating({ mutationKey: ["romm", "auth"] }) > 0; const logoutMutation = useMutation({ mutationKey: ["romm", "auth", "logout"], mutationFn: () => window.cookieStore.delete({ name: "romm_session" }), onSuccess: async (d, v, r, c) => { c.client.invalidateQueries({ queryKey: ["romm", "auth"] }); } }); return
    {data.user.isError &&
    } {data.user.isSuccess &&
    Logged In As: {data.user.data?.username}
    }
    ; } function RouteComponent () { const { focus } = Route.useSearch(); const { ref, focusKey, focusSelf } = useFocusable({ preferredChildFocusKey: focus }); const rommOnline = useQuery({ ...statsApiStatsGetOptions(), refetchInterval: 30000, retry: false, }); const user = useQuery({ ...getCurrentUserApiUsersMeGetOptions(), queryKey: ['romm', 'auth', "login"], refetchOnWindowFocus: false, retry: 0 }); useEffect(() => { if (focus) { focusSelf(); } }, [focus]); const loginMutation = useMutation({ mutationKey: ["romm", "login"], ...loginApiLoginPostMutation(), onSuccess: (d, v, r, c) => { c.client.invalidateQueries({ queryKey: ['romm', 'auth'] }); }, onError: (e) => { console.error(e); }, }); let indicator = ""; if (rommOnline.isError) { indicator = "status-error"; } else if (rommOnline.isSuccess) { indicator = "status-success"; } return (

      Romm

    ); }