feat: Implemented emulator launching

Fixes #1
This commit is contained in:
Simeon Radivoev 2026-04-04 03:13:09 +03:00
parent 04d5856f7d
commit 09b8b9c6f8
Signed by: simeonradivoev
GPG key ID: 7611A451D2A5D37A
20 changed files with 351 additions and 231 deletions

View file

@ -1,13 +1,10 @@
import { AnimatedBackground } from '@/mainview/components/AnimatedBackground';
import { createFileRoute, useRouter } from '@tanstack/react-router';
import { createFileRoute, useBlocker, useRouter } from '@tanstack/react-router';
import DotsLoading from '../components/backgrounds/dots';
import { useEffect } from 'react';
import { useQuery } from '@tanstack/react-query';
import { GamePadButtonCode, useShortcutContext, useShortcuts } from '../scripts/shortcuts';
import { useFocusable } from '@noriginmedia/norigin-spatial-navigation';
import Shortcuts from '../components/Shortcuts';
import { gameQuery } from '@queries/romm';
import { rommApi } from '../scripts/clientApi';
import { useJobStatus } from '../scripts/utils';
export const Route = createFileRoute('/launcher/$source/$id')({
component: RouteComponent,
@ -18,34 +15,33 @@ function RouteComponent ()
const router = useRouter();
function HandleGoBack ()
{
router.navigate({ to: '/game/$source/$id', viewTransition: { types: ['zoom-out'] }, params: { source, id }, replace: true });
if (router.history.canGoBack())
{
router.history.back();
} else
{
router.navigate({ to: '/game/$source/$id', viewTransition: { types: ['zoom-out'] }, params: { source, id }, replace: true });
}
}
const { source, id } = Route.useParams();
const { ref, focusKey } = useFocusable({ focusKey: `launching-${source}-${id}` });
const { data } = useQuery(gameQuery(source, id));
useShortcuts(focusKey, () => [{ label: "Back", button: GamePadButtonCode.B, action: HandleGoBack }]);
const { shortcuts } = useShortcutContext();
useEffect(() =>
{
if (!data) return;
const sub = rommApi.api.romm.status({ source: data.id.source })({ id: data.id.id }).subscribe();
sub.subscribe((e) =>
const { data } = useJobStatus('launch-game', {
onEnded (data)
{
if (e.data.status !== 'playing')
{
HandleGoBack();
}
});
return () =>
HandleGoBack();
},
onWaiting ()
{
sub.close();
};
}, [data?.id]);
HandleGoBack();
},
});
useBlocker({ shouldBlockFn: () => !!data });
return <AnimatedBackground ref={ref} backgroundKey='game-details'>
<div className='flex shadow-2xs shadow-black flex-col absolute w-screen h-screen overflow-hidden justify-center items-center gap-4'>