refactor: Removed the use of d.ts files to support SDK generation for public plugins

This commit is contained in:
Simeon Radivoev 2026-05-05 01:21:22 +03:00
parent 06b7e4074d
commit 2683d46b16
Signed by: simeonradivoev
GPG key ID: 7611A451D2A5D37A
114 changed files with 408 additions and 257 deletions

View file

@ -1,5 +1,5 @@
import { doesFocusableExist, FocusDetails, getCurrentFocusKey } from "@noriginmedia/norigin-spatial-navigation";
import { useEffect, useLayoutEffect } from "react";
import { useEffect } from "react";
export function AutoFocus (data: {
parentKey?: string;

View file

@ -1,4 +1,4 @@
import { FocusDetails, useFocusable } from "@noriginmedia/norigin-spatial-navigation";
import { useFocusable } from "@noriginmedia/norigin-spatial-navigation";
import classNames from "classnames";
import { JSX } from "react";
import { twMerge } from "tailwind-merge";

View file

@ -3,7 +3,6 @@ import
FocusContext,
useFocusable,
} from "@noriginmedia/norigin-spatial-navigation";
import { GameMeta } from "../../shared/constants";
import CardElement, { GameCardParams } from "./CardElement";
import { JSX } from "react";
import { twMerge } from "tailwind-merge";

View file

@ -1,6 +1,6 @@
import { FocusContext, useFocusable } from "@noriginmedia/norigin-spatial-navigation";
import { Home, TriangleAlert } from "lucide-react";
import { GamePadButtonCode, useShortcutContext, useShortcuts } from "../scripts/shortcuts";
import { GamePadButtonCode, useShortcuts } from "../scripts/shortcuts";
import { FloatingShortcuts } from "./Shortcuts";
import { Button } from "./options/Button";
import { useEffect } from "react";

View file

@ -86,7 +86,6 @@ function List (data: {
function NewFolderInput (data: { id: string, name: string | undefined, setName: (name: string) => void; className?: string; })
{
const inputRef = useRef<HTMLInputElement>(null);
const { control } = useActiveControl();
const { ref, focused, focusSelf } = useFocusable({
focusKey: data.id,
onEnterPress: () => inputRef.current?.focus(),

View file

@ -4,6 +4,7 @@ import { FileQuestion, HardDrive, Store } from "lucide-react";
import { JSX } from "react";
import { FOCUS_KEYS } from "../scripts/types";
import { useRouter } from "@tanstack/react-router";
import { FrontEndGameType, FrontEndId } from "@/shared/types";
export default function FrontEndGameCard (data: { index: number, game: FrontEndGameType; showSource?: boolean; } & FocusParams & InteractParams)
{

View file

@ -1,12 +1,13 @@
import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
import { useSuspenseQuery } from "@tanstack/react-query";
import { GameMetaExtra, CardList } from "./CardList";
import { DefaultRommStaleTime, GameListFilterType, RPC_URL } from "@shared/constants";
import { useNavigate } from "@tanstack/react-router";
import { HardDrive } from "lucide-react";
import { JSX, Ref, useContext, useEffect } from "react";
import { JSX, useContext } from "react";
import { useLocalSetting } from "../scripts/utils";
import { AnimatedBackgroundContext } from "../scripts/contexts";
import { allGamesQuery } from "@queries/romm";
import { FrontEndGameType, FrontEndId } from "@/shared/types";
export interface GameListParams extends FocusParams
{
@ -95,7 +96,7 @@ export function GameList (data: GameListParams)
const previewUrls = g.path_covers.map(c =>
{
const url = new URL(`${RPC_URL(__HOST__)}${c}`);
const url = c.startsWith("http") ? new URL(c) : new URL(`${RPC_URL(__HOST__)}${c}`);
url.searchParams.delete('ts');
return url;
});
@ -103,7 +104,7 @@ export function GameList (data: GameListParams)
let platformUrl: URL | undefined = undefined;
if (g.path_platform_cover)
{
platformUrl = new URL(`${RPC_URL(__HOST__)}${g.path_platform_cover}`);
platformUrl = g.path_platform_cover.startsWith("http") ? new URL(g.path_platform_cover) : new URL(`${RPC_URL(__HOST__)}${g.path_platform_cover}`);
platformUrl.searchParams.set('width', "64");
}

View file

@ -40,7 +40,7 @@ const KeyElements: Record<string, JSX.Element> = {
'←': <ArrowLeft />,
'→': <ArrowRight />,
};
const DZ = 0.22, TH = 0.85, NS = 'http://www.w3.org/2000/svg';
const DZ = 0.22;
function ang (x: number, y: number)
{

View file

@ -19,7 +19,6 @@ function SearchInput (data: {
onSubmit: (search: string | undefined) => void;
} & FocusParams)
{
const { control } = useActiveControl();
const { ref, focusKey } = useFocusable({
onBlur: () => inputRef.current?.blur(),
onFocus: (l, p, d) =>

View file

@ -1,6 +1,6 @@
import { FocusContext, useFocusable } from "@noriginmedia/norigin-spatial-navigation";
import { Home, TriangleAlert } from "lucide-react";
import { GamePadButtonCode, useShortcutContext, useShortcuts } from "../scripts/shortcuts";
import { GamePadButtonCode, useShortcuts } from "../scripts/shortcuts";
import { Button } from "./options/Button";
import { useEffect } from "react";
import { useRouter } from "@tanstack/react-router";

View file

@ -1,4 +1,5 @@
import { RPC_URL } from "@/shared/constants";
import { FrontendNotification } from "@/shared/types";
import { Clock, CloudUpload, Save } from "lucide-react";
import { useEffect } from "react";
import toast, { ToastOptions } from "react-hot-toast";

View file

@ -3,8 +3,8 @@ import { useNavigate } from "@tanstack/react-router";
import { DefaultRommStaleTime, RPC_URL } from "@shared/constants";
import { CardList, GameMetaExtra } from "./CardList";
import { rommApi } from "../scripts/clientApi";
import { JSX, useMemo, useState } from "react";
import { Gamepad2, HardDrive } from "lucide-react";
import { JSX, useMemo } from "react";
import { HardDrive } from "lucide-react";
import { mobileCheck } from "../scripts/utils";
import { twMerge } from "tailwind-merge";
import placeholder from '../assets/256x256.png?url';

View file

@ -6,6 +6,7 @@ import { useFocusable, FocusContext } from "@noriginmedia/norigin-spatial-naviga
import { ArrowDownAz, ClockArrowDown, CalendarArrowDown, Rocket, HardDrive, SortDesc, User, Drama, FunnelX, Store } from "lucide-react";
import { sourceIconMap } from "./Constants";
import { useContextDialog, ContextList, DialogEntry } from "./ContextDialog";
import { FrontEndFilterLists } from "@/shared/types";
function FilterButton (data: {
id: string,

View file

@ -1,4 +1,4 @@
import { Ref, RefObject } from 'react';
import { Ref } from 'react';
import './dots.css';
export default function DotsLoading (data: { ref?: Ref<any>; })

View file

@ -1,4 +1,5 @@
import { FrontEndGameTypeDetailed, FrontEndGameTypeDetailedAchievement } from "@/shared/types";
import { useFocusable } from "@noriginmedia/norigin-spatial-navigation";
import { Medal } from "lucide-react";

View file

@ -10,6 +10,7 @@ import ActionButton from "./ActionButton";
import { useLocalStorage } from "usehooks-ts";
import FocusTooltip from "../FocusTooltip";
import { useBlocker, useNavigate, useRouter } from "@tanstack/react-router";
import { FrontEndGameTypeDetailed } from "@/shared/types";
function AchievementsInfo (data: { game: FrontEndGameTypeDetailed; } & InteractParams)
{

View file

@ -2,7 +2,7 @@ import { scrollIntoViewHandler } from "@/mainview/scripts/utils";
import { RPC_URL } from "@/shared/constants";
import { FocusContext, useFocusable } from "@noriginmedia/norigin-spatial-navigation";
import classNames from "classnames";
import { Clock, CloudBackup, CloudDownload, CloudUpload, Gamepad2, HardDrive, Store, TriangleAlert } from "lucide-react";
import { Clock, CloudDownload, CloudUpload, HardDrive, TriangleAlert } from "lucide-react";
import prettyBytes from "pretty-bytes";
import { JSX } from "react";
import ActionButtons from "./ActionButtons";
@ -10,6 +10,7 @@ import prettyMilliseconds from 'pretty-ms';
import { useQuery } from "@tanstack/react-query";
import { validateSourceQuery } from "@/mainview/scripts/queries/romm";
import { sourceIconMap } from "../Constants";
import { FrontEndGameTypeDetailed } from "@/shared/types";
export function DetailElement (data: { icon: JSX.Element; tooltip?: string | null, children?: any | any[]; })
{

View file

@ -1,4 +1,4 @@
import { gameLookup } from "@/mainview/scripts/queries/romm";
import { FocusContext, useFocusable } from "@noriginmedia/norigin-spatial-navigation";
import { useQuery } from "@tanstack/react-query";
import { Check, Search } from "lucide-react";
@ -6,6 +6,8 @@ import HeaderSearchField from "../HeaderSearchField";
import { GamePadButtonCode, useShortcuts } from "@/mainview/scripts/shortcuts";
import { scrollIntoViewHandler } from "@/mainview/scripts/utils";
import { FOCUS_KEYS } from "@/mainview/scripts/types";
import { FrontEndId, GameLookup } from "@/shared/types";
import { gameLookupQuery } from "@/mainview/scripts/queries/romm";
function Result (data: {
match: GameLookup;
@ -54,7 +56,7 @@ function SearchField (data: { setSearch: (search: string | undefined) => void; s
</div>;
}
export default function GameLookup (data: {
export default function GameLookupElement (data: {
search: string | undefined,
setSearch: (search: string | undefined) => void,
onSelect: (match: GameLookup) => void;
@ -62,7 +64,7 @@ export default function GameLookup (data: {
selected?: FrontEndId;
})
{
const { data: lookups, isFetching } = useQuery({ ...gameLookup(data.search), staleTime: 1000 * 60 * 60 });
const { data: lookups, isFetching } = useQuery({ ...gameLookupQuery(data.search), staleTime: 1000 * 60 * 60 });
return <div>
<SearchField setSearch={data.setSearch} search={data.search} />

View file

@ -11,6 +11,7 @@ import ActionButton from "./ActionButton";
import { useRouter } from "@tanstack/react-router";
import { DownloadSourceType } from "@/shared/constants";
import { GamePadButtonCode, Shortcut, useShortcuts } from "@/mainview/scripts/shortcuts";
import { CommandEntry, FrontEndGameTypeDetailed } from "@/shared/types";
export default function MainActions (data: { game?: FrontEndGameTypeDetailed, source: string, id: string; })
{

View file

@ -3,6 +3,7 @@ import { PathSettingsOptionBase, PathSettingsOptionParams } from "./PathSettings
import { useMutation, useQuery } from "@tanstack/react-query";
import { changeDownloadsMutation, getSettingQuery } from "@queries/settings";
import { SettingsType } from "@/shared/constants";
import { KeysWithValueAssignableTo } from "@/shared/types";
export default function DownloadDirectoryOption (data: PathSettingsOptionParams & { id: KeysWithValueAssignableTo<SettingsType, string>; })
{

View file

@ -5,7 +5,6 @@ import { useFocusable } from "@noriginmedia/norigin-spatial-navigation";
import { CheckIcon, X } from "lucide-react";
import { oneShot } from "@/mainview/scripts/audio/audio";
import { GamePadButtonCode, Shortcut, useShortcuts } from "@/mainview/scripts/shortcuts";
import useActiveControl from "@/mainview/scripts/gamepads";
export function OptionInput (data: {
name: string;
@ -35,7 +34,6 @@ export function OptionInput (data: {
}
oneShot('click');
};
const { control } = useActiveControl();
const [inputFocused, setInputFocused] = useState(false);
const inputRef = useRef<HTMLInputElement>(null);
const { ref, focusKey } = useFocusable({

View file

@ -9,6 +9,7 @@ import { ContextDialog } from "../ContextDialog";
import FilePicker from "../FilePicker";
import { setFocus } from "@noriginmedia/norigin-spatial-navigation";
import { getSettingQuery, setSettingMutation } from "@queries/settings";
import { KeysWithValueAssignableTo } from "@/shared/types";
export interface PathSettingsOptionParams
{

View file

@ -4,6 +4,7 @@ import { useMutation, useQuery } from "@tanstack/react-query";
import { OptionSpace } from "./OptionSpace";
import { getSettingQuery, setSettingMutation } from "@queries/settings";
import { OptionDropdown } from "./OptionDropdown";
import { KeysWithValueAssignableTo } from "@/shared/types";
export function SettingsDropdown (data: {
label: string;

View file

@ -4,6 +4,7 @@ import { useMutation, useQuery } from "@tanstack/react-query";
import { OptionSpace } from "./OptionSpace";
import { OptionInput } from "./OptionInput";
import { getSettingQuery, setSettingMutation } from "@queries/settings";
import { KeysWithValueAssignableTo } from "@/shared/types";
export function SettingsOption (data: {
label: string;

View file

@ -12,6 +12,7 @@ import { StoreEmulatorCard } from "./StoreEmulatorCard";
import { FOCUS_KEYS } from "@/mainview/scripts/types";
import Carousel from "../Carousel";
import { useRouter } from "@tanstack/react-router";
import { FrontEndEmulator } from "@/shared/types";
function SeeAllCard (data: { id: string; onAction: () => void; onFocus?: (details: { node: HTMLElement, instant?: boolean; }) => void; })
{

View file

@ -10,6 +10,7 @@ import FrontEndGameCard from "../FrontEndGameCard";
import { FOCUS_KEYS } from "@/mainview/scripts/types";
import Carousel from "../Carousel";
import { twMerge } from "tailwind-merge";
import { FrontEndGameType, FrontEndId } from "@/shared/types";
export function GamesSection (data: {
games?: FrontEndGameType[];

View file

@ -8,6 +8,7 @@ import { GamePadButtonCode, useShortcuts } from "@/mainview/scripts/shortcuts";
import { RPC_URL } from "@/shared/constants";
import { FOCUS_KEYS } from "@/mainview/scripts/types";
import { oneShot } from "@/mainview/scripts/audio/audio";
import { FrontEndEmulator } from "@/shared/types";
// ── Single missing-emulator card ───────────────────────────────────────────
interface MissingCardProps

View file

@ -10,6 +10,7 @@ import { JSX } from "react";
import { oneShot } from "@/mainview/scripts/audio/audio";
import { useQuery } from "@tanstack/react-query";
import { getUpdateInfoForEmulator } from "@/mainview/scripts/queries/store";
import { FrontEndEmulator } from "@/shared/types";
export const emulatorStatusIcons: Record<string, JSX.Element> = {
store: <Store />,

View file

@ -5,7 +5,7 @@ import z from 'zod';
import { RefObject, useEffect, useRef, useState } from 'react';
import { FocusContext, useFocusable } from '@noriginmedia/norigin-spatial-navigation';
import { ButtonStyle } from '../components/options/Button';
import { CloudDownload, DoorOpen, RefreshCw, Save, Undo } from 'lucide-react';
import { CloudDownload, DoorOpen, RefreshCw, Undo } from 'lucide-react';
import { GamePadButtonCode, useShortcuts } from '../scripts/shortcuts';
import { FloatingShortcuts } from '../components/Shortcuts';
import { useEventListener } from 'usehooks-ts';

View file

@ -6,8 +6,8 @@ import { Calendar, Folder, Gamepad2, Image, Info, TriangleAlert, Trophy } from "
import { HeaderUI, StickyHeaderUI } from "../../components/Header";
import { AnimatedBackground } from "../../components/AnimatedBackground";
import { useQuery } from "@tanstack/react-query";
import Shortcuts, { FloatingShortcuts } from "../../components/Shortcuts";
import { GamePadButtonCode, useShortcutContext, useShortcuts } from "@/mainview/scripts/shortcuts";
import { FloatingShortcuts } from "../../components/Shortcuts";
import { GamePadButtonCode, useShortcuts } from "@/mainview/scripts/shortcuts";
import Screenshots from "@/mainview/components/Screenshots";
import { HandleGoBack, scrollIntoViewHandler, useOnNavigateBack } from "@/mainview/scripts/utils";
import { FilterUI } from "@/mainview/components/Filters";
@ -23,8 +23,8 @@ import { GamesSection } from "@/mainview/components/store/GamesSection";
import Details from "@/mainview/components/game/Details";
import { AutoFocus } from "@/mainview/components/AutoFocus";
import SelectMenu from "@/mainview/components/SelectMenu";
import { en } from "zod/v4/locales";
import { IGDBIcon } from "@/mainview/scripts/brandIcons";
import { FrontEndGameTypeDetailed } from "@/shared/types";
export const Route = createFileRoute("/game/$source/$id")({
loader: async ({ params, context }) =>

View file

@ -1,6 +1,6 @@
import { AutoFocus } from '@/mainview/components/AutoFocus';
import { OptionElement } from '@/mainview/components/ContextDialog';
import GameLookup from '@/mainview/components/game/GameLookup';
import GameLookupElement from '@/mainview/components/game/GameLookup';
import { StickyHeaderUI } from '@/mainview/components/Header';
import LoadingScreen from '@/mainview/components/LoadingScreen';
import { Button } from '@/mainview/components/options/Button';
@ -208,7 +208,7 @@ function Lookup ()
navigate({ to: '/game/add', search: { ...state, selectedGame: { source, id }, platformId: undefined, search, step: 2 }, replace: true });
oneShot('openGeneric');
};
return <GameLookup
return <GameLookupElement
showPlatforms
selected={state.selectedGame}
search={search}

View file

@ -1,6 +1,6 @@
import { AnimatedBackground } from '@/mainview/components/AnimatedBackground';
import { AutoFocus } from '@/mainview/components/AutoFocus';
import GameLookup from '@/mainview/components/game/GameLookup';
import GameLookupElement from '@/mainview/components/game/GameLookup';
import { StickyHeaderUI } from '@/mainview/components/Header';
import { FloatingShortcuts } from '@/mainview/components/Shortcuts';
import { customUpdateMutation, gameInvalidationQuery, gameQuery } from '@/mainview/scripts/queries/romm';
@ -20,7 +20,6 @@ function RouteComponent ()
{
const { source, id } = Route.useParams();
const [search, setSearch] = useState<string | undefined>(undefined);
const navigate = useNavigate();
const router = useRouter();
const { data: game } = useQuery(gameQuery(source, id));
@ -47,7 +46,7 @@ function RouteComponent ()
<FocusContext value={focusKey}>
<div className='flex flex-col z-10 overflow-y-scroll'>
<StickyHeaderUI ref={ref} />
<GameLookup
<GameLookupElement
search={search}
setSearch={setSearch}
onSelect={l =>

View file

@ -3,23 +3,17 @@ import
{
Gamepad2,
Settings,
MessageSquare,
Image,
Search,
Power,
OctagonAlert,
Maximize,
Store,
LayoutGrid,
PlusCircle,
Plus,
LucideIcon,
} from "lucide-react";
import
{
createFileRoute,
PathParamOptions,
ToPathOption,
useRouter,
} from "@tanstack/react-router";
import { useMutation, useQueryClient } from "@tanstack/react-query";
@ -41,11 +35,11 @@ import SaveScroll from "../components/SaveScroll";
import { ErrorBoundary, useErrorBoundary } from "react-error-boundary";
import { twMerge } from "tailwind-merge";
import { PlatformsList } from "../components/PlatformsList";
import { GamePadButtonCode, useShortcutContext, useShortcuts } from "../scripts/shortcuts";
import { GamePadButtonCode, useShortcuts } from "../scripts/shortcuts";
import z from "zod";
import CollectionList from "../components/CollectionList";
import { zodValidator } from '@tanstack/zod-adapter';
import { mobileCheck, scrollIntoNearestParent, scrollIntoViewHandler, useDragScroll } from "../scripts/utils";
import { mobileCheck, scrollIntoViewHandler, useDragScroll } from "../scripts/utils";
import { AnimatedBackgroundContext } from "../scripts/contexts";
import Carousel from "../components/Carousel";
import { closeMutation } from "@queries/system";
@ -56,6 +50,7 @@ import SelectMenu from "../components/SelectMenu";
import HeaderSearchField from "../components/HeaderSearchField";
import CardElement from "../components/CardElement";
import { Router } from "..";
import { FrontEndId } from "@/shared/types";
export const Route = createFileRoute("/")({
component: ConsoleHomeUI,

View file

@ -1,12 +1,11 @@
import { AnimatedBackground } from '@/mainview/components/AnimatedBackground';
import { createFileRoute, useBlocker, useRouter } from '@tanstack/react-router';
import DotsLoading from '../components/backgrounds/dots';
import { GamePadButtonCode, useShortcutContext, useShortcuts } from '../scripts/shortcuts';
import { GamePadButtonCode, useShortcuts } from '../scripts/shortcuts';
import { useFocusable } from '@noriginmedia/norigin-spatial-navigation';
import Shortcuts, { FloatingShortcuts } from '../components/Shortcuts';
import { FloatingShortcuts } from '../components/Shortcuts';
import { useJobStatus } from '../scripts/utils';
import { useEffect, useRef } from 'react';
import { rommApi } from '../scripts/clientApi';
import { useRef } from 'react';
export const Route = createFileRoute('/launcher/$source/$id')({
component: RouteComponent,

View file

@ -1,11 +1,9 @@
import { Button } from '@/mainview/components/options/Button';
import { FocusContext, useFocusable } from '@noriginmedia/norigin-spatial-navigation';
import { checkUpdateMutation, hasUpdateQuery, systemInfoQuery, updateMutation } from '@queries/system';
import { useMutation, useQuery } from '@tanstack/react-query';
import { systemInfoQuery } from '@queries/system';
import { useQuery } from '@tanstack/react-query';
import { createFileRoute } from '@tanstack/react-router';
import { ArrowUpCircle, CircleFadingArrowUp, RefreshCcw } from 'lucide-react';
import prettyBytes from 'pretty-bytes';
export const Route = createFileRoute('/settings/about')({

View file

@ -13,6 +13,7 @@ import { systemApi } from '@/mainview/scripts/clientApi';
import useActiveControl from '@/mainview/scripts/gamepads';
import { changeDownloadsMutation } from '@queries/settings';
import { downloadDrivesQuery } from '@/mainview/scripts/queries/system';
import { DownloadsDrive } from '@/shared/types';
export const Route = createFileRoute('/settings/directories')({
component: RouteComponent,

View file

@ -20,6 +20,7 @@ import { FOCUS_KEYS } from '@/mainview/scripts/types';
import { scrollIntoNearestParent, scrollIntoViewHandler, useDragScroll } from '@/mainview/scripts/utils';
import { SettingsOption } from '@/mainview/components/options/SettingsOption';
import { SettingsDropdown } from '@/mainview/components/options/SettingsDropdown';
import { FrontEndEmulator } from '@/shared/types';
export const Route = createFileRoute('/settings/emulators')({
component: RouteComponent,

View file

@ -5,15 +5,15 @@ import { OptionDropdown } from '@/mainview/components/options/OptionDropdown';
import { OptionInput } from '@/mainview/components/options/OptionInput';
import { OptionSpace } from '@/mainview/components/options/OptionSpace';
import { RoundButton } from '@/mainview/components/RoundButton';
import { getAllPluginsQuery, getPluginDetailsQuery } from '@/mainview/scripts/queries/plugins';
import { getPluginDetailsQuery } from '@/mainview/scripts/queries/plugins';
import { getPluginActionsQuery, getPluginSettingQuery, getPluginSettingsDefinitionQuery, pluginActionMutation, setPluginSettingMutation } from '@/mainview/scripts/queries/settings';
import { GamePadButtonCode, useShortcuts } from '@/mainview/scripts/shortcuts';
import { scrollIntoViewHandler } from '@/mainview/scripts/utils';
import { FocusContext, useFocusable } from '@noriginmedia/norigin-spatial-navigation';
import { useMutation, useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-query';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { createFileRoute, useNavigate } from '@tanstack/react-router';
import { JSONSchema7 } from 'json-schema';
import { ArrowLeft, CirclePlay, Play, Settings2, SettingsIcon } from 'lucide-react';
import { ArrowLeft, CirclePlay, Settings2 } from 'lucide-react';
import toast from 'react-hot-toast';
export const Route = createFileRoute('/settings/plugin/$source')({
component: RouteComponent,

View file

@ -1,11 +1,11 @@
import { AutoFocus } from '@/mainview/components/AutoFocus';
import { pluginCategoryIcons, pluginCategoryPriorities } from '@/mainview/components/Constants';
import { Button } from '@/mainview/components/options/Button';
import { OptionInput } from '@/mainview/components/options/OptionInput';
import { OptionSpace } from '@/mainview/components/options/OptionSpace';
import { RoundButton } from '@/mainview/components/RoundButton';
import { enablePluginMutation, getAllPluginsQuery } from '@/mainview/scripts/queries/plugins';
import { GamePadButtonCode, Shortcut } from '@/mainview/scripts/shortcuts';
import { FrontendPlugin } from '@/shared/types';
import { FocusContext, useFocusable } from '@noriginmedia/norigin-spatial-navigation';
import { useMutation, useQuery } from '@tanstack/react-query';
import { createFileRoute, useNavigate } from '@tanstack/react-router';

View file

@ -7,7 +7,6 @@ import
{
Outlet,
createFileRoute,
useMatch,
useMatchRoute,
useRouter,
useRouterState,
@ -29,8 +28,8 @@ import { JSX, useMemo } from "react";
import { twMerge } from "tailwind-merge";
import z from "zod";
import { SettingsSchema } from "../../../shared/constants";
import { GamePadButtonCode, useShortcutContext, useShortcuts } from "@/mainview/scripts/shortcuts";
import Shortcuts, { FloatingShortcuts } from "@/mainview/components/Shortcuts";
import { GamePadButtonCode, useShortcuts } from "@/mainview/scripts/shortcuts";
import Shortcuts from "@/mainview/components/Shortcuts";
import { HandleGoBack } from "@/mainview/scripts/utils";
import { AutoFocus } from "@/mainview/components/AutoFocus";
import { oneShot } from "@/mainview/scripts/audio/audio";

View file

@ -5,12 +5,12 @@ import
FocusContext,
} from "@noriginmedia/norigin-spatial-navigation";
import { createFileRoute, useNavigate, useRouter } from "@tanstack/react-router";
import { GamePadButtonCode, useShortcutContext, useShortcuts } from "@/mainview/scripts/shortcuts";
import Shortcuts, { FloatingShortcuts } from "@/mainview/components/Shortcuts";
import { GamePadButtonCode, useShortcuts } from "@/mainview/scripts/shortcuts";
import { FloatingShortcuts } from "@/mainview/components/Shortcuts";
import { AnimatedBackground } from "@/mainview/components/AnimatedBackground";
import { rommApi, systemApi } from "@/mainview/scripts/clientApi";
import { Button } from "@/mainview/components/options/Button";
import { ChevronDown, CircleFadingArrowUp, CloudUpload, Cpu, Download, Fullscreen, Gamepad2, Info, Monitor, Puzzle, Save, Settings, Settings2, Terminal, Trash2, TriangleAlert, WandSparkles } from "lucide-react";
import { ChevronDown, CircleFadingArrowUp, CloudUpload, Cpu, Download, Fullscreen, Gamepad2, Info, Monitor, Puzzle, Settings, Settings2, Terminal, Trash2, TriangleAlert, WandSparkles } from "lucide-react";
import { ContextList, DialogEntry, useContextDialog } from "@/mainview/components/ContextDialog";
import { RPC_URL } from "@/shared/constants";
import Screenshots from "@/mainview/components/Screenshots";
@ -29,6 +29,7 @@ import FocusTooltip from "@/mainview/components/FocusTooltip";
import { AutoFocus } from "@/mainview/components/AutoFocus";
import { FilterUI } from "@/mainview/components/Filters";
import Markdown from "react-markdown";
import { FrontEndEmulatorDetailed } from "@/shared/types";
export const Route = createFileRoute('/store/details/emulator/$id')({
component: RouteComponent,

View file

@ -1,6 +1,6 @@
import { createFileRoute, useSearch } from '@tanstack/react-router';
import { createFileRoute } from '@tanstack/react-router';
import { Joystick } from 'lucide-react';
import { useContext, useEffect } from 'react';
import { FocusContext, getCurrentFocusKey, useFocusable } from '@noriginmedia/norigin-spatial-navigation';

View file

@ -1,13 +1,11 @@
import { FocusContext, getCurrentFocusKey, useFocusable } from '@noriginmedia/norigin-spatial-navigation';
import { createFileRoute, useNavigate, useSearch } from '@tanstack/react-router';
import { createFileRoute, useNavigate } from '@tanstack/react-router';
import { Gamepad2, HardDrive } from 'lucide-react';
import { JSX, useContext, useEffect, useState } from 'react';
import { useInfiniteQuery, useQuery, useQueryClient } from '@tanstack/react-query';
import FrontEndGameCard from '@/mainview/components/FrontEndGameCard';
import { JSX, useEffect } from 'react';
import { useInfiniteQuery, useQuery } from '@tanstack/react-query';
import { GetFocusedElement } from '@/mainview/scripts/spatialNavigation';
import LoadMoreButton from '@/mainview/components/LoadMoreButton';
import { storeGamesInfiniteQuery } from '@queries/store';
import { StoreContext } from '@/mainview/scripts/contexts';
import InvalidStoreError from '@/mainview/components/store/InvalidStoreError';
import { CardList, GameMetaExtra } from '@/mainview/components/CardList';
import { GameListFilterType, RPC_URL } from '@/shared/constants';
@ -16,6 +14,7 @@ import { zodValidator } from '@tanstack/zod-adapter';
import z from 'zod';
import SideFilters from '@/mainview/components/SideFilters';
import { gameFiltersQuery } from '@/mainview/scripts/queries/romm';
import { FrontEndGameType } from '@/shared/types';
export const Route = createFileRoute('/store/tab/games')({
component: RouteComponent,
@ -91,7 +90,7 @@ function RouteComponent ()
const previewUrls = g.path_covers.map(c =>
{
const url = new URL(`${RPC_URL(__HOST__)}${c}`);
const url = c.startsWith('http') ? new URL(c) : new URL(`${RPC_URL(__HOST__)}${c}`);
url.searchParams.delete('ts');
return url;
});

View file

@ -16,6 +16,7 @@ import { useQuery } from '@tanstack/react-query';
import { autoEmulatorsQuery } from '@queries/settings';
import { storeEmulatorsRecommendedQuery, storeFeaturedGamesQuery } from '@queries/store';
import ImageWithFallbacks from '@/mainview/components/ImageWithFallbacks';
import { FrontEndGameTypeDetailed } from '@/shared/types';
export const Route = createFileRoute('/store/tab/')({
component: RouteComponent

View file

@ -37,10 +37,6 @@ function sinRandom ()
return Math.sin(new Date().getMilliseconds() / 1000 * Math.PI);
}
function cosRandom ()
{
return Math.sin(new Date().getMilliseconds() / 1000 * Math.PI);
}
function random ()
{

View file

@ -2,6 +2,7 @@ import { SystemInfoType } from "@/shared/constants";
import { Direction, FocusDetails } from "@noriginmedia/norigin-spatial-navigation";
import { createContext } from "react";
import { Shortcut } from "./shortcuts";
import { Drive } from "@/shared/types";
export const StoreContext = createContext({} as {
showDetails: (type: 'emulator' | 'game', source: string, id: string, focusSource: string) => void;

View file

@ -3,6 +3,7 @@ import { rommApi, settingsApi } from "../clientApi";
import { InvalidateQueryFilters, mutationOptions, QueryClient, QueryFilters, queryOptions } from "@tanstack/react-query";
import z from "zod";
import { statsApiStatsGetOptions } from "@/clients/romm/@tanstack/react-query.gen";
import { FrontEndId } from "@/shared/types";
export const allGamesQuery = (filter?: GameListFilterType) => queryOptions({
queryKey: ['games', filter ?? 'all'],
@ -180,7 +181,7 @@ export const gameInvalidationQuery = (source: string, id: string): QueryFilters
export const validateSourceQuery = (source: string, id: string) => queryOptions({
queryKey: ["game", source, id, "validate"], queryFn: async () =>
{
const { data, error } = await rommApi.api.romm.game({ source })({ id }).validate.get();
const { data } = await rommApi.api.romm.game({ source })({ id }).validate.get();
return data;
}
});
@ -237,7 +238,7 @@ export const gameFiltersQuery = (filters: { source?: string; }) => queryOptions(
}
});
export const gameLookup = (search: string | undefined) => queryOptions({
export const gameLookupQuery = (search: string | undefined) => queryOptions({
queryKey: ['game', 'lookup', search],
queryFn: async () =>
{

View file

@ -1,6 +1,7 @@
import { infiniteQueryOptions, mutationOptions, queryOptions } from "@tanstack/react-query";
import { rommApi, storeApi } from "../clientApi";
import { GameListFilterType } from "@/shared/constants";
import { FrontEndGameType } from "@/shared/types";
export const storeEmulatorsQuery = (filters: { search?: string; }) => queryOptions({

View file

@ -1,3 +1,5 @@
import { FrontEndId } from "@/shared/types";
export const FOCUS_KEYS = {
NAV_CATEGORIES: "NAV_CATEGORIES",
NAV_CATEGORY: (cat: string) => `NAV_CAT_${cat}`,

View file

@ -1,5 +1,5 @@
import { LocalSettingsSchema, LocalSettingsType } from "@/shared/constants";
import { DependencyList, FocusEventHandler, RefObject, useEffect, useRef, useState } from "react";
import { DependencyList, RefObject, useEffect, useRef, useState } from "react";
import { useLocalStorage } from "usehooks-ts";
import { jobsApi, systemApi } from "./clientApi";
import { JobsAPIType } from "@/bun/api/rpc";

View file

@ -2,7 +2,7 @@ import { settingsApi } from "./clientApi";
const handleResize = () =>
{
settingsApi.api.settings({ id: 'windowSize' }).post({ value: { width: window.innerWidth, height: window.innerHeight } });
settingsApi.api.settings.local({ id: 'windowSize' }).post({ value: { width: window.innerWidth, height: window.innerHeight } });
};
window.addEventListener("resize", handleResize);
import.meta.hot?.dispose(() => window.removeEventListener('resize', handleResize));
@ -13,7 +13,7 @@ var screenPositionInternal: NodeJS.Timeout = setInterval(() =>
{
if (lastWindowPosX != window.screenX || lastWindowPosY != window.screenY)
{
settingsApi.api.settings({ id: 'windowPosition' }).post({ value: { x: window.screenX, y: window.screenY } });
settingsApi.api.settings.local({ id: 'windowPosition' }).post({ value: { x: window.screenX, y: window.screenY } });
}
lastWindowPosX = window.screenX;

View file

@ -46,6 +46,16 @@ declare interface FocusEventDetails
focusKeyChanged: boolean;
}
declare interface GameMeta extends FocusParams
{
id: string,
onSelect?: () => void,
title: string,
subtitle?: any,
previewUrls?: string | URL[];
previewSrcset?: string;
};
declare interface FocusParams
{
onFocus?: (focusKey: string, node: HTMLElement, details: Record<string, any>) => void;