Render a Game Boy player for GB/GBC attachments
This commit is contained in:
47
src/components/gameboy.tsx
Normal file
47
src/components/gameboy.tsx
Normal file
@ -0,0 +1,47 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
// @ts-ignore No types available
|
||||
import { WasmBoy } from 'wasmboy';
|
||||
|
||||
interface IGameboy extends React.CanvasHTMLAttributes<HTMLCanvasElement> {
|
||||
/** URL to the ROM. */
|
||||
src: string;
|
||||
}
|
||||
|
||||
/** Component to display a playable Gameboy emulator. */
|
||||
const Gameboy: React.FC<IGameboy> = ({ src, ...rest }) => {
|
||||
const canvas = useRef<HTMLCanvasElement>(null);
|
||||
|
||||
async function init() {
|
||||
await WasmBoy.config(WasmBoyOptions, canvas.current!);
|
||||
await WasmBoy.loadROM(src);
|
||||
await WasmBoy.play();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
init();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<canvas ref={canvas} {...rest} />
|
||||
);
|
||||
};
|
||||
|
||||
const WasmBoyOptions = {
|
||||
headless: false,
|
||||
useGbcWhenOptional: true,
|
||||
isAudioEnabled: false,
|
||||
frameSkip: 1,
|
||||
audioBatchProcessing: true,
|
||||
timersBatchProcessing: false,
|
||||
audioAccumulateSamples: true,
|
||||
graphicsBatchProcessing: false,
|
||||
graphicsDisableScanlineRendering: false,
|
||||
tileRendering: true,
|
||||
tileCaching: true,
|
||||
gameboyFPSCap: 60,
|
||||
updateGraphicsCallback: false,
|
||||
updateAudioCallback: false,
|
||||
saveStateCallback: false,
|
||||
};
|
||||
|
||||
export { Gameboy };
|
||||
@ -12,6 +12,8 @@ import { truncateFilename } from 'soapbox/utils/media';
|
||||
import { isIOS } from '../is-mobile';
|
||||
import { isPanoramic, isPortrait, isNonConformingRatio, minimumAspectRatio, maximumAspectRatio } from '../utils/media-aspect-ratio';
|
||||
|
||||
import { Gameboy } from './gameboy';
|
||||
|
||||
import type { Property } from 'csstype';
|
||||
import type { List as ImmutableList } from 'immutable';
|
||||
|
||||
@ -141,8 +143,22 @@ const Item: React.FC<IItem> = ({
|
||||
}
|
||||
|
||||
let thumbnail: React.ReactNode = '';
|
||||
const ext = attachment.url.split('.').pop()?.toLowerCase();
|
||||
|
||||
if (attachment.type === 'unknown') {
|
||||
if (attachment.type === 'unknown' && ['gb', 'gbc'].includes(ext!)) {
|
||||
return (
|
||||
<div
|
||||
className={clsx('media-gallery__item', {
|
||||
standalone,
|
||||
'rounded-md': total > 1,
|
||||
})}
|
||||
key={attachment.id}
|
||||
style={{ position, float, left, top, right, bottom, height, width: `${width}%` }}
|
||||
>
|
||||
<Gameboy className='media-gallery__item-thumbnail object-contain' src={attachment.url} />
|
||||
</div>
|
||||
);
|
||||
} else if (attachment.type === 'unknown') {
|
||||
const filename = truncateFilename(attachment.url, MAX_FILENAME_LENGTH);
|
||||
const attachmentIcon = (
|
||||
<Icon
|
||||
@ -215,7 +231,6 @@ const Item: React.FC<IItem> = ({
|
||||
</div>
|
||||
);
|
||||
} else if (attachment.type === 'audio') {
|
||||
const ext = attachment.url.split('.').pop()?.toUpperCase();
|
||||
thumbnail = (
|
||||
<a
|
||||
className={clsx('media-gallery__item-thumbnail')}
|
||||
@ -225,11 +240,10 @@ const Item: React.FC<IItem> = ({
|
||||
title={attachment.description}
|
||||
>
|
||||
<span className='media-gallery__item__icons'><Icon src={require('@tabler/icons/volume.svg')} /></span>
|
||||
<span className='media-gallery__file-extension__label'>{ext}</span>
|
||||
<span className='media-gallery__file-extension__label uppercase'>{ext}</span>
|
||||
</a>
|
||||
);
|
||||
} else if (attachment.type === 'video') {
|
||||
const ext = attachment.url.split('.').pop()?.toUpperCase();
|
||||
thumbnail = (
|
||||
<a
|
||||
className={clsx('media-gallery__item-thumbnail')}
|
||||
@ -246,7 +260,7 @@ const Item: React.FC<IItem> = ({
|
||||
>
|
||||
<source src={attachment.url} />
|
||||
</video>
|
||||
<span className='media-gallery__file-extension__label'>{ext}</span>
|
||||
<span className='media-gallery__file-extension__label uppercase'>{ext}</span>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user