feat: Implemented public plugin system accessible from the store.
feat: Implemented external ryujinx integration plugin refactor: moved sdk types and schemas to own workspace package fix: Fixed emulator launch with no game
This commit is contained in:
parent
9051834ace
commit
38cb752552
124 changed files with 1918 additions and 1067 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import { useEffect, useRef, useState } from "react";
|
||||
import { SystemInfoContext } from "../scripts/contexts";
|
||||
import { systemApi } from "../scripts/clientApi";
|
||||
import { SystemInfoType } from "@/shared/constants";
|
||||
import { SystemInfoType } from '@simeonradivoev/gameflow-sdk/shared';
|
||||
import LoadingScreen from "./LoadingScreen";
|
||||
import { GamepadKeyboard } from "./GamepadKeyboard";
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { JSX, Suspense } from 'react';
|
|||
import { FloatingShortcuts } from './Shortcuts';
|
||||
import { AutoFocus } from './AutoFocus';
|
||||
import { GamePadButtonCode, useShortcuts } from '../scripts/shortcuts';
|
||||
import { GameListFilterType } from '@/shared/constants';
|
||||
import { GameListFilterType } from '@simeonradivoev/gameflow-sdk/shared';
|
||||
import { HandleGoBack } from '../scripts/utils';
|
||||
import LoadingCardList from './LoadingCardList';
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { FocusEventHandler, useContext, useRef, useState } from "react";
|
|||
import path from "pathe";
|
||||
import { Check, File, FileInput, Folder, FolderInput, FolderOutput, FolderPlus, HardDrive, Usb, X } from "lucide-react";
|
||||
import { FocusContext, useFocusable } from "@noriginmedia/norigin-spatial-navigation";
|
||||
import { DirType } from "@/shared/constants";
|
||||
import { DirType } from '@simeonradivoev/gameflow-sdk/shared';
|
||||
import classNames from "classnames";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { GamePadButtonCode, Shortcut, useShortcuts } from "../scripts/shortcuts";
|
||||
|
|
|
|||
|
|
@ -4,7 +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";
|
||||
import { FrontEndGameType, FrontEndId } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
export default function FrontEndGameCard (data: { index: number, game: FrontEndGameType; showSource?: boolean; } & FocusParams & InteractParams)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
import { useSuspenseQuery } from "@tanstack/react-query";
|
||||
import { GameMetaExtra, CardList } from "./CardList";
|
||||
import { DefaultRommStaleTime, GameListFilterType, RPC_URL } from "@shared/constants";
|
||||
import { DefaultRommStaleTime, RPC_URL } from "@shared/constants";
|
||||
import { GameListFilterType } from '@simeonradivoev/gameflow-sdk/shared';
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
import { HardDrive } from "lucide-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";
|
||||
import { FrontEndGameType, FrontEndId } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
export interface GameListParams extends FocusParams
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ function buildWheel (side: 0 | 1, shift: boolean, characters: boolean)
|
|||
const elements: JSX.Element[] = [];
|
||||
const refs: RefObject<HTMLSpanElement | null>[] = [];
|
||||
const positions: { left: string; top: string; }[] = [];
|
||||
const W = 258, C = 129, R2 = 107, R1 = 42, n = GetKeys(characters)[side].length, GAP = 0.028;
|
||||
const n = GetKeys(characters)[side].length, GAP = 0.028;
|
||||
|
||||
for (let i = 0; i < n; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { oneShot } from "../scripts/audio/audio";
|
|||
import { Search } from "lucide-react";
|
||||
import { RoundButton } from "./RoundButton";
|
||||
import { useEventListener } from "usehooks-ts";
|
||||
import useActiveControl from "../scripts/gamepads";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
function SearchInput (data: {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { setFocus, useFocusable } from "@noriginmedia/norigin-spatial-navigation";
|
||||
import { FOCUS_KEYS } from "../scripts/types";
|
||||
import { useIntersectionObserver } from "usehooks-ts";
|
||||
import { FrontEndId } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
export default function LoadMoreButton (data: { isFetching: boolean; hidden?: boolean, lastId?: FrontEndId; } & FocusParams & InteractParams)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { RPC_URL } from "@/shared/constants";
|
||||
import { FrontendNotification } from "@/shared/types";
|
||||
import { FrontendNotification } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
import { Clock, CloudUpload, Save } from "lucide-react";
|
||||
import { useEffect } from "react";
|
||||
import toast, { ToastOptions } from "react-hot-toast";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { GameListFilterType } from "@/shared/constants";
|
||||
import { GameListFilterType } from '@simeonradivoev/gameflow-sdk/shared';
|
||||
import { RoundButton } from "./RoundButton";
|
||||
import classNames from "classnames";
|
||||
import { GamePadButtonCode, useShortcuts } from "../scripts/shortcuts";
|
||||
|
|
@ -6,7 +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";
|
||||
import { FrontEndFilterLists } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
function FilterButton (data: {
|
||||
id: string,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
import { FrontEndGameTypeDetailed, FrontEndGameTypeDetailedAchievement } from "@/shared/types";
|
||||
import { FrontEndGameTypeDetailed, FrontEndGameTypeDetailedAchievement } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
import { useFocusable } from "@noriginmedia/norigin-spatial-navigation";
|
||||
import { Medal } from "lucide-react";
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +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";
|
||||
import { FrontEndGameTypeDetailed } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
function AchievementsInfo (data: { game: FrontEndGameTypeDetailed; } & InteractParams)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +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";
|
||||
import { FrontEndGameTypeDetailed } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
export function DetailElement (data: { icon: JSX.Element; tooltip?: string | null, children?: any | any[]; })
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ 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 { FrontEndId, GameLookup } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
import { gameLookupQuery } from "@/mainview/scripts/queries/romm";
|
||||
import { Button } from "../options/Button";
|
||||
import { useNavigate } from "@tanstack/react-router";
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@ import { Clock, Crosshair, Download, EllipsisVertical, Import, PackageOpen, Play
|
|||
import { gameInvalidationQuery, installMutation, playMutation } from "@/mainview/scripts/queries/romm";
|
||||
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";
|
||||
import { CommandEntry, FrontEndGameTypeDetailed, DownloadSourceType } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
export default function MainActions (data: { game?: FrontEndGameTypeDetailed, source: string, id: string; })
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ import { useState } from "react";
|
|||
import { PathSettingsOptionBase, PathSettingsOptionParams } from "./PathSettingsOption";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { changeDownloadsMutation, getSettingQuery } from "@queries/settings";
|
||||
import { SettingsType } from "@/shared/constants";
|
||||
import { KeysWithValueAssignableTo } from "@/shared/types";
|
||||
import { KeysWithValueAssignableTo, SettingsType } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
export default function DownloadDirectoryOption (data: PathSettingsOptionParams & { id: KeysWithValueAssignableTo<SettingsType, string>; })
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { JSX } from "react";
|
||||
import { LocalSettingsSchema, LocalSettingsType } from "@shared/constants";
|
||||
import { LocalSettingsSchema, LocalSettingsType } from '@simeonradivoev/gameflow-sdk/shared';
|
||||
import { OptionSpace } from "./OptionSpace";
|
||||
import { OptionInput } from "./OptionInput";
|
||||
import { useLocalStorage } from "usehooks-ts";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { HTMLInputTypeAttribute, JSX, useEffect, useState } from "react";
|
||||
import { SettingsType } from "../../../shared/constants";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { OptionSpace } from "./OptionSpace";
|
||||
import { OptionInput } from "./OptionInput";
|
||||
|
|
@ -9,7 +8,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";
|
||||
import { KeysWithValueAssignableTo, SettingsType } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
export interface PathSettingsOptionParams
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { JSX, useCallback, useEffect, useState } from "react";
|
||||
import { SettingsType } from "../../../shared/constants";
|
||||
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";
|
||||
import { KeysWithValueAssignableTo, SettingsType } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
export function SettingsDropdown (data: {
|
||||
label: string;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { HTMLInputTypeAttribute, JSX, useCallback, useEffect, useState } from "react";
|
||||
import { SettingsType } from "../../../shared/constants";
|
||||
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";
|
||||
import { KeysWithValueAssignableTo, SettingsType } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
export function SettingsOption (data: {
|
||||
label: string;
|
||||
|
|
|
|||
|
|
@ -12,7 +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";
|
||||
import { FrontEndEmulator } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
function SeeAllCard (data: { id: string; onAction: () => void; onFocus?: (details: { node: HTMLElement, instant?: boolean; }) => void; })
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +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";
|
||||
import { FrontEndGameType, FrontEndId } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
export function GamesSection (data: {
|
||||
games?: FrontEndGameType[];
|
||||
|
|
|
|||
|
|
@ -8,7 +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";
|
||||
import { FrontEndEmulator } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
// ── Single missing-emulator card ───────────────────────────────────────────
|
||||
interface MissingCardProps
|
||||
|
|
|
|||
|
|
@ -10,7 +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";
|
||||
import { FrontEndEmulator } from "@simeonradivoev/gameflow-sdk/shared";
|
||||
|
||||
export const emulatorStatusIcons: Record<string, JSX.Element> = {
|
||||
store: <Store />,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue