2025-10-08 18:10:07 -06:00

181 lines
6.0 KiB
TypeScript

"use client";
import { useState, useRef } from "react";
import { useDoomOverlay } from "@/app/providers/DoomOverlayProvider";
import { Modal } from "@/app/components/overlay/Modal";
import { JsDosPlayer } from "./JsDosPlayer";
export enum DoomEngine {
JsDos = "js-dos",
}
export type DoomConfig = {
engine: DoomEngine;
jsdos?: { zipUrl?: string };
};
export function DoomOverlay() {
const { isOpen, close } = useDoomOverlay();
const [selectedZipUrl, setSelectedZipUrl] = useState<string | null>(null);
const [loadError, setLoadError] = useState<string | null>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
const remoteDemoUrl = "https://v8.js-dos.com/v7/build/doom.jsdos";
const handleRemoteLoad = async () => {
try {
setLoadError(null);
setSelectedZipUrl(remoteDemoUrl);
} catch (error) {
console.error("Failed to load remote demo:", error);
setLoadError("Failed to load remote demo. Please try selecting a local file.");
}
};
const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (file && file.name.endsWith(".jsdos")) {
const url = URL.createObjectURL(file);
setSelectedZipUrl(url);
setLoadError(null);
} else {
setLoadError("Please select a valid .jsdos file");
}
};
const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
const file = event.dataTransfer.files[0];
if (file && file.name.endsWith(".jsdos")) {
const url = URL.createObjectURL(file);
setSelectedZipUrl(url);
setLoadError(null);
} else {
setLoadError("Please drop a valid .jsdos file");
}
};
const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
};
const handleReset = () => {
setSelectedZipUrl(null);
setLoadError(null);
if (fileInputRef.current) {
fileInputRef.current.value = "";
}
};
return (
<Modal open={isOpen} onClose={close} title="Doom Emulator">
<div className="p-6">
{!selectedZipUrl ? (
<div className="space-y-6">
<div className="text-center">
<h3 className="text-xl font-semibold text-neutral-100 mb-2">
Running on a Potato
</h3>
<p className="text-neutral-400 mb-6">
Choose how you'd like to run Doom:
</p>
</div>
<div className="space-y-4">
<button
onClick={handleRemoteLoad}
className="w-full px-4 py-3 rounded-lg glass text-neutral-200 font-medium transition-colors hover:opacity-95 focus:outline-none focus:ring-2 focus:ring-[color:var(--accent)]"
>
Load Demo from Internet
</button>
<div className="relative">
<div className="absolute inset-0 flex items-center">
<div className="w-full border-t border-white/20"></div>
</div>
<div className="relative flex justify-center text-sm">
<span className="px-4 bg-transparent text-neutral-400">or</span>
</div>
</div>
<div
onDrop={handleDrop}
onDragOver={handleDragOver}
className="border-2 border-dashed border-white/20 rounded-lg p-8 text-center hover:border-white/30 transition-colors"
>
<div className="space-y-4">
<div className="text-neutral-400">
<p className="mb-2">Drag and drop a .jsdos file here</p>
<p className="text-sm">or</p>
</div>
<input
ref={fileInputRef}
type="file"
accept=".jsdos"
onChange={handleFileSelect}
className="hidden"
id="file-input"
/>
<label
htmlFor="file-input"
className="inline-block px-4 py-2 rounded-lg glass text-neutral-200 font-medium cursor-pointer transition-colors hover:opacity-95"
>
Browse Files
</label>
</div>
</div>
</div>
{loadError && (
<div className="p-4 glass text-red-400 rounded-lg text-sm">
{loadError}
</div>
)}
<div className="text-xs text-neutral-500 space-y-1">
<p>
You can create .jsdos files using the{" "}
<a
href="https://js-dos.com/tools"
target="_blank"
rel="noopener noreferrer"
className="text-[color:var(--accent)] hover:underline"
>
js-dos tools
</a>
.
</p>
<p>
The demo requires internet connection and may take a moment to load.
</p>
</div>
</div>
) : (
<div className="space-y-4">
<div className="flex justify-between items-center">
<div className="text-sm text-neutral-400">
{selectedZipUrl === remoteDemoUrl
? "Running demo from internet"
: "Running local file"}
</div>
<button
onClick={handleReset}
className="px-3 py-1 text-sm rounded-md border border-white/10 text-neutral-300 hover:bg-white/5 transition-colors"
>
Change Source
</button>
</div>
<JsDosPlayer zipUrl={selectedZipUrl} className="w-full" />
<div className="text-xs text-neutral-500">
<p>Use keyboard controls to play. ESC to exit fullscreen mode.</p>
<p>Close this modal to stop the emulator.</p>
</div>
</div>
)}
</div>
</Modal>
);
}