|
|
|
@ -6,17 +6,27 @@ import Menu from '../Menu/Menu'
|
|
|
|
|
import useGameState from '../../hooks/useGameState'
|
|
|
|
|
import useSharedState from '../../hooks/useSharedState'
|
|
|
|
|
|
|
|
|
|
export default function Text({promptVisible, handleCommand, showReflection}) {
|
|
|
|
|
import {game} from '../../engine'
|
|
|
|
|
|
|
|
|
|
export default function Text({promptVisible: promptEnabled, handleCommand, showReflection}) {
|
|
|
|
|
const inputRef = useRef()
|
|
|
|
|
const outputRef = useRef()
|
|
|
|
|
const textRef = useRef()
|
|
|
|
|
const menuRef = useRef()
|
|
|
|
|
const {messages} = useGameState()
|
|
|
|
|
const [currentMenu] = useSharedState('currentMenu')
|
|
|
|
|
const [_, updateArbitrary] = useState(0) // eslint-disable-line no-unused-vars
|
|
|
|
|
const forceRender = () => updateArbitrary(arbitrary => arbitrary + 1)
|
|
|
|
|
|
|
|
|
|
const [currentInput, setCurrentInput] = useState('')
|
|
|
|
|
const [currentScroll, setCurrentScroll] = useState(0)
|
|
|
|
|
|
|
|
|
|
const currentPause = messages.findIndex(message => (message.type === 'pause' && message.resolved === false))
|
|
|
|
|
const outputPaused = currentPause > -1
|
|
|
|
|
|
|
|
|
|
let printedMessages = !outputPaused ? messages : messages.slice(0, currentPause)
|
|
|
|
|
const promptVisible = promptEnabled && !outputPaused
|
|
|
|
|
|
|
|
|
|
async function onSubmit(ev) {
|
|
|
|
|
if(ev) ev.preventDefault()
|
|
|
|
|
|
|
|
|
@ -62,12 +72,30 @@ export default function Text({promptVisible, handleCommand, showReflection}) {
|
|
|
|
|
inputRef.current.focus()
|
|
|
|
|
}, [currentMenu])
|
|
|
|
|
|
|
|
|
|
// Unpause output on space or return
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if(!outputPaused) return;
|
|
|
|
|
|
|
|
|
|
function handleKey(ev) {
|
|
|
|
|
if(ev.key !== ' ' && ev.key !== 'Enter') return;
|
|
|
|
|
ev.preventDefault()
|
|
|
|
|
|
|
|
|
|
console.log('Unpausing')
|
|
|
|
|
game.getState().messages[currentPause].resolved = true
|
|
|
|
|
game.saveDraft()
|
|
|
|
|
forceRender()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
document.addEventListener('keydown', handleKey)
|
|
|
|
|
return () => document.removeEventListener('keydown', handleKey)
|
|
|
|
|
}, [currentPause, outputPaused, messages])
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<div ref={textRef} className={styles.playArea}>
|
|
|
|
|
<Menu containerRef={menuRef}/>
|
|
|
|
|
<div ref={outputRef} onScroll={() => setCurrentScroll(outputRef.current?.scrollTop)} className={styles.output + (currentMenu !== null ? ' ' + styles.noMouse : '')}>
|
|
|
|
|
{messages.map((message, i) => {
|
|
|
|
|
{printedMessages.map((message, i) => {
|
|
|
|
|
if(message.type === 'message')
|
|
|
|
|
return <ReactMarkdown key={i}>{message.message}</ReactMarkdown>
|
|
|
|
|
|
|
|
|
@ -76,12 +104,17 @@ export default function Text({promptVisible, handleCommand, showReflection}) {
|
|
|
|
|
|
|
|
|
|
return null
|
|
|
|
|
})}
|
|
|
|
|
{outputPaused && (
|
|
|
|
|
<p className={styles.pausePrompt}>
|
|
|
|
|
(Press [RETURN] to continue)
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
<form style={{pointerEvents: currentMenu ? 'none' : 'initial'}} className={styles.input + (!promptVisible ? ' ' + styles.hidden : '')} onSubmit={onSubmit}>
|
|
|
|
|
<form style={{pointerEvents: currentMenu ? 'none' : 'initial'}} className={styles.input + (!promptVisible ? ' ' + styles.hidden : '')} onSubmit={onSubmit}>
|
|
|
|
|
<input autoFocus ref={inputRef} onChange={ev => setCurrentInput(ev.target.value)} id="gameInput"/>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
{showReflection && <Reflection promptVisible={promptVisible} messages={messages} currentInput={currentInput} currentScroll={currentScroll}/>}
|
|
|
|
|
{showReflection && <Reflection outputPaused={outputPaused} promptVisible={promptVisible} messages={printedMessages} currentInput={currentInput} currentScroll={currentScroll}/>}
|
|
|
|
|
</>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|