Added TIC-80
Some checks are pending
Tests / tests (push) Waiting to run

This commit is contained in:
Dustin Brett
2025-01-18 09:48:52 -08:00
parent 54f9baeb44
commit c2db213b68
19 changed files with 189 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
import styled from "styled-components";
const StyledTic80 = styled.div`
iframe {
background-color: #1a1c2c;
border: 0;
height: 100%;
width: 100%;
}
`;
export default StyledTic80;

View File

@@ -0,0 +1,10 @@
import useTic80 from "components/apps/Tic80/useTic80";
import StyledTic80 from "components/apps/Tic80/StyledTic80";
import AppContainer from "components/system/Apps/AppContainer";
import { type ComponentProcessProps } from "components/system/Apps/RenderComponent";
const Tic80: FC<ComponentProcessProps> = ({ id }) => (
<AppContainer StyledComponent={StyledTic80} id={id} useHook={useTic80} />
);
export default Tic80;

View File

@@ -0,0 +1,143 @@
import { basename } from "path";
import { useCallback, useEffect, useRef } from "react";
import { type ContainerHookProps } from "components/system/Apps/AppContainer";
import { useProcesses } from "contexts/process";
import { bufferToUrl } from "utils/functions";
import { useFileSystem } from "contexts/fileSystem";
import { useSession } from "contexts/session";
import { PREVENT_SCROLL } from "utils/constants";
import useFileDrop from "components/system/Files/FileManager/useFileDrop";
import useTitle from "components/system/Window/useTitle";
import processDirectory from "contexts/process/directory";
const useTic80 = ({
containerRef,
id,
setLoading,
url,
}: ContainerHookProps): void => {
const { processes: { [id]: { libs = [], maximized, title } = {} } = {} } =
useProcesses();
const { foregroundId, setForegroundId } = useSession();
const { readFile } = useFileSystem();
const { onDragOver, onDrop } = useFileDrop({ id });
const loadedUrl = useRef<string>(undefined);
const initializing = useRef(false);
const { appendFileToTitle } = useTitle(id);
const createIframe = useCallback((): Window => {
containerRef.current?.querySelector("iframe")?.remove();
const iframe = document.createElement("iframe");
iframe.title = title || processDirectory[id].title;
containerRef.current?.append(iframe);
const contentWindow = iframe.contentWindow as Window;
contentWindow.document.body.style.margin = "0";
contentWindow.document.body.style.overflow = "hidden";
return contentWindow;
}, [containerRef, id, title]);
const createCanvas = useCallback(
(baseDocument: Document): HTMLCanvasElement => {
const canvas = baseDocument.createElement("canvas");
canvas.id = "canvas";
canvas.style.width = "100%";
canvas.style.height = "100%";
canvas.style.imageRendering = "pixelated";
canvas.tabIndex = -1;
baseDocument.body.append(canvas);
return canvas;
},
[]
);
const loadComputer = useCallback(
(fileUrl?: string) => {
initializing.current = true;
setLoading(true);
const iframeWindow = createIframe();
const canvas = createCanvas(iframeWindow.document);
const focusCanvas = (): void => {
canvas.focus(PREVENT_SCROLL);
setForegroundId(id);
};
const postRun = (): void => setLoading(false);
iframeWindow.Module = { canvas, postRun };
iframeWindow.addEventListener("click", focusCanvas);
iframeWindow.addEventListener("focus", focusCanvas);
iframeWindow.addEventListener("blur", () => setForegroundId(""));
iframeWindow.addEventListener("dragover", onDragOver);
iframeWindow.addEventListener("drop", onDrop);
const loadApp = (blobUrl?: string): void => {
if (blobUrl) {
iframeWindow.Module.arguments = [blobUrl];
appendFileToTitle(basename(url));
}
const [tic80Lib] = libs;
const script = iframeWindow.document.createElement("script");
script.type = "text/javascript";
script.src = tic80Lib;
iframeWindow.document.head.append(script);
loadedUrl.current = fileUrl || "";
initializing.current = false;
setLoading(false);
};
if (fileUrl) {
readFile(fileUrl).then((file) =>
loadApp(`${bufferToUrl(file)}?e=.tic`)
);
} else {
loadApp();
}
},
[
appendFileToTitle,
createCanvas,
createIframe,
id,
libs,
onDragOver,
onDrop,
readFile,
setForegroundId,
setLoading,
url,
]
);
useEffect(() => {
if (!initializing.current && url !== loadedUrl.current) {
loadComputer(url);
}
}, [loadComputer, url]);
useEffect(() => {
if (foregroundId === id) {
requestAnimationFrame(() => {
containerRef.current
?.querySelector("iframe")
?.contentWindow?.document.querySelector<HTMLCanvasElement>("#canvas")
?.focus(PREVENT_SCROLL);
});
}
// eslint-disable-next-line react-hooks-addons/no-unused-deps
}, [containerRef, foregroundId, id, maximized]);
};
export default useTic80;

View File

@@ -88,6 +88,10 @@ const types = {
process: ["Photos", ...TEXT_EDITORS],
type: "Scalable Vector Graphics File",
},
Tic80: {
process: ["Tic80"],
type: "TIC-80 Cartridge",
},
WasmFile: {
command: "wapm",
icon: "wapm",
@@ -133,6 +137,7 @@ const extensions: Record<string, Extension> = {
".spl": types.FutureSplash,
".svg": types.SvgFile,
".swf": types.ShockwaveFlash,
".tic": types.Tic80,
".ttf": types.Font,
".wasm": types.WasmFile,
".whtml": types.WysiwygHtmlDocument,

View File

@@ -305,6 +305,19 @@ const directory: Processes = {
preferProcessIcon: true,
title: "Terminal",
},
Tic80: {
Component: dynamic(() => import("components/apps/Tic80")),
backgroundColor: "#1A1C2C",
defaultSize: {
height: 346,
width: 615,
},
dependantLibs: ["/Program Files/Tic80/tic80.wasm"],
icon: "/System/Icons/tic80.webp",
libs: ["/Program Files/Tic80/tic80.js"],
lockAspectRatio: true,
title: "TIC-80 tiny computer",
},
TinyMCE: {
Component: dynamic(() => import("components/apps/TinyMCE")),
backgroundColor: "#202124",

View File

@@ -90,6 +90,7 @@ This project is greatly augmented by code from the open source community. Thank
- [nostr-tools](https://github.com/nbd-wtf/nostr-tools)
- [DOMPurify](https://github.com/cure53/DOMPurify)
- [t-rex-runner](https://github.com/wayou/t-rex-runner)
- [TIC-80](https://tic80.com/)
## Services

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

View File

@@ -0,0 +1,4 @@
[InternetShortcut]
BaseURL=Tic80
Comment=TIC-80 Tiny Computer
IconFile=/System/Icons/tic80.webp