Compare commits

..

2 Commits

Author SHA1 Message Date
Joni Juup
d3b0fef406 optimize editor navigation by removing shortcuts on mobile, more space to tabs 2022-08-26 16:22:44 +03:00
Joni Juup
4cbc316c62 small mobile style fixes 2022-08-26 16:03:46 +03:00
18 changed files with 234 additions and 261 deletions

View File

@@ -6,11 +6,14 @@ const ButtonGroup = styled('div', {
marginLeft: '1px', marginLeft: '1px',
[`& ${StyledButton}`]: { [`& ${StyledButton}`]: {
marginLeft: '-1px', marginLeft: '-1px',
px: '$4', px: '0.65rem',
zIndex: 2, zIndex: 2,
position: 'relative', position: 'relative',
'&:hover, &:focus': { '&:hover, &:focus': {
zIndex: 200 zIndex: 200
},
'@sm': {
px: '$4'
} }
}, },
[`& ${StyledButton}:not(:only-of-type):not(:first-child):not(:last-child)`]: { [`& ${StyledButton}:not(:only-of-type):not(:first-child):not(:last-child)`]: {

View File

@@ -40,11 +40,10 @@ const StyledContent = styled(DialogPrimitive.Content, {
color: '$mauve12', color: '$mauve12',
borderRadius: '$md', borderRadius: '$md',
position: 'relative', position: 'relative',
mb: '15%', mb: '0%',
boxShadow: '0px 10px 38px -5px rgba(22, 23, 24, 0.25), 0px 10px 20px -5px rgba(22, 23, 24, 0.2)', boxShadow: '0px 10px 38px -5px rgba(22, 23, 24, 0.25), 0px 10px 20px -5px rgba(22, 23, 24, 0.2)',
width: '90vw', width: '90vw',
maxWidth: '450px', maxWidth: '450px',
// maxHeight: "85vh",
padding: 25, padding: 25,
'@media (prefers-reduced-motion: no-preference)': { '@media (prefers-reduced-motion: no-preference)': {
animation: `${contentShow} 150ms cubic-bezier(0.16, 1, 0.3, 1)` animation: `${contentShow} 150ms cubic-bezier(0.16, 1, 0.3, 1)`
@@ -53,6 +52,9 @@ const StyledContent = styled(DialogPrimitive.Content, {
'.dark &': { '.dark &': {
backgroundColor: '$mauve5', backgroundColor: '$mauve5',
boxShadow: '0px 10px 38px 0px rgba(0, 0, 0, 0.85), 0px 10px 20px 0px rgba(0, 0, 0, 0.6)' boxShadow: '0px 10px 38px 0px rgba(0, 0, 0, 0.85), 0px 10px 20px 0px rgba(0, 0, 0, 0.6)'
},
'@md': {
mb: '8%'
} }
}) })

View File

@@ -78,7 +78,6 @@ const EditorNavigation = ({ renderNav }: { renderNav?: () => ReactNode }) => {
return ( return (
<Flex css={{ flexShrink: 0, gap: '$0' }}> <Flex css={{ flexShrink: 0, gap: '$0' }}>
<Flex <Flex
id="kissa"
ref={scrollRef} ref={scrollRef}
css={{ css={{
overflowX: 'scroll', overflowX: 'scroll',
@@ -181,7 +180,21 @@ const EditorNavigation = ({ renderNav }: { renderNav?: () => ReactNode }) => {
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
) : ( ) : (
<Button outline size="sm" css={{ mr: '$3' }} onClick={() => setPopUp(true)}> <Button
outline
size="sm"
css={{
mr: '-1px',
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
'@sm': {
borderTopRightRadius: '$sm',
borderBottomRightRadius: '$sm',
mr: '$3'
}
}}
onClick={() => setPopUp(true)}
>
<GithubLogo size="16px" /> Login <GithubLogo size="16px" /> Login
</Button> </Button>
)} )}
@@ -202,6 +215,9 @@ const EditorNavigation = ({ renderNav }: { renderNav?: () => ReactNode }) => {
alignSelf: 'flex-start', alignSelf: 'flex-start',
boxShadow: 'none' boxShadow: 'none'
}, },
'button:not(:last-child)': {
display: 'none'
},
'button:not(:first-child):not(:last-child)': { 'button:not(:first-child):not(:last-child)': {
borderRight: 0, borderRight: 0,
borderLeft: 0 borderLeft: 0
@@ -217,6 +233,11 @@ const EditorNavigation = ({ renderNav }: { renderNav?: () => ReactNode }) => {
'&:hover': { '&:hover': {
boxShadow: 'inset 0px 0px 0px 1px $colors$mauve12' boxShadow: 'inset 0px 0px 0px 1px $colors$mauve12'
} }
},
'@sm': {
'button:not(:last-child)': {
display: 'flex'
}
} }
}} }}
> >

View File

@@ -200,15 +200,15 @@ const HooksEditor = () => {
defaultValue={file?.content} defaultValue={file?.content}
// onChange={val => (state.files[snap.active].content = val)} // Auto save? // onChange={val => (state.files[snap.active].content = val)} // Auto save?
beforeMount={monaco => { beforeMount={monaco => {
// if (!snap.editorCtx) { if (!snap.editorCtx) {
// snap.files.forEach(file => snap.files.forEach(file =>
// monaco.editor.createModel( monaco.editor.createModel(
// file.content, file.content,
// file.language, file.language,
// monaco.Uri.parse(`file:///work/c/${file.name}`) monaco.Uri.parse(`file:///work/c/${file.name}`)
// ) )
// ) )
// } }
// create the web socket // create the web socket
if (!subscriptionRef.current) { if (!subscriptionRef.current) {
@@ -218,11 +218,6 @@ const HooksEditor = () => {
aliases: ['C', 'c', 'H', 'h'], aliases: ['C', 'c', 'H', 'h'],
mimetypes: ['text/plain'] mimetypes: ['text/plain']
}) })
monaco.languages.register({
id: 'text',
extensions: ['.txt'],
mimetypes: ['text/plain'],
})
MonacoServices.install(monaco) MonacoServices.install(monaco)
const webSocket = createWebSocket( const webSocket = createWebSocket(
process.env.NEXT_PUBLIC_LANGUAGE_SERVER_API_ENDPOINT || '' process.env.NEXT_PUBLIC_LANGUAGE_SERVER_API_ENDPOINT || ''

View File

@@ -33,7 +33,7 @@ import { styled } from '../stitches.config'
const ImageWrapper = styled(Flex, { const ImageWrapper = styled(Flex, {
position: 'relative', position: 'relative',
mt: '$2', mt: '$2',
mb: '$10', mb: '$6',
svg: { svg: {
// fill: "red", // fill: "red",
'.angle': { '.angle': {
@@ -66,16 +66,23 @@ const Navigation = () => {
<Container <Container
css={{ css={{
display: 'flex', display: 'flex',
alignItems: 'center' alignItems: 'center',
px: '$3',
'@sm': {
px: '$4'
}
}} }}
> >
<Flex <Flex
css={{ css={{
flex: 1, flex: 1,
alignItems: 'center', alignItems: 'center',
borderRight: '1px solid $colors$mauve6',
py: '$3', py: '$3',
pr: '$4' pr: '$0',
'@sm': {
borderRight: '1px solid $colors$mauve6',
pr: '$4'
}
}} }}
> >
<Link href={gistId ? `/develop/${gistId}` : '/develop'} passHref> <Link href={gistId ? `/develop/${gistId}` : '/develop'} passHref>
@@ -84,7 +91,11 @@ const Navigation = () => {
css={{ css={{
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
color: '$textColor' color: '$textColor',
mr: '$2',
'@sm': {
mr: '$4'
}
}} }}
> >
<Logo width="32px" height="32px" /> <Logo width="32px" height="32px" />
@@ -92,9 +103,12 @@ const Navigation = () => {
</Link> </Link>
<Flex <Flex
css={{ css={{
ml: '$5',
flexDirection: 'column', flexDirection: 'column',
gap: '1px' gap: '1px',
display: 'none',
'@md': {
display: 'flex'
}
}} }}
> >
{snap.loading ? ( {snap.loading ? (
@@ -135,8 +149,8 @@ const Navigation = () => {
css={{ css={{
display: 'flex', display: 'flex',
maxWidth: '1080px', maxWidth: '1080px',
width: '80vw', width: '90vw',
maxHeight: '80%', maxHeight: '90%',
backgroundColor: '$mauve1 !important', backgroundColor: '$mauve1 !important',
overflowY: 'auto', overflowY: 'auto',
background: 'black', background: 'black',
@@ -265,15 +279,18 @@ const Navigation = () => {
gridTemplateColumns: '1fr', gridTemplateColumns: '1fr',
gridTemplateRows: 'max-content', gridTemplateRows: 'max-content',
flex: 1, flex: 1,
p: '$7', p: '$4',
pb: '$16', pb: '$8',
gap: '$3', gap: '$3',
alignItems: 'normal', alignItems: 'normal',
flexWrap: 'wrap', flexWrap: 'wrap',
backgroundColor: '$mauve1', backgroundColor: '$mauve1',
'@md': { '@md': {
gridTemplateColumns: '1fr 1fr', gridTemplateColumns: '1fr 1fr',
gridTemplateRows: 'max-content' gridTemplateRows: 'max-content',
p: '$7',
pb: '$10',
paddingRight: '$12'
}, },
'@lg': { '@lg': {
gridTemplateColumns: '1fr 1fr 1fr', gridTemplateColumns: '1fr 1fr 1fr',
@@ -316,23 +333,30 @@ const Navigation = () => {
<Flex <Flex
css={{ css={{
flexWrap: 'nowrap', flexWrap: 'nowrap',
marginLeft: '$4', marginLeft: '$2',
overflowX: 'scroll', overflowX: 'scroll',
'&::-webkit-scrollbar': { '&::-webkit-scrollbar': {
height: 0, height: 0,
background: 'transparent' background: 'transparent'
}, },
scrollbarColor: 'transparent', scrollbarColor: 'transparent',
scrollbarWidth: 'none' scrollbarWidth: 'none',
'@sm': {
marginLeft: '$4'
}
}} }}
> >
<Stack <Stack
css={{ css={{
ml: '$4', ml: '$0',
gap: '$3', gap: '$2',
flexWrap: 'nowrap', flexWrap: 'nowrap',
alignItems: 'center', alignItems: 'center',
marginLeft: 'auto' marginLeft: 'auto',
'@sm': {
marginLeft: '$4',
gap: '$3'
}
}} }}
> >
<ButtonGroup> <ButtonGroup>

View File

@@ -7,7 +7,7 @@ const PanelBox = styled('div', {
flexDirection: 'column', flexDirection: 'column',
border: '1px solid $colors$mauve6', border: '1px solid $colors$mauve6',
backgroundColor: '$mauve2', backgroundColor: '$mauve2',
padding: '$3', padding: '$5',
borderRadius: '$sm', borderRadius: '$sm',
fontWeight: 'lighter', fontWeight: 'lighter',
height: 'auto', height: 'auto',

View File

@@ -11,7 +11,7 @@ import {
} from './Dialog' } from './Dialog'
import { Plus, X } from 'phosphor-react' import { Plus, X } from 'phosphor-react'
import { styled } from '../stitches.config' import { styled } from '../stitches.config'
import { capitalize, getFileExtention } from '../utils/helpers' import { capitalize } from '../utils/helpers'
import ContextMenu, { ContentMenuOption } from './ContextMenu' import ContextMenu, { ContentMenuOption } from './ContextMenu'
const ErrorText = styled(Text, { const ErrorText = styled(Text, {
@@ -97,7 +97,7 @@ export const Tabs = ({
if (!tabname) { if (!tabname) {
return { error: `Please enter ${label.toLocaleLowerCase()} name.` } return { error: `Please enter ${label.toLocaleLowerCase()} name.` }
} }
let ext = getFileExtention(tabname) let ext = (tabname.includes('.') && tabname.split('.').pop()) || ''
if (!ext && defaultExtension) { if (!ext && defaultExtension) {
ext = defaultExtension ext = defaultExtension
@@ -109,7 +109,7 @@ export const Tabs = ({
if (extensionRequired && !ext) { if (extensionRequired && !ext) {
return { error: 'File extension is required!' } return { error: 'File extension is required!' }
} }
if (allowedExtensions && ext && !allowedExtensions.includes(ext)) { if (allowedExtensions && !allowedExtensions.includes(ext)) {
return { error: 'This file extension is not allowed!' } return { error: 'This file extension is not allowed!' }
} }
if (headerExtraValidation && !tabname.match(headerExtraValidation.regex)) { if (headerExtraValidation && !tabname.match(headerExtraValidation.regex)) {

View File

@@ -19,7 +19,6 @@ import { TxJson } from './json'
import { TxUI } from './ui' import { TxUI } from './ui'
import { default as _estimateFee } from '../../utils/estimateFee' import { default as _estimateFee } from '../../utils/estimateFee'
import toast from 'react-hot-toast' import toast from 'react-hot-toast'
import { combineFlags, extractFlags, transactionFlags } from '../../state/constants/flags'
export interface TransactionProps { export interface TransactionProps {
header: string header: string
@@ -40,17 +39,14 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
const prepareOptions = useCallback( const prepareOptions = useCallback(
(state: Partial<TransactionState> = txState) => { (state: Partial<TransactionState> = txState) => {
const { selectedTransaction, selectedDestAccount, selectedAccount, txFields, selectedFlags } = const { selectedTransaction, selectedDestAccount, selectedAccount, txFields } = state
state
const TransactionType = selectedTransaction?.value || null const TransactionType = selectedTransaction?.value || null
const Destination = selectedDestAccount?.value || txFields?.Destination const Destination = selectedDestAccount?.value || txFields?.Destination
const Account = selectedAccount?.value || null const Account = selectedAccount?.value || null
const Flags = combineFlags(selectedFlags?.map(flag => flag.value)) || txFields?.Flags
return prepareTransaction({ return prepareTransaction({
...txFields, ...txFields,
Flags,
TransactionType, TransactionType,
Destination, Destination,
Account Account
@@ -140,13 +136,8 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
} else { } else {
fields.Destination = undefined fields.Destination = undefined
} }
if (transactionType?.value && transactionFlags[transactionType?.value] && fields.Flags) {
nwState.selectedFlags = extractFlags(transactionType.value, fields.Flags)
fields.Flags = undefined
}
nwState.txFields = fields nwState.txFields = fields
const state = modifyTxState(header, nwState, { replaceState: true }) const state = modifyTxState(header, nwState, { replaceState: true })
const editorValue = getJsonString(state) const editorValue = getJsonString(state)
return setState({ editorValue }) return setState({ editorValue })
@@ -188,22 +179,22 @@ const Transaction: FC<TransactionProps> = ({ header, state: txState, ...props })
estimateFee={estimateFee} estimateFee={estimateFee}
/> />
) : ( ) : (
<TxUI <TxUI state={txState} setState={setState} estimateFee={estimateFee} />
state={txState}
resetState={resetState}
setState={setState}
estimateFee={estimateFee}
/>
)} )}
<Flex <Flex
row row
css={{ css={{
justifyContent: 'space-between', justifyContent: 'space-between',
position: 'absolute',
left: 0,
bottom: 0,
width: '100%', width: '100%',
mb: '$1' mb: '$2',
mt: '$1',
'@md': {
position: 'absolute',
left: 0,
bottom: 0,
mt: '$0',
mb: '$2'
}
}} }}
> >
<Button <Button

View File

@@ -17,19 +17,16 @@ import state from '../../state'
import { streamState } from '../DebugStream' import { streamState } from '../DebugStream'
import { Button } from '..' import { Button } from '..'
import Textarea from '../Textarea' import Textarea from '../Textarea'
import { getFlags } from '../../state/constants/flags'
interface UIProps { interface UIProps {
setState: (pTx?: Partial<TransactionState> | undefined) => TransactionState | undefined setState: (pTx?: Partial<TransactionState> | undefined) => TransactionState | undefined
resetState: (tt?: SelectOption) => TransactionState | undefined
state: TransactionState state: TransactionState
estimateFee?: (...arg: any) => Promise<string | undefined> estimateFee?: (...arg: any) => Promise<string | undefined>
} }
export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estimateFee }) => { export const TxUI: FC<UIProps> = ({ state: txState, setState, estimateFee }) => {
const { accounts } = useSnapshot(state) const { accounts } = useSnapshot(state)
const { selectedAccount, selectedDestAccount, selectedTransaction, txFields, selectedFlags } = const { selectedAccount, selectedDestAccount, selectedTransaction, txFields } = txState
txState
const accountOptions: SelectOption[] = accounts.map(acc => ({ const accountOptions: SelectOption[] = accounts.map(acc => ({
label: acc.name, label: acc.name,
@@ -43,15 +40,23 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
})) }))
.filter(acc => acc.value !== selectedAccount?.value) .filter(acc => acc.value !== selectedAccount?.value)
const flagsOptions: SelectOption[] = Object.entries(
getFlags(selectedTransaction?.value) || {}
).map(([label, value]) => ({
label,
value
}))
const [feeLoading, setFeeLoading] = useState(false) const [feeLoading, setFeeLoading] = useState(false)
const resetFields = useCallback(
(tt: string) => {
const fields = getTxFields(tt)
if (fields.Destination !== undefined) {
setState({ selectedDestAccount: null })
fields.Destination = ''
} else {
fields.Destination = undefined
}
return setState({ txFields: fields })
},
[setState]
)
const handleSetAccount = (acc: SelectOption) => { const handleSetAccount = (acc: SelectOption) => {
setState({ selectedAccount: acc }) setState({ selectedAccount: acc })
streamState.selectedAccount = acc streamState.selectedAccount = acc
@@ -87,11 +92,11 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
(tt: SelectOption) => { (tt: SelectOption) => {
setState({ selectedTransaction: tt }) setState({ selectedTransaction: tt })
const newState = resetState(tt) const newState = resetFields(tt.value)
handleEstimateFee(newState, true) handleEstimateFee(newState, true)
}, },
[handleEstimateFee, resetState, setState] [handleEstimateFee, resetFields, setState]
) )
const switchToJson = () => setState({ viewType: 'json' }) const switchToJson = () => setState({ viewType: 'json' })
@@ -110,16 +115,14 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
[selectedTransaction?.value] [selectedTransaction?.value]
) )
const richFields = ['TransactionType', 'Account'] const specialFields = ['TransactionType', 'Account']
if (fields.Destination !== undefined) { if (fields.Destination !== undefined) {
richFields.push('Destination') specialFields.push('Destination')
} }
if (flagsOptions.length) { const otherFields = Object.keys(txFields).filter(k => !specialFields.includes(k)) as [
richFields.push('Flags') keyof TxFields
} ]
const otherFields = Object.keys(txFields).filter(k => !richFields.includes(k)) as [keyof TxFields]
return ( return (
<Container <Container
@@ -134,11 +137,14 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
row row
fluid fluid
css={{ css={{
justifyContent: 'flex-end', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
mb: '$3', mb: '$3',
mt: '1px', mt: '1px',
pr: '1px' pr: '1px',
'@xl': {
justifyContent: 'flex-end'
}
}} }}
> >
<Text muted css={{ mr: '$3' }}> <Text muted css={{ mr: '$3' }}>
@@ -149,7 +155,13 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
placeholder="Select transaction type" placeholder="Select transaction type"
options={transactionsOptions} options={transactionsOptions}
hideSelectedOptions hideSelectedOptions
css={{ width: '70%' }} css={{
width: '60%',
minWidth: '200px',
'@lg': {
width: '70%'
}
}}
value={selectedTransaction} value={selectedTransaction}
onChange={(tt: any) => handleChangeTxType(tt)} onChange={(tt: any) => handleChangeTxType(tt)}
/> />
@@ -158,10 +170,13 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
row row
fluid fluid
css={{ css={{
justifyContent: 'flex-end', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
mb: '$3', mb: '$3',
pr: '1px' pr: '1px',
'@xl': {
justifyContent: 'flex-end'
}
}} }}
> >
<Text muted css={{ mr: '$3' }}> <Text muted css={{ mr: '$3' }}>
@@ -170,30 +185,45 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
<Select <Select
instanceId="from-account" instanceId="from-account"
placeholder="Select your account" placeholder="Select your account"
css={{ width: '70%' }} css={{
width: '60%',
minWidth: '200px',
'@lg': {
width: '70%'
}
}}
options={accountOptions} options={accountOptions}
value={selectedAccount} value={selectedAccount}
onChange={(acc: any) => handleSetAccount(acc)} // TODO make react-select have correct types for acc onChange={(acc: any) => handleSetAccount(acc)} // TODO make react-select have correct types for acc
/> />
</Flex> </Flex>
{richFields.includes('Destination') && ( {fields.Destination !== undefined && (
<Flex <Flex
row row
fluid fluid
css={{ css={{
justifyContent: 'flex-end', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
mb: '$3', mb: '$3',
pr: '1px' pr: '1px',
'@xl': {
justifyContent: 'flex-end'
}
}} }}
> >
<Text muted css={{ mr: '$3', textAlign: 'end' }}> <Text muted css={{ mr: '$3' }}>
Destination account:{' '} Destination account:{' '}
</Text> </Text>
<Select <Select
instanceId="to-account" instanceId="to-account"
placeholder="Select the destination account" placeholder="Select the destination account"
css={{ width: '70%' }} css={{
width: '60%',
minWidth: '200px',
'@lg': {
width: '70%'
}
}}
options={destAccountOptions} options={destAccountOptions}
value={selectedDestAccount} value={selectedDestAccount}
isClearable isClearable
@@ -201,36 +231,6 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
/> />
</Flex> </Flex>
)} )}
{richFields.includes('Flags') && (
<Flex
row
fluid
css={{
justifyContent: 'flex-end',
alignItems: 'center',
mb: '$3',
pr: '1px'
}}
>
<Text muted css={{ mr: '$3' }}>
Flags:{' '}
</Text>
<Select
isClearable
css={{ width: '70%' }}
instanceId="flags"
placeholder="Select flags to apply"
menuPosition="fixed"
value={selectedFlags}
isMulti
options={flagsOptions}
onChange={flags => setState({ selectedFlags: flags as any })}
closeMenuOnSelect={
selectedFlags ? selectedFlags.length >= flagsOptions.length - 1 : false
}
/>
</Flex>
)}
{otherFields.map(field => { {otherFields.map(field => {
let _value = txFields[field] let _value = txFields[field]
@@ -256,9 +256,12 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
row row
fluid fluid
css={{ css={{
justifyContent: 'flex-end', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
position: 'relative' position: 'relative',
'@xl': {
justifyContent: 'flex-end'
}
}} }}
> >
<Text muted css={{ mr: '$3' }}> <Text muted css={{ mr: '$3' }}>
@@ -271,9 +274,13 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
spellCheck={false} spellCheck={false}
onChange={switchToJson} onChange={switchToJson}
css={{ css={{
width: '70%', width: '60%',
minWidth: '200px',
flex: 'inherit', flex: 'inherit',
resize: 'vertical' resize: 'vertical',
'@lg': {
width: '70%'
}
}} }}
/> />
) : ( ) : (
@@ -298,7 +305,8 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
: undefined : undefined
} }
css={{ css={{
width: '70%', width: '60%',
minWidth: '200px',
flex: 'inherit', flex: 'inherit',
'-moz-appearance': 'textfield', '-moz-appearance': 'textfield',
'&::-webkit-outer-spin-button': { '&::-webkit-outer-spin-button': {
@@ -308,6 +316,9 @@ export const TxUI: FC<UIProps> = ({ state: txState, setState, resetState, estima
'&::-webkit-inner-spin-button ': { '&::-webkit-inner-spin-button ': {
'-webkit-appearance': 'none', '-webkit-appearance': 'none',
margin: 0 margin: 0
},
'@lg': {
width: '70%'
} }
}} }}
/> />

View File

@@ -6,7 +6,7 @@
"DestinationTag": 13, "DestinationTag": 13,
"Fee": "2000000", "Fee": "2000000",
"Sequence": 2470665, "Sequence": 2470665,
"Flags": "2147483648" "Flags": 2147483648
}, },
{ {
"TransactionType": "AccountSet", "TransactionType": "AccountSet",
@@ -48,7 +48,7 @@
"Account": "rsUiUMpnrgxQp24dJYZDhmV4bE3aBtQyt8", "Account": "rsUiUMpnrgxQp24dJYZDhmV4bE3aBtQyt8",
"Authorize": "rEhxGqkqPPSxQ3P25J66ft5TwpzV14k2de", "Authorize": "rEhxGqkqPPSxQ3P25J66ft5TwpzV14k2de",
"Fee": "10", "Fee": "10",
"Flags": "2147483648", "Flags": 2147483648,
"Sequence": 2 "Sequence": 2
}, },
{ {
@@ -109,9 +109,7 @@
"Fee": "10", "Fee": "10",
"NFTokenOffers": { "NFTokenOffers": {
"$type": "json", "$type": "json",
"$value": [ "$value": ["4AAAEEA76E3C8148473CB3840CE637676E561FB02BD4CA22CA59729EA815B862"]
"4AAAEEA76E3C8148473CB3840CE637676E561FB02BD4CA22CA59729EA815B862"
]
} }
}, },
{ {
@@ -122,7 +120,7 @@
"$value": "100", "$value": "100",
"$type": "xrp" "$type": "xrp"
}, },
"Flags": "1", "Flags": 1,
"Destination": "", "Destination": "",
"Fee": "10" "Fee": "10"
}, },
@@ -130,7 +128,7 @@
"TransactionType": "OfferCancel", "TransactionType": "OfferCancel",
"Account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", "Account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
"Fee": "12", "Fee": "12",
"Flags": "0", "Flags": 0,
"LastLedgerSequence": 7108629, "LastLedgerSequence": 7108629,
"OfferSequence": 6, "OfferSequence": 6,
"Sequence": 7 "Sequence": 7
@@ -139,7 +137,7 @@
"TransactionType": "OfferCreate", "TransactionType": "OfferCreate",
"Account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", "Account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
"Fee": "12", "Fee": "12",
"Flags": "0", "Flags": 0,
"LastLedgerSequence": 7108682, "LastLedgerSequence": 7108682,
"Sequence": 8, "Sequence": 8,
"TakerGets": "6000000", "TakerGets": "6000000",
@@ -157,7 +155,7 @@
"$type": "xrp" "$type": "xrp"
}, },
"Fee": "12", "Fee": "12",
"Flags": "2147483648", "Flags": 2147483648,
"Sequence": 2 "Sequence": 2
}, },
{ {
@@ -187,14 +185,14 @@
"Fee": "10" "Fee": "10"
}, },
{ {
"Flags": "0", "Flags": 0,
"TransactionType": "SetRegularKey", "TransactionType": "SetRegularKey",
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
"Fee": "12", "Fee": "12",
"RegularKey": "rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD" "RegularKey": "rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD"
}, },
{ {
"Flags": "0", "Flags": 0,
"TransactionType": "SignerListSet", "TransactionType": "SignerListSet",
"Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn",
"Fee": "12", "Fee": "12",
@@ -234,7 +232,7 @@
"TransactionType": "TrustSet", "TransactionType": "TrustSet",
"Account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", "Account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX",
"Fee": "12", "Fee": "12",
"Flags": "262144", "Flags": 262144,
"LastLedgerSequence": 8007750, "LastLedgerSequence": 8007750,
"LimitAmount": { "LimitAmount": {
"$type": "json", "$type": "json",
@@ -246,4 +244,4 @@
}, },
"Sequence": 12 "Sequence": 12
} }
] ]

View File

@@ -10,11 +10,10 @@ import Box from '../../components/Box'
import Button from '../../components/Button' import Button from '../../components/Button'
import Popover from '../../components/Popover' import Popover from '../../components/Popover'
import RunScript from '../../components/RunScript' import RunScript from '../../components/RunScript'
import state, { IFile } from '../../state' import state from '../../state'
import { compileCode } from '../../state/actions' import { compileCode } from '../../state/actions'
import { getSplit, saveSplit } from '../../state/actions/persistSplits' import { getSplit, saveSplit } from '../../state/actions/persistSplits'
import { styled } from '../../stitches.config' import { styled } from '../../stitches.config'
import { getFileExtention } from '../../utils/helpers'
const HooksEditor = dynamic(() => import('../../components/HooksEditor'), { const HooksEditor = dynamic(() => import('../../components/HooksEditor'), {
ssr: false ssr: false
@@ -148,8 +147,6 @@ const CompilerSettings = () => {
const Home: NextPage = () => { const Home: NextPage = () => {
const snap = useSnapshot(state) const snap = useSnapshot(state)
const activeFile = snap.files[snap.active] as IFile | undefined
const activeFileExt = getFileExtention(activeFile?.name)
return ( return (
<Split <Split
direction="vertical" direction="vertical"
@@ -162,7 +159,7 @@ const Home: NextPage = () => {
> >
<main style={{ display: 'flex', flex: 1, position: 'relative' }}> <main style={{ display: 'flex', flex: 1, position: 'relative' }}>
<HooksEditor /> <HooksEditor />
{activeFileExt === 'c' && ( {snap.files[snap.active]?.name?.split('.')?.[1]?.toLowerCase() === 'c' && (
<Hotkeys <Hotkeys
keyName="command+b,ctrl+b" keyName="command+b,ctrl+b"
onKeyDown={() => !snap.compiling && snap.files.length && compileCode(snap.active)} onKeyDown={() => !snap.compiling && snap.files.length && compileCode(snap.active)}
@@ -196,7 +193,7 @@ const Home: NextPage = () => {
</Flex> </Flex>
</Hotkeys> </Hotkeys>
)} )}
{activeFileExt === 'js' && ( {snap.files[snap.active]?.name?.split('.')?.[1]?.toLowerCase() === 'js' && (
<Hotkeys <Hotkeys
keyName="command+b,ctrl+b" keyName="command+b,ctrl+b"
onKeyDown={() => !snap.compiling && snap.files.length && compileCode(snap.active)} onKeyDown={() => !snap.compiling && snap.files.length && compileCode(snap.active)}
@@ -212,7 +209,7 @@ const Home: NextPage = () => {
gap: '$2' gap: '$2'
}} }}
> >
<RunScript file={activeFile as IFile} /> <RunScript file={snap.files[snap.active]} />
</Flex> </Flex>
</Hotkeys> </Hotkeys>
)} )}
@@ -228,7 +225,7 @@ const Home: NextPage = () => {
> >
<LogBox title="Development Log" clearLog={() => (state.logs = [])} logs={snap.logs} /> <LogBox title="Development Log" clearLog={() => (state.logs = [])} logs={snap.logs} />
</Flex> </Flex>
{activeFileExt === 'js' && ( {snap.files[snap.active]?.name?.split('.')?.[1]?.toLowerCase() === 'js' && (
<Flex <Flex
css={{ css={{
flex: 1 flex: 1

View File

@@ -68,6 +68,7 @@ const Test = () => {
justifyContent: 'center', justifyContent: 'center',
p: '$3 $2' p: '$3 $2'
}} }}
className="split-mobile-forceAutoHeight"
> >
<Split <Split
direction="horizontal" direction="horizontal"
@@ -82,6 +83,7 @@ const Test = () => {
height: '100%' height: '100%'
}} }}
onDragEnd={e => saveSplit('testHorizontal', e)} onDragEnd={e => saveSplit('testHorizontal', e)}
className="split-mobile-forceVertical"
> >
<Box css={{ width: '55%', px: '$2' }}> <Box css={{ width: '55%', px: '$2' }}>
<Tabs <Tabs
@@ -105,7 +107,18 @@ const Test = () => {
))} ))}
</Tabs> </Tabs>
</Box> </Box>
<Box css={{ width: '45%', mx: '$2', height: '100%' }}> <Box
css={{
width: '45%',
mx: '$0',
mt: '$1',
height: '100%',
'@md': {
mx: '$2',
mt: '$0'
}
}}
>
<Accounts card hideDeployBtn showHookStats /> <Accounts card hideDeployBtn showHookStats />
</Box> </Box>
</Split> </Split>
@@ -131,6 +144,7 @@ const Test = () => {
<Flex> <Flex>
<Split <Split
direction="horizontal" direction="horizontal"
className="split-mobile-forceVertical"
sizes={[50, 50]} sizes={[50, 50]}
minSize={[320, 160]} minSize={[320, 160]}
gutterSize={4} gutterSize={4}

View File

@@ -1,19 +1,21 @@
import { getFileExtention } from '../../utils/helpers'
import state, { IFile } from '../index' import state, { IFile } from '../index'
const languageMapping: Record<string, string | undefined> = { const languageMapping = {
ts: 'typescript', ts: 'typescript',
js: 'javascript', js: 'javascript',
md: 'markdown', md: 'markdown',
c: 'c', c: 'c',
h: 'c', h: 'c',
txt: 'text' other: ''
} } /* Initializes empty file to global state */
export const createNewFile = (name: string) => { export const createNewFile = (name: string) => {
const ext = getFileExtention(name) || '' const tempName = name.split('.')
const fileExt = tempName[tempName.length - 1] || 'other'
const emptyFile: IFile = { name, language: languageMapping[ext] || 'text', content: '' } const emptyFile: IFile = {
name,
language: languageMapping[fileExt as 'ts' | 'js' | 'md' | 'c' | 'h' | 'other'],
content: ''
}
state.files.push(emptyFile) state.files.push(emptyFile)
state.active = state.files.length - 1 state.active = state.files.length - 1
} }
@@ -22,8 +24,5 @@ export const renameFile = (oldName: string, nwName: string) => {
const file = state.files.find(file => file.name === oldName) const file = state.files.find(file => file.name === oldName)
if (!file) throw Error(`No file exists with name ${oldName}`) if (!file) throw Error(`No file exists with name ${oldName}`)
const ext = getFileExtention(nwName) || ''
const language = languageMapping[ext] || 'text'
file.name = nwName file.name = nwName
file.language = language
} }

View File

@@ -1,79 +0,0 @@
import { SelectOption } from '../transactions';
interface Flags {
[key: string]: string;
}
export const transactionFlags: { [key: /* TransactionType */ string]: Flags } = {
"*": {
tfFullyCanonicalSig: '0x80000000'
},
Payment: {
tfNoDirectRipple: '0x00010000',
tfPartialPayment: '0x00020000',
tfLimitQuality: '0x00040000',
},
AccountSet: {
tfRequireDestTag: '0x00010000',
tfOptionalDestTag: '0x00020000',
tfRequireAuth: '0x00040000',
tfOptionalAuth: '0x00080000',
tfDisallowXRP: '0x00100000',
tfAllowXRP: '0x00200000',
},
NFTokenCreateOffer: {
tfSellNFToken: '0x00000001',
},
NFTokenMint: {
tfBurnable: '0x00000001',
tfOnlyXRP: '0x00000002',
tfTrustLine: '0x00000004',
tfTransferable: '0x00000008',
},
OfferCreate: {
tfPassive: '0x00010000',
tfImmediateOrCancel: '0x00020000',
tfFillOrKill: '0x00040000',
tfSell: '0x00080000',
},
PaymentChannelClaim: {
tfRenew: '0x00010000',
tfClose: '0x00020000',
},
TrustSet: {
tfSetfAuth: '0x00010000',
tfSetNoRipple: '0x00020000',
tfClearNoRipple: '0x00040000',
tfSetFreeze: '0x00100000',
tfClearFreeze: '0x00200000',
},
}
export const getFlags = (tt?: string) => {
if (!tt) return
const flags = {
...transactionFlags['*'],
...transactionFlags[tt]
}
return flags
}
export function combineFlags(flags?: string[]): string | undefined {
if (!flags) return
const num = flags.reduce((cumm, curr) => cumm | BigInt(curr), BigInt(0))
return num.toString()
}
export function extractFlags(transactionType: string, flags?: string | number,): SelectOption[] {
const flagsObj = getFlags(transactionType)
if (!flags || !flagsObj) return []
const extracted = Object.entries(flagsObj).reduce((cumm, [label, value]) => {
return (BigInt(flags) & BigInt(value)) ? cumm.concat({ label, value }) : cumm
}, [] as SelectOption[])
return extracted
}

View File

@@ -4,7 +4,6 @@ import transactionsData from '../content/transactions.json'
import state from '.' import state from '.'
import { showAlert } from '../state/actions/showAlert' import { showAlert } from '../state/actions/showAlert'
import { parseJSON } from '../utils/json' import { parseJSON } from '../utils/json'
import { extractFlags, getFlags } from './constants/flags'
export type SelectOption = { export type SelectOption = {
value: string value: string
@@ -15,7 +14,6 @@ export interface TransactionState {
selectedTransaction: SelectOption | null selectedTransaction: SelectOption | null
selectedAccount: SelectOption | null selectedAccount: SelectOption | null
selectedDestAccount: SelectOption | null selectedDestAccount: SelectOption | null
selectedFlags: SelectOption[] | null
txIsLoading: boolean txIsLoading: boolean
txIsDisabled: boolean txIsDisabled: boolean
txFields: TxFields txFields: TxFields
@@ -33,7 +31,6 @@ export const defaultTransaction: TransactionState = {
selectedTransaction: null, selectedTransaction: null,
selectedAccount: null, selectedAccount: null,
selectedDestAccount: null, selectedDestAccount: null,
selectedFlags: null,
txIsLoading: false, txIsLoading: false,
txIsDisabled: false, txIsDisabled: false,
txFields: {}, txFields: {},
@@ -131,8 +128,9 @@ export const prepareTransaction = (data: any) => {
try { try {
options[field] = JSON.parse(_value.$value) options[field] = JSON.parse(_value.$value)
} catch (error) { } catch (error) {
const message = `Input error for json field '${field}': ${error instanceof Error ? error.message : '' const message = `Input error for json field '${field}': ${
}` error instanceof Error ? error.message : ''
}`
console.error(message) console.error(message)
options[field] = _value.$value options[field] = _value.$value
} }
@@ -207,13 +205,6 @@ export const prepareState = (value: string, transactionType?: string) => {
rest.Destination = Destination rest.Destination = Destination
} }
if (getFlags(TransactionType) && rest.Flags) {
const flags = extractFlags(TransactionType, rest.Flags)
rest.Flags = undefined
tx.selectedFlags = flags
}
Object.keys(rest).forEach(field => { Object.keys(rest).forEach(field => {
const value = rest[field] const value = rest[field]
const schemaVal = schema[field as keyof TxFields] const schemaVal = schema[field as keyof TxFields]

View File

@@ -54,3 +54,15 @@ html.light .gutter-horizontal:hover {
.monaco-editor .monaco-hover { .monaco-editor .monaco-hover {
z-index: 9999; z-index: 9999;
} }
@media screen and (max-width: 48rem) {
.split-mobile-forceAutoHeight {
height: auto !important;
}
.split-mobile-forceVertical {
flex-direction: column !important;
}
.split-mobile-forceVertical > div {
width: 100% !important;
}
}

View File

@@ -13,9 +13,3 @@ export const capitalize = (value?: string) => {
return value[0].toLocaleUpperCase() + value.slice(1) return value[0].toLocaleUpperCase() + value.slice(1)
} }
export const getFileExtention = (filename?: string): string | undefined => {
if (!filename) return
const ext = (filename.includes('.') && filename.split('.').pop()) || undefined
return ext
}

View File

@@ -2725,9 +2725,9 @@ javascript-time-ago@^2.3.11:
relative-time-format "^1.0.7" relative-time-format "^1.0.7"
jose@^4.1.4, jose@^4.3.7: jose@^4.1.4, jose@^4.3.7:
version "4.10.0" version "4.6.0"
resolved "https://registry.yarnpkg.com/jose/-/jose-4.10.0.tgz#2e0b7bcc80dd0775f8a4588e55beb9460c37d60a" resolved "https://registry.npmjs.org/jose/-/jose-4.6.0.tgz"
integrity sha512-KEhB/eLGLomWGPTb+/RNbYsTjIyx03JmbqAyIyiXBuNSa7CmNrJd5ysFhblayzs/e/vbOPMUaLnjHUMhGp4yLw== integrity sha512-0hNAkhMBNi4soKSAX4zYOFV+aqJlEz/4j4fregvasJzEVtjDChvWqRjPvHwLqr5hx28Ayr6bsOs1Kuj87V0O8w==
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0" version "4.0.0"