Skip to content
Snippets Groups Projects
Verified Commit 80c80175 authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

feat: support for button upload

parent 57c3c71e
No related branches found
No related tags found
1 merge request!9Version 0.4.0 🍾
Pipeline #1406 passed
......@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
* A whole new layout implemented using React.JS 🔥
* Instant boot support using the `GameBoy.boot()` method
* Support for pending cycles in web version
......
......@@ -361,16 +361,6 @@ class GameboyEmulator extends Observable implements Emulator {
}
registerButtons() {
const buttonPause = document.getElementById("button-pause")!;
buttonPause.addEventListener("click", () => {
this.toggleRunning();
});
const buttonReset = document.getElementById("button-reset")!;
buttonReset.addEventListener("click", () => {
this.reset();
});
const buttonBenchmark = document.getElementById("button-benchmark")!;
buttonBenchmark.addEventListener("click", async () => {
buttonBenchmark.classList.add("enabled");
......@@ -496,47 +486,6 @@ class GameboyEmulator extends Observable implements Emulator {
}
}
});
const buttonInformation =
document.getElementById("button-information")!;
buttonInformation.addEventListener("click", () => {
const sectionDiag = document.getElementById("section-diag")!;
const separatorDiag = document.getElementById("separator-diag")!;
if (buttonInformation.classList.contains("enabled")) {
sectionDiag.style.display = "none";
separatorDiag.style.display = "none";
buttonInformation.classList.remove("enabled");
} else {
sectionDiag.style.display = "block";
separatorDiag.style.display = "block";
buttonInformation.classList.add("enabled");
}
});
const buttonUploadFile = document.getElementById(
"button-upload-file"
) as HTMLInputElement;
buttonUploadFile.addEventListener("change", async () => {
if (
!buttonUploadFile.files ||
buttonUploadFile.files.length === 0
) {
return;
}
const file = buttonUploadFile.files[0];
const arrayBuffer = await file.arrayBuffer();
const romData = new Uint8Array(arrayBuffer);
buttonUploadFile.value = "";
this.boot({ engine: null, romName: file.name, romData: romData });
this.trigger("message", {
text: `Loaded ${file.name} ROM successfully!`
});
});
}
setRom(name: string, data: Uint8Array, cartridge: Cartridge) {
......@@ -607,23 +556,11 @@ class GameboyEmulator extends Observable implements Emulator {
pause() {
this.paused = true;
const buttonPause = document.getElementById("button-pause")!;
const img = buttonPause.getElementsByTagName("img")[0];
const span = buttonPause.getElementsByTagName("span")[0];
buttonPause.classList.add("enabled");
img.src = require("./res/play.svg");
span.textContent = "Resume";
}
resume() {
this.paused = false;
this.nextTickTime = new Date().getTime();
const buttonPause = document.getElementById("button-pause")!;
const img = buttonPause.getElementsByTagName("img")[0];
const span = buttonPause.getElementsByTagName("span")[0];
buttonPause.classList.remove("enabled");
img.src = require("./res/pause.svg");
span.textContent = "Pause";
}
reset() {
......
......@@ -335,6 +335,12 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
const onThemeClick = () => {
setBackgroundIndex((backgroundIndex + 1) % backgrounds.length);
};
const onUploadFile = async (file: File) => {
const arrayBuffer = await file.arrayBuffer();
const romData = new Uint8Array(arrayBuffer);
emulator.boot({ engine: null, romName: file.name, romData: romData });
showToast(`Loaded ${file.name} ROM successfully!`);
};
const onEngineChange = (engine: string) => {
emulator.boot({ engine: engine.toLowerCase() });
showToast(
......@@ -478,7 +484,7 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
<Button
text={"Information"}
image={require("../res/info.svg")}
imageAlt="iformation"
imageAlt="information"
onClick={onInformationClick}
/>
<Button
......@@ -487,6 +493,14 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => {
imageAlt="theme"
onClick={onThemeClick}
/>
<Button
text={"Upload ROM"}
image={require("../res/upload.svg")}
imageAlt="upload"
file={true}
accept={".gb"}
onFile={onUploadFile}
/>
</ButtonContainer>
<Info>
<Pair
......
import React, { FC } from "react";
import React, { ChangeEvent, FC } from "react";
import "./button.css";
......@@ -6,33 +6,50 @@ type ButtonProps = {
text: string;
image?: string;
imageAlt?: string;
file?: boolean;
accept?: string;
size?: string;
style?: string[];
onClick?: () => void;
onFile?: (file: File) => void;
};
export const Button: FC<ButtonProps> = ({
text,
image,
imageAlt,
file = false,
accept = ".txt",
size = "small",
style = ["simple", "border"],
onClick
onClick,
onFile
}) => {
const classes = () => ["button", size, ...style].join(" ");
const _onClick = () => (onClick ? onClick() : undefined);
const buttonSimple = () => (
<span className={classes()} onClick={_onClick}>
const classes = () =>
["button", size, file ? "file" : "", ...style].join(" ");
const onFileChange = (event: ChangeEvent<HTMLInputElement>) => {
if (!event.target.files || event.target.files.length === 0) {
return;
}
const file = event.target.files[0];
onFile && onFile(file);
event.target.value = "";
};
const renderButtonSimple = () => (
<span className={classes()} onClick={onClick}>
{text}
</span>
);
const buttonImage = () => (
<span className={classes()} onClick={_onClick}>
<img src={image} alt={imageAlt || text || "button"} />
const renderButtonComplex = () => (
<span className={classes()} onClick={onClick}>
{image && <img src={image} alt={imageAlt || text || "button"} />}
{file && (
<input type="file" accept={accept} onChange={onFileChange} />
)}
<span>{text}</span>
</span>
);
return image ? buttonImage() : buttonSimple();
return image ? renderButtonComplex() : renderButtonSimple();
};
export default Button;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment