Skip to content

Commit

Permalink
Add Preact cassette UI (#225)
Browse files Browse the repository at this point in the history
  • Loading branch information
whscullin authored Jul 7, 2024
1 parent ea84471 commit f58e924
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 56 deletions.
70 changes: 14 additions & 56 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
{
// Global
"root": true,
"plugins": [
"prettier"
],
"plugins": ["prettier"],
"parser": "@typescript-eslint/parser",
"extends": [
"eslint:recommended",
Expand All @@ -12,38 +10,22 @@
],
"rules": {
"prettier/prettier": "error",
"linebreak-style": [
"error",
"unix"
],
"eqeqeq": [
"error",
"smart"
],
"prefer-const": [
"error"
],
"linebreak-style": ["error", "unix"],
"eqeqeq": ["error", "smart"],
"prefer-const": ["error"],
"no-var": "error",
"no-use-before-define": "off",
"no-console": [
"error",
{
"allow": [
"info",
"warn",
"error"
]
"allow": ["info", "warn", "error"]
}
],
// Jest configuration
"jest/expect-expect": [
"error",
{
"assertFunctionNames": [
"expect*",
"checkImageData",
"testCode"
]
"assertFunctionNames": ["expect*", "checkImageData", "testCode"]
}
]
},
Expand All @@ -58,13 +40,8 @@
//
// TypeScript/TSX-specific configuration
{
"files": [
"*.ts",
"*.tsx"
],
"plugins": [
"@typescript-eslint/eslint-plugin"
],
"files": ["*.ts", "*.tsx"],
"plugins": ["@typescript-eslint/eslint-plugin"],
"extends": [
"plugin:react/recommended",
"plugin:react-hooks/recommended",
Expand Down Expand Up @@ -106,9 +83,6 @@
],
// no redeclaration of classes, members or variables
"no-redeclare": "off",
"@typescript-eslint/no-redeclare": [
"error"
],
// allow empty interface definitions and empty extends
"@typescript-eslint/no-empty-interface": "off",
// allow explicit type declaration
Expand All @@ -132,21 +106,15 @@
},
// UI elements
{
"files": [
"js/ui/**.ts"
],
"files": ["js/ui/**.ts"],
"rules": {
// allow non-null assertions since these classes reference the DOM
"@typescript-eslint/no-non-null-assertion": "off"
}
},
// JS Node configuration
{
"files": [
"bin/*",
"babel.config.js",
"webpack.config.js"
],
"files": ["bin/*", "babel.config.js", "webpack.config.js"],
"rules": {
"no-console": 0
},
Expand All @@ -158,9 +126,7 @@
},
// Test configuration
{
"files": [
"test/**/*"
],
"files": ["test/**/*"],
"env": {
"jest": true,
"jasmine": true,
Expand All @@ -172,28 +138,20 @@
},
// Entry point configuration
{
"files": [
"js/entry2.ts",
"js/entry2e.ts",
"jest.config.js"
],
"files": ["js/entry2.ts", "js/entry2e.ts", "jest.config.js"],
"env": {
"commonjs": true
}
},
// Worker configuration
{
"files": [
"workers/*"
],
"files": ["workers/*"],
"parserOptions": {
"project": "workers/tsconfig.json"
}
}
],
"ignorePatterns": [
"coverage/**/*"
],
"ignorePatterns": ["coverage/**/*"],
"settings": {
"react": {
"pragma": "h",
Expand Down
1 change: 1 addition & 0 deletions js/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { defaultSystem, systemTypes } from './util/systems';

import styles from './css/App.module.scss';
import componentStyles from './css/Components.module.scss';
import 'bootstrap-icons/font/bootstrap-icons.css';

/**
* Top level application component, provides the parameters
Expand Down
70 changes: 70 additions & 0 deletions js/components/Cassette.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { h, Fragment } from 'preact';
import { useMemo, useState } from 'preact/hooks';
import styles from './css/ControlButton.module.scss';
import cs from 'classnames';

import Apple2IO from 'js/apple2io';
import Tape, { TAPE_TYPES } from 'js/ui/tape';
import { debug } from 'js/util';
import { noAwait } from './util/promises';

import { FileChooser } from './FileChooser';
import { Modal, ModalContent } from './Modal';

const CASSETTE_TYPES: FilePickerAcceptType[] = [
{
description: 'Audio Files',
accept: {
'application/octet-stream': TAPE_TYPES.map((x) => '.' + x),
},
},
];

export interface CassetteParams {
io: Apple2IO | undefined;
}

export const Cassette = ({ io }: CassetteParams) => {
const tape = useMemo(() => (io ? new Tape(io) : null), [io]);
const [active, setActive] = useState(false);
const [isOpen, setIsOpen] = useState(false);

const onClose = () => setIsOpen(false);
const onChange = (handles: FileSystemFileHandle[]) => {
if (tape && handles.length > 0) {
const load = async () => {
debug('Loading Cassette');
const file = await handles[0].getFile();
tape.doLoadLocalTape(file, () => debug('Cassette Loaded'));
};
noAwait(load)();
onClose();
setActive(true);
}
};

return (
<>
<Modal
title="Select Audio Cassette"
isOpen={isOpen}
onClose={onClose}
>
<ModalContent>
<FileChooser onChange={onChange} accept={CASSETTE_TYPES} />
</ModalContent>
</Modal>
<button
className={styles.iconButton}
onClick={() => setIsOpen(true)}
title="Cassette"
>
<i
className={cs('bi', 'bi-cassette', {
[styles.active]: active,
})}
/>
</button>
</>
);
};
2 changes: 2 additions & 0 deletions js/components/ControlStrip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { OptionsModal } from './OptionsModal';
import { OptionsContext } from './OptionsContext';
import { Printer } from './Printer';
import { ControlButton } from './ControlButton';
import { Cassette } from './Cassette';
import { Apple2 as Apple2Impl } from '../apple2';
import { JoyStick } from '../ui/joystick';
import { Screen, SCREEN_FULL_PAGE } from '../ui/screen';
Expand Down Expand Up @@ -92,6 +93,7 @@ export const ControlStrip = ({
/>
<AudioControl apple2={apple2} />
<Printer io={io} slot={1} />
<Cassette io={io} />
<div style={{ flexGrow: 1 }} />
<ControlButton onClick={doReadme} title="About" icon="info" />
<ControlButton
Expand Down
39 changes: 39 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"dependencies": {
"@whscullin/cpu6502": "file:submodules/cpu6502",
"apple2shader": "file:submodules/apple2shader",
"bootstrap-icons": "^1.11.3",
"classnames": "^2.3.1",
"micromodal": "^0.4.2",
"preact": "^10.7.1"
Expand Down

0 comments on commit f58e924

Please sign in to comment.