import { HiresPage2D, LoresPage2D, VideoModes2D } from 'js/canvas'; import { h, Fragment } from 'preact'; import { useEffect, useRef, useState } from 'preact/hooks'; import { Modal, ModalContent, ModalFooter } from '../Modal'; import styles from './css/FileViewer.module.scss'; /** * Binary and text representation of file to be previewed */ export interface FileData { fileName: string; binary: Uint8Array; text: string; } /** * FileViewer props */ export interface FileViewerProps { fileData: FileData | null; onClose: () => void; } /** * Preview a file as a hires image if a file is roughly 8192 bytes. * Leverages HiresPage2D. * * @param binary Potential file to preview * @returns HiresPreview component */ const HiresPreview = ({ binary }: { binary: Uint8Array }) => { const canvasRef = useRef(null); // Hires pictures are often a few bytes short of 8192 bytes // because that saves a sector on DOS 3.3 disks. if (binary.byteLength < 8184 || binary.byteLength > 8192) { return null; } if (canvasRef.current) { const vm = new VideoModes2D(canvasRef.current, true); const lores = new LoresPage2D(vm, 1, new Uint8Array(), false); const hires = new HiresPage2D(vm, 1); vm.setLoresPage(1, lores); vm.setHiresPage(1, hires); vm.text(false); vm.hires(true); vm.doubleHires(false); vm.page(1); for (let idx = 0; idx < 0x20; idx++) { for (let jdx = 0; jdx < 0x100; jdx++) { hires.write(idx + 0x20, jdx, binary[idx * 0x100 + jdx]); } } vm.blit(); } return ; }; /** * Preview a file as a double hires if a file is roughly 16384 bytes. * * @param binary Potential file to preview * @returns DoubleHiresPreview component */ const DoubleHiresPreview = ({ binary }: { binary: Uint8Array }) => { const canvasRef = useRef(null); if (binary.byteLength < 16376 || binary.byteLength > 16384) { return null; } if (canvasRef.current) { const vm = new VideoModes2D(canvasRef.current, true); const lores = new LoresPage2D(vm, 1, new Uint8Array(), false); const hires = new HiresPage2D(vm, 1); vm.setLoresPage(1, lores); vm.setHiresPage(1, hires); vm.text(false); vm.hires(true); vm._80col(true); vm.doubleHires(true); vm.page(1); for (let idx = 0; idx < 0x20; idx++) { for (let jdx = 0; jdx < 0x100; jdx++) { hires.bank1().write(idx + 0x20, jdx, binary[idx * 0x100 + jdx]); } } for (let idx = 0x20; idx < 0x40; idx++) { for (let jdx = 0; jdx < 0x100; jdx++) { hires.bank0().write(idx, jdx, binary[idx * 0x100 + jdx]); } } vm.blit(); } return ; }; /** * Apple file preview component. Supports a binary dump and hires and * double hires images. * * @param fileData * @param onClose Close button callback * @returns */ export const FileViewer = ({ fileData, onClose }: FileViewerProps) => { const [binaryHref, setBinaryHref] = useState(''); const [textHref, setTextHref] = useState(''); useEffect(() => { if (fileData) { const { binary, text } = fileData; const binaryBlob = new Blob( [binary], { type: 'application/octet-stream' } ); const binaryHref = window.URL.createObjectURL(binaryBlob); setBinaryHref(binaryHref); const textBlob = new Blob( [text], { type: 'application/octet-stream' } ); const textHref = window.URL.createObjectURL(textBlob); setTextHref(textHref); } }, [fileData]); if (!fileData) { return null; } const { fileName, text, binary } = fileData; return ( <>
                            {text}
                        
Download Raw Download Text
); };