167 lines
5.0 KiB
TypeScript
167 lines
5.0 KiB
TypeScript
import React, { useState } from 'react'
|
|
import { useSnapshot } from 'valtio'
|
|
|
|
import { useTheme } from 'next-themes'
|
|
import { useRouter } from 'next/router'
|
|
import NextLink from 'next/link'
|
|
import ReactTimeAgo from 'react-time-ago'
|
|
import filesize from 'filesize'
|
|
|
|
import Box from './Box'
|
|
import Container from './Container'
|
|
import state from '../state'
|
|
import wat from '../utils/wat-highlight'
|
|
|
|
import EditorNavigation from './EditorNavigation'
|
|
import { Button, Text, Link, Flex, Tabs, Tab } from '.'
|
|
import Monaco from './Monaco'
|
|
|
|
const FILESIZE_BREAKPOINTS: [number, number] = [2 * 1024, 5 * 1024]
|
|
|
|
const DeployEditor = () => {
|
|
const snap = useSnapshot(state)
|
|
const router = useRouter()
|
|
const { theme } = useTheme()
|
|
|
|
const [showContent, setShowContent] = useState(false)
|
|
|
|
const compiledFiles = snap.files.filter(file => file.compiledContent)
|
|
const activeFile = compiledFiles[snap.activeWat]
|
|
|
|
const renderNav = () => (
|
|
<Tabs activeIndex={snap.activeWat} onChangeActive={idx => (state.activeWat = idx)}>
|
|
{compiledFiles.map((file, index) => {
|
|
return <Tab key={file.name} header={`${file.name}.wat`} />
|
|
})}
|
|
</Tabs>
|
|
)
|
|
|
|
const compiledSize = activeFile?.compiledContent?.byteLength || 0
|
|
const color =
|
|
compiledSize > FILESIZE_BREAKPOINTS[1]
|
|
? '$error'
|
|
: compiledSize > FILESIZE_BREAKPOINTS[0]
|
|
? '$warning'
|
|
: '$success'
|
|
|
|
const isContentChanged = activeFile && activeFile.compiledValueSnapshot !== activeFile.content
|
|
// const hasDeployErrors = activeFile && activeFile.containsErrors;
|
|
|
|
const CompiledStatView = activeFile && (
|
|
<Flex
|
|
column
|
|
align="center"
|
|
css={{
|
|
fontSize: '$sm',
|
|
fontFamily: '$monospace',
|
|
textAlign: 'center'
|
|
}}
|
|
>
|
|
<Flex row align="center">
|
|
<Text css={{ mr: '$1' }}>Compiled {activeFile.name.split('.')[0] + '.wasm'}</Text>
|
|
{activeFile?.lastCompiled && <ReactTimeAgo date={activeFile.lastCompiled} locale="en-US" />}
|
|
|
|
{activeFile.compiledContent?.byteLength && (
|
|
<Text css={{ ml: '$2', color }}>({filesize(activeFile.compiledContent.byteLength)})</Text>
|
|
)}
|
|
</Flex>
|
|
{activeFile.compiledContent?.byteLength && activeFile.compiledContent?.byteLength >= 64000 && (
|
|
<Flex css={{ flexDirection: 'column', py: '$3', pb: '$1' }}>
|
|
<Text css={{ ml: '$2', color: '$error' }}>
|
|
File size is larger than 64kB, cannot set hook!
|
|
</Text>
|
|
</Flex>
|
|
)}
|
|
<Button variant="link" onClick={() => setShowContent(true)}>
|
|
View as WAT-file
|
|
</Button>
|
|
{isContentChanged && (
|
|
<Text warning>
|
|
File contents were changed after last compile, compile again to incorporate your latest
|
|
changes in the build.
|
|
</Text>
|
|
)}
|
|
</Flex>
|
|
)
|
|
const NoContentView = !snap.loading && router.isReady && (
|
|
<Text
|
|
css={{
|
|
mt: '-60px',
|
|
fontSize: '$sm',
|
|
fontFamily: '$monospace',
|
|
maxWidth: '300px',
|
|
textAlign: 'center'
|
|
}}
|
|
>
|
|
{`You haven't compiled any files yet, compile files on `}
|
|
<NextLink legacyBehavior shallow href={`/develop/${router.query.slug}`} passHref>
|
|
<Link as="a">develop view</Link>
|
|
</NextLink>
|
|
</Text>
|
|
)
|
|
|
|
const isContent = snap.files?.filter(file => file.compiledWatContent).length > 0 && router.isReady
|
|
return (
|
|
<Box
|
|
css={{
|
|
flex: 1,
|
|
display: 'flex',
|
|
position: 'relative',
|
|
flexDirection: 'column',
|
|
backgroundColor: '$mauve2',
|
|
width: '100%'
|
|
}}
|
|
>
|
|
<EditorNavigation renderNav={renderNav} />
|
|
<Container
|
|
css={{
|
|
display: 'flex',
|
|
flex: 1,
|
|
justifyContent: 'center',
|
|
alignItems: 'center'
|
|
}}
|
|
>
|
|
{!isContent ? (
|
|
NoContentView
|
|
) : !showContent ? (
|
|
CompiledStatView
|
|
) : (
|
|
<Monaco
|
|
className="hooks-editor"
|
|
defaultLanguage={'wat'}
|
|
language={'wat'}
|
|
path={`file://tmp/c/${activeFile?.name}.wat`}
|
|
value={activeFile?.compiledWatContent || ''}
|
|
beforeMount={monaco => {
|
|
monaco.languages.register({ id: 'wat' })
|
|
monaco.languages.setLanguageConfiguration('wat', wat.config)
|
|
monaco.languages.setMonarchTokensProvider('wat', wat.tokens)
|
|
}}
|
|
onMount={editor => {
|
|
editor.updateOptions({
|
|
glyphMargin: true,
|
|
readOnly: true
|
|
})
|
|
}}
|
|
theme={theme === 'dark' ? 'dark' : 'light'}
|
|
overlay={
|
|
<Flex
|
|
css={{
|
|
m: '$1',
|
|
ml: 'auto',
|
|
fontSize: '$sm',
|
|
color: '$textMuted'
|
|
}}
|
|
>
|
|
<Link onClick={() => setShowContent(false)}>Exit editor mode</Link>
|
|
</Flex>
|
|
}
|
|
/>
|
|
)}
|
|
</Container>
|
|
</Box>
|
|
)
|
|
}
|
|
|
|
export default DeployEditor
|