This commit is contained in:
He4eT 2023-05-21 16:46:30 +03:00 committed by Alexey
commit 7a96d99055
21 changed files with 174 additions and 170 deletions

View file

@ -1,6 +1,6 @@
import { h } from 'preact'
export default function ({ theme, setLocation, buildLink }) {
export default function LocalFileSelector ({ theme, setLocation, buildLink }) {
const fileInputHandler = ({ target }) => {
const file = target.files[0]
const url = `${URL.createObjectURL(file)}#${file.name}`

View file

@ -1,6 +1,6 @@
import { h } from 'preact'
export default function ({ theme, setLocation, buildLink }) {
export default function TargetURLSelector ({ theme, setLocation, buildLink }) {
const urlRE = /^(http|https):\/\/[^ "]+$/
const onKeyPress = ({ keyCode, target }) => {

View file

@ -2,22 +2,24 @@ import { h } from 'preact'
import { Link } from 'wouter-preact'
import {
buildPlayLinkHref
buildPlayLinkHref,
} from '~/src/utils/utils.routing'
export default ({ name, ifdb, url }) => (
<div>
<h4>{name}</h4>
<a
target='_blank'
rel='noopener noreferrer'
href={ifdb}>
IFDB page
</a>
<span> | </span>
<Link
href={buildPlayLinkHref({ url })}>
Play
</Link>
</div>
)
export default function GameEntry ({ name, ifdb, url }) {
return (
<div>
<h4>{name}</h4>
<a
target='_blank'
rel='noopener noreferrer'
href={ifdb}>
IFDB page
</a>
<span> | </span>
<Link
href={buildPlayLinkHref({ url })}>
Play
</Link>
</div>
)
}

View file

@ -3,7 +3,7 @@ import { useEffect, useState } from 'preact/hooks'
import TextMessage from './TextMessage'
export default function ({ inbox, currentWindow }) {
export default function GridBuffer ({ inbox, currentWindow }) {
const [prevMessages, setPrevMessages] = useState([])
const [messages, setMessages] = useState([])
@ -14,7 +14,7 @@ export default function ({ inbox, currentWindow }) {
const currentInbox = currentInboxObj?.lines ?? []
const newOrPrev = (cur, prev) => i => {
const newOrPrev = (cur, prev) => (i) => {
const byId = (list, i) =>
list.find(({ line }) => line === i)
@ -31,23 +31,23 @@ export default function ({ inbox, currentWindow }) {
const rawMessagesContent =
rawMessages
.map(x => x.content)
.map((x) => x.content)
.map(([x]) => x)
.map(({ text }) => text)
.map(text => text.trim())
.map((text) => text.trim())
const isEmpty =
rawMessagesContent
.map(text => text.length)
.every(l => l === 0)
.map((text) => text.length)
.every((l) => l === 0)
const messages =
rawMessagesContent
.map(text =>
.map((text) =>
text.replace(' ', ' / '))
.map(text => ({
.map((text) => ({
style: 'grid',
text
text,
}))
setMessages(isEmpty ? [] : messages)
@ -56,7 +56,7 @@ export default function ({ inbox, currentWindow }) {
return (
<section
className='buffer gridBuffer'>
{messages.map(TextMessage)}
{messages.map(TextMessage)}
</section>
)
}

View file

@ -33,11 +33,11 @@ const keyNames = {
}
/* eslint-enable */
export default function ({
export default function InputBox ({
inputType,
windows,
currentWindowId,
sendMessage
sendMessage,
}) {
const [targetWindow, setTargetWindow] = useState(null)
const [inputText, setInputText] = useState('')
@ -56,7 +56,7 @@ export default function ({
id === currentWindowId))
}, [currentWindowId, windows])
const send = message => {
const send = (message) => {
sendMessage(
message,
inputType,
@ -65,12 +65,12 @@ export default function ({
setInputText('')
}
const charHandler = event =>
const charHandler = (event) =>
(event.keyCode === 229
? charHandlerMobile
: charHandlerDefault)(event)
const charHandlerDefault = event => {
const charHandlerDefault = (event) => {
event.preventDefault()
const key =
@ -80,8 +80,8 @@ export default function ({
send(key)
}
const charHandlerMobile = event =>
setTimeout(_ => {
const charHandlerMobile = (event) =>
setTimeout(() => {
send(event.target.value.slice(-1).toUpperCase())
setInputText('')
})
@ -96,7 +96,7 @@ export default function ({
if (keyCode === keyCodes.KEY_UP) {
setInputText(lastInput)
setTimeout(_ => {
setTimeout(() => {
const end = lastInput.length
inputEl.current.setSelectionRange(end, end)
}, 0)
@ -113,16 +113,16 @@ export default function ({
autocorrect: 'off',
spellcheck: 'false',
placeholder: 'Press any key here',
onKeyDown: charHandler
onKeyDown: charHandler,
},
line: {
placeholder: ' > ',
onKeyDown: lineArrowHandler,
onKeyPress: lineHandler
}
onKeyPress: lineHandler,
},
}
const enterFullscreen = _ =>
const enterFullscreen = () =>
document.documentElement.requestFullscreen()
return (

View file

@ -15,7 +15,7 @@ import './player.css'
const INITIAL_STATUS = {
stage: 'loading',
details: ['Preparing']
details: ['Preparing'],
}
const runMachine = ({ engine: Engine, file, handlers }) => {
@ -28,8 +28,8 @@ const runMachine = ({ engine: Engine, file, handlers }) => {
return { sendFn, instance: vm }
}
export default function ({
vmParts: { file, engine }, singleWindow
export default function Player ({
vmParts: { file, engine }, singleWindow,
}) {
const [status, setStatus] = useState(INITIAL_STATUS)
@ -50,28 +50,28 @@ export default function ({
setWindows,
setCurrentWindowId,
setInputType,
setInbox
})
setInbox,
}),
})
setVm(vm)
}, [file, engine])
useEffect(() => {
setSendMessage(_ => vm
setSendMessage(() => vm
? vm.sendFn
: null)
}, [vm])
const textWindow = inbox => currentWindow => {
const textWindow = (inbox) => (currentWindow) => {
const props = {
inbox,
currentWindow
currentWindow,
}
return ({
buffer: <TextBuffer {...props} />,
grid: <GridBuffer {...props} />
grid: <GridBuffer {...props} />,
})[currentWindow.type]
}
@ -82,18 +82,18 @@ export default function ({
? (<Status {...status} />)
: (<section className='ifplayer'>
<section className='output'>{
windows
.sort(byTop)
.filter(singleWindow
? ({ id }) => id === currentWindowId
: _ => true)
.map(textWindow(inbox))}
windows
.sort(byTop)
.filter(singleWindow
? ({ id }) => id === currentWindowId
: () => true)
.map(textWindow(inbox))}
</section>
<InputBox {...{
inputType,
windows,
currentWindowId,
sendMessage
sendMessage,
}} />
</section>)
}

View file

@ -1,12 +1,12 @@
import { h } from 'preact'
import { Link } from 'wouter-preact'
const fail = details => (
const fail = (details) => (
<div className='status fail'>
<h1>
Error
</h1>
{details.map(x => (<p key={x}>{x}</p>))}
{details.map((x) => (<p key={x}>{x}</p>))}
<hr />
<Link href='/'>
Home
@ -21,9 +21,9 @@ const fail = details => (
</div>
)
const loading = details => (
const loading = (details) => (
<div className='status loading'>
{details.map(x => (<div key={x}>{x}</div>))}
{details.map((x) => (<div key={x}>{x}</div>))}
</div>
)

View file

@ -3,10 +3,10 @@ import { useEffect, useRef, useState } from 'preact/hooks'
import TextMessage from './TextMessage'
const isFakeStatus = w =>
const isFakeStatus = (w) =>
w.height < 5
const trimInputPrompt = messages =>
const trimInputPrompt = (messages) =>
messages.length < 1
? messages
: messages.slice(-1)[0].text === '>'
@ -21,7 +21,7 @@ const parseInbox = (inbox, currentWindow) => {
if (!currentInbox) {
return {
clear: false,
incoming: []
incoming: [],
}
}
@ -45,11 +45,11 @@ const parseInbox = (inbox, currentWindow) => {
incoming,
clear: isFakeStatus(currentWindow)
? true
: currentInbox.clear
: currentInbox.clear,
}
}
export default function ({ inbox, currentWindow }) {
export default function TextBuffer ({ inbox, currentWindow }) {
const [messages, setMessages] = useState([])
const textBufferEl = useRef(null)
@ -57,7 +57,7 @@ export default function ({ inbox, currentWindow }) {
const { incoming, clear } =
parseInbox(inbox, currentWindow)
setMessages(messages => clear
setMessages((messages) => clear
? incoming
: messages.concat(incoming))
@ -85,7 +85,7 @@ export default function ({ inbox, currentWindow }) {
tabindex='0'
ref={textBufferEl}
className={classes}>
{messages.map(TextMessage)}
{messages.map(TextMessage)}
</section>
)
}

View file

@ -1,6 +1,6 @@
import { h } from 'preact'
export default function ({ style, text }) {
export default function TextMessage ({ style, text }) {
const defaultContent = (
<span className={['message', style].join(' ')}>
{text}
@ -11,6 +11,6 @@ export default function ({ style, text }) {
input: (<span className='message input'>&gt; {text}</span>),
subheader: (<strong className='message subheader'>{text}</strong>),
emphasized: (<em className='message emphasized'>{text}</em>),
endOfLine: (<br />)
endOfLine: (<br />),
})[style] || defaultContent
}

View file

@ -8,16 +8,16 @@ import Status from './Status'
const INITIAL_STATUS = {
stage: 'loading',
details: ['Loading']
details: ['Loading'],
}
const prepareVM = ({ url, setStatus, setParts }) => {
const st = (stage, details) => args => {
const st = (stage, details) => (args) => {
setStatus({ stage, details: [details] })
return args
}
const cleanUrl = url =>
const cleanUrl = (url) =>
url.startsWith('blob:')
? url.replace(/#(.*)$/g, '')
: url
@ -27,21 +27,21 @@ const prepareVM = ({ url, setStatus, setParts }) => {
.then(cleanUrl)
.then(fetch)
.then(st('loading', 'Processing file'))
.then(response => response.arrayBuffer())
.then(arrayBuffer => new Uint8Array(arrayBuffer))
.then((response) => response.arrayBuffer())
.then((arrayBuffer) => new Uint8Array(arrayBuffer))
.then(st('loading', 'Downloading engine'))
.then(file => setParts({
.then((file) => setParts({
file,
engine: engineByFilename(url)
engine: engineByFilename(url),
}))
.then(st('loading', 'Running'))
.catch(e => {
.catch((e) => {
console.error(e)
setStatus({ stage: 'fail', details: [e.message, url] })
})
}
export default function ({ url, singleWindow }) {
export default function UrlPlayer ({ url, singleWindow }) {
const [status, setStatus] = useState(INITIAL_STATUS)
const [vmParts, setParts] = useState(null)
@ -54,8 +54,8 @@ export default function ({ url, singleWindow }) {
return vmParts
? (<Player {...{
vmParts,
singleWindow
}} />)
vmParts,
singleWindow,
}} />)
: (<Status {...status} />)
}

View file

@ -7,27 +7,27 @@ const formats = [
{
id: 'bocfel',
extensions: /z([3458]|blorb)$/,
engine: bocfel
engine: bocfel,
},
{
id: 'git',
extensions: /(gblorb|ulx)$/,
engine: git
engine: git,
},
{
id: 'hugo',
extensions: /hex$/,
engine: hugo
engine: hugo,
},
{
id: 'tads',
extensions: /(gam|t3)$/,
engine: tads
}
engine: tads,
},
]
export const engineByFilename = filename => {
const format = formats.find(x =>
export const engineByFilename = (filename) => {
const format = formats.find((x) =>
x.extensions.test(filename))
if (format) {

View file

@ -1,6 +1,6 @@
import {
compressToUTF16 as encode,
decompressFromUTF16 as decode
decompressFromUTF16 as decode,
} from 'lz-string'
export const Handlers = ({
@ -8,33 +8,33 @@ export const Handlers = ({
setWindows,
setCurrentWindowId,
setInputType,
setInbox
setInbox,
}) => ({
onInit: _ => {
onInit: () => {
setStatus({ stage: 'ready' })
},
/* */
onUpdateWindows: windows => {
onUpdateWindows: (windows) => {
setWindows(windows)
},
onUpdateInputs: data => {
onUpdateInputs: (data) => {
if (data.length === 0) return null
const { type, id } = data[0]
setCurrentWindowId(id)
setInputType(type)
},
onUpdateContent: inbox => {
onUpdateContent: (inbox) => {
setInbox(inbox)
},
onDisable: _ => {
onDisable: () => {
setInputType(null)
},
/* */
onFileNameRequest: (tosave, usage, _, setFileName) => {
setFileName({
usage,
filename: prompt('Enter the filename')
filename: prompt('Enter the filename'),
})
},
onFileRead: ({ filename }) => {
@ -45,7 +45,7 @@ export const Handlers = ({
localStorage.setItem(`fake-fs/${filename}`, encode(content))
},
/* */
onExit: _ => {
onExit: () => {
setInputType(null)
}
},
})

View file

@ -1,11 +1,11 @@
import { h } from 'preact'
export default function ({ themeEngine }) {
const options = themeEngine.themes.map(theme => (
export default function ThemeSelector ({ themeEngine }) {
const options = themeEngine.themes.map((theme) => (
<option
key={theme}
value={theme}>
{theme}
{theme}
</option>))
return (