|
|
|
@ -12,6 +12,7 @@ import { CopyToClipboard } from '@remix-ui/clipboard' |
|
|
|
|
import { configFileContent } from './compilerConfiguration' |
|
|
|
|
|
|
|
|
|
import './css/style.css' |
|
|
|
|
const defaultPath = "compiler_config.json" |
|
|
|
|
|
|
|
|
|
declare global { |
|
|
|
|
interface Window { |
|
|
|
@ -22,11 +23,23 @@ declare global { |
|
|
|
|
const _paq = window._paq = window._paq || [] //eslint-disable-line
|
|
|
|
|
|
|
|
|
|
export const CompilerContainer = (props: CompilerContainerProps) => { |
|
|
|
|
const { api, compileTabLogic, tooltip, modal, compiledFileName, updateCurrentVersion, configurationSettings, isHardhatProject, isTruffleProject, workspaceName } = props // eslint-disable-line
|
|
|
|
|
const { |
|
|
|
|
api, |
|
|
|
|
compileTabLogic, |
|
|
|
|
tooltip, |
|
|
|
|
modal, |
|
|
|
|
compiledFileName, |
|
|
|
|
updateCurrentVersion, |
|
|
|
|
configurationSettings, |
|
|
|
|
isHardhatProject, |
|
|
|
|
isTruffleProject, |
|
|
|
|
workspaceName, |
|
|
|
|
configFilePath, |
|
|
|
|
setConfigFilePath, |
|
|
|
|
} = props // eslint-disable-line
|
|
|
|
|
const [state, setState] = useState({ |
|
|
|
|
hideWarnings: false, |
|
|
|
|
autoCompile: false, |
|
|
|
|
configFilePath: "compiler_config.json", |
|
|
|
|
useFileConfiguration: false, |
|
|
|
|
matomoAutocompileOnce: true, |
|
|
|
|
optimize: false, |
|
|
|
@ -40,7 +53,8 @@ export const CompilerContainer = (props: CompilerContainerProps) => { |
|
|
|
|
compiledFileName: '', |
|
|
|
|
includeNightlies: false, |
|
|
|
|
language: 'Solidity', |
|
|
|
|
evmVersion: '' |
|
|
|
|
evmVersion: '', |
|
|
|
|
createFileOnce: true |
|
|
|
|
}) |
|
|
|
|
const [showFilePathInput, setShowFilePathInput] = useState<boolean>(false) |
|
|
|
|
const [toggleExpander, setToggleExpander] = useState<boolean>(false) |
|
|
|
@ -53,17 +67,27 @@ export const CompilerContainer = (props: CompilerContainerProps) => { |
|
|
|
|
const [compilerContainer, dispatch] = useReducer(compilerReducer, compilerInitialState) |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
api.setAppParameter('configFilePath', "/compiler_config.json") |
|
|
|
|
api.fileExists("/compiler_config.json").then((exists) => { |
|
|
|
|
if (!exists) createNewConfigFile() |
|
|
|
|
else { |
|
|
|
|
// what to do? discuss
|
|
|
|
|
if (workspaceName) { |
|
|
|
|
api.setAppParameter('configFilePath', defaultPath) |
|
|
|
|
if (state.useFileConfiguration) { |
|
|
|
|
api.fileExists(defaultPath).then((exists) => { |
|
|
|
|
if (!exists && state.useFileConfiguration) createNewConfigFile() |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
api.setAppParameter('configFilePath', "/compiler_config.json") |
|
|
|
|
setShowFilePathInput(false) |
|
|
|
|
setShowFilePathInput(false) |
|
|
|
|
} |
|
|
|
|
}, [workspaceName]) |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
if (state.useFileConfiguration) { |
|
|
|
|
api.fileExists(defaultPath).then((exists) => { |
|
|
|
|
if (!exists) createNewConfigFile() |
|
|
|
|
}) |
|
|
|
|
setToggleExpander(true) |
|
|
|
|
} |
|
|
|
|
}, [state.useFileConfiguration]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
const listener = (event) => { |
|
|
|
|
if (configFilePathInput.current !== event.target) { |
|
|
|
@ -106,8 +130,10 @@ export const CompilerContainer = (props: CompilerContainerProps) => { |
|
|
|
|
const hideWarnings = await api.getAppParameter('hideWarnings') as boolean || false |
|
|
|
|
const includeNightlies = await api.getAppParameter('includeNightlies') as boolean || false |
|
|
|
|
const useFileConfiguration = await api.getAppParameter('useFileConfiguration') as boolean || false |
|
|
|
|
let configFilePath = await api.getAppParameter('configFilePath') |
|
|
|
|
if (!configFilePath || configFilePath == '') configFilePath = "/compiler_config.json" |
|
|
|
|
let configFilePathSaved = await api.getAppParameter('configFilePath') |
|
|
|
|
if (!configFilePathSaved || configFilePathSaved == '') configFilePathSaved = defaultPath |
|
|
|
|
|
|
|
|
|
setConfigFilePath(configFilePathSaved) |
|
|
|
|
|
|
|
|
|
setState(prevState => { |
|
|
|
|
const params = api.getCompilerParameters() |
|
|
|
@ -122,7 +148,6 @@ export const CompilerContainer = (props: CompilerContainerProps) => { |
|
|
|
|
autoCompile: autocompile, |
|
|
|
|
includeNightlies: includeNightlies, |
|
|
|
|
useFileConfiguration: useFileConfiguration, |
|
|
|
|
configFilePath: configFilePath, |
|
|
|
|
optimize: optimize, |
|
|
|
|
runs: runs, |
|
|
|
|
evmVersion: (evmVersion !== null) && (evmVersion !== 'null') && (evmVersion !== undefined) && (evmVersion !== 'undefined') ? evmVersion : 'default', |
|
|
|
@ -181,7 +206,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
compileTabLogic.setUseFileConfiguration(state.useFileConfiguration) |
|
|
|
|
if (state.useFileConfiguration) compileTabLogic.setConfigFilePath(state.configFilePath) |
|
|
|
|
if (state.useFileConfiguration) compileTabLogic.setConfigFilePath(configFilePath) |
|
|
|
|
}, [state.useFileConfiguration]) |
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
@ -191,6 +216,16 @@ export const CompilerContainer = (props: CompilerContainerProps) => { |
|
|
|
|
}, [configurationSettings]) |
|
|
|
|
|
|
|
|
|
const toggleConfigType = () => { |
|
|
|
|
if (state.useFileConfiguration) |
|
|
|
|
if (state.createFileOnce) { |
|
|
|
|
api.fileExists(defaultPath).then((exists) => { |
|
|
|
|
if (!exists || state.useFileConfiguration ) createNewConfigFile() |
|
|
|
|
}) |
|
|
|
|
setState(prevState => { |
|
|
|
|
return { ...prevState, createFileOnce: false } |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
setState(prevState => { |
|
|
|
|
api.setAppParameter('useFileConfiguration', !state.useFileConfiguration) |
|
|
|
|
return { ...prevState, useFileConfiguration: !state.useFileConfiguration } |
|
|
|
@ -198,18 +233,17 @@ export const CompilerContainer = (props: CompilerContainerProps) => { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const openFile = async () => { |
|
|
|
|
api.open(state.configFilePath) |
|
|
|
|
api.open(configFilePath) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const createNewConfigFile = async () => { |
|
|
|
|
let filePath = configFilePathInput.current && configFilePathInput.current.value !== '' ? configFilePathInput.current.value : state.configFilePath |
|
|
|
|
let filePath = configFilePathInput.current && configFilePathInput.current.value !== '' ? configFilePathInput.current.value : configFilePath |
|
|
|
|
if (filePath === '') filePath = defaultPath |
|
|
|
|
if (!filePath.endsWith('.json')) filePath = filePath + '.json' |
|
|
|
|
|
|
|
|
|
await api.writeFile(filePath, configFileContent) |
|
|
|
|
api.setAppParameter('configFilePath', filePath) |
|
|
|
|
setState(prevState => { |
|
|
|
|
return { ...prevState, configFilePath: filePath } |
|
|
|
|
}) |
|
|
|
|
setConfigFilePath(filePath) |
|
|
|
|
compileTabLogic.setConfigFilePath(filePath) |
|
|
|
|
setShowFilePathInput(false) |
|
|
|
|
} |
|
|
|
@ -220,9 +254,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => { |
|
|
|
|
|
|
|
|
|
if (await api.fileExists(configFilePathInput.current.value)) { |
|
|
|
|
api.setAppParameter('configFilePath', configFilePathInput.current.value) |
|
|
|
|
setState(prevState => { |
|
|
|
|
return { ...prevState, configFilePath: configFilePathInput.current.value } |
|
|
|
|
}) |
|
|
|
|
setConfigFilePath(configFilePathInput.current.value) |
|
|
|
|
compileTabLogic.setConfigFilePath(configFilePathInput.current.value) |
|
|
|
|
|
|
|
|
|
setShowFilePathInput(false) |
|
|
|
@ -394,6 +426,9 @@ export const CompilerContainer = (props: CompilerContainerProps) => { |
|
|
|
|
compileIcon.current.classList.remove('remixui_spinningIcon') |
|
|
|
|
compileIcon.current.classList.remove('remixui_bouncingIcon') |
|
|
|
|
if (!state.autoCompile || (state.autoCompile && state.matomoAutocompileOnce)) { |
|
|
|
|
if (state.useFileConfiguration) |
|
|
|
|
_paq.push(['trackEvent', 'compiler', 'compiled_with_config_file']) |
|
|
|
|
|
|
|
|
|
_paq.push(['trackEvent', 'compiler', 'compiled_with_version', _retrieveVersion()]) |
|
|
|
|
if (state.autoCompile && state.matomoAutocompileOnce) { |
|
|
|
|
setState(prevState => { |
|
|
|
@ -750,36 +785,38 @@ export const CompilerContainer = (props: CompilerContainerProps) => { |
|
|
|
|
</div> |
|
|
|
|
<div className="d-flex pb-1 remixui_compilerConfig custom-control custom-radio"> |
|
|
|
|
<input className="custom-control-input" type="radio" name="configradio" value="file" onChange={toggleConfigType} checked={state.useFileConfiguration} id="scFileConfig" /> |
|
|
|
|
<label className="form-check-label custom-control-label" htmlFor="scFileConfig">Use configuration file</label> |
|
|
|
|
<label className="form-check-label custom-control-label" htmlFor="scFileConfig" data-id="scFileConfiguration">Use configuration file</label> |
|
|
|
|
</div> |
|
|
|
|
<div className={`pt-2 ml-4 ml-2 align-items-start justify-content-between d-flex`}> |
|
|
|
|
{ (!showFilePathInput && state.useFileConfiguration) && <span |
|
|
|
|
title="Click to open the config file." |
|
|
|
|
onClick={openFile} |
|
|
|
|
className="py-2 text-primary remixui_compilerConfigPath" |
|
|
|
|
>{state.configFilePath}</span> } |
|
|
|
|
{ (!showFilePathInput&& !state.useFileConfiguration) && <span className="py-2 text-secondary">{state.configFilePath}</span> } |
|
|
|
|
onClick={configFilePath === '' ? () => {} : openFile} |
|
|
|
|
className="py-2 remixui_compilerConfigPath" |
|
|
|
|
>{configFilePath === '' ? 'No file selected.' : configFilePath}</span> } |
|
|
|
|
{ (!showFilePathInput && !state.useFileConfiguration) && <span className="py-2 text-secondary">{configFilePath}</span> } |
|
|
|
|
<input |
|
|
|
|
ref={configFilePathInput} |
|
|
|
|
className={`py-0 my-0 form-control ${showFilePathInput ? "d-flex" : "d-none"}`} |
|
|
|
|
placeholder={"Enter the new path"} |
|
|
|
|
title="If the file you entered does not exist you will be able to create one in the next step." |
|
|
|
|
disabled={!state.useFileConfiguration} |
|
|
|
|
data-id="scConfigFilePathInput" |
|
|
|
|
onKeyPress={event => { |
|
|
|
|
if (event.key === 'Enter') { |
|
|
|
|
handleConfigPathChange() |
|
|
|
|
} |
|
|
|
|
}} |
|
|
|
|
/> |
|
|
|
|
{ !showFilePathInput && <button disabled={!state.useFileConfiguration} className="btn-secondary" onClick={() => {setShowFilePathInput(true)}}>Change</button> } |
|
|
|
|
{ !showFilePathInput && <button disabled={!state.useFileConfiguration} data-id="scConfigChangeFilePath" className="btn-secondary" onClick={() => {setShowFilePathInput(true)}}>Change</button> } |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
<div className="px-4"> |
|
|
|
|
<button id="compileBtn" data-id="compilerContainerCompileBtn" className="btn btn-primary btn-block d-block w-100 text-break remixui_disabled mb-1 mt-3" onClick={compile} disabled={disableCompileButton}> |
|
|
|
|
<button id="compileBtn" data-id="compilerContainerCompileBtn" className="btn btn-primary btn-block d-block w-100 text-break remixui_disabled mb-1 mt-3" onClick={compile} disabled={(configFilePath === '' && state.useFileConfiguration) || disableCompileButton}> |
|
|
|
|
<OverlayTrigger overlay={ |
|
|
|
|
<Tooltip id="overlay-tooltip-compile"> |
|
|
|
|
<div className="text-left"> |
|
|
|
|
<div><b>Ctrl+S</b> for compiling</div> |
|
|
|
|
{ !(configFilePath === '' && state.useFileConfiguration) && <div><b>Ctrl+S</b> for compiling</div> } |
|
|
|
|
{ (configFilePath === '' && state.useFileConfiguration) && <div> No config file selected</div> } |
|
|
|
|
</div> |
|
|
|
|
</Tooltip> |
|
|
|
|
}> |
|
|
|
@ -790,11 +827,12 @@ export const CompilerContainer = (props: CompilerContainerProps) => { |
|
|
|
|
</OverlayTrigger> |
|
|
|
|
</button> |
|
|
|
|
<div className='d-flex align-items-center'>
|
|
|
|
|
<button id="compileAndRunBtn" data-id="compilerContainerCompileAndRunBtn" className="btn btn-secondary btn-block d-block w-100 text-break remixui_solidityCompileAndRunButton d-inline-block remixui_disabled mb-1 mt-3" onClick={compileAndRun} disabled={disableCompileButton}> |
|
|
|
|
<button id="compileAndRunBtn" data-id="compilerContainerCompileAndRunBtn" className="btn btn-secondary btn-block d-block w-100 text-break remixui_solidityCompileAndRunButton d-inline-block remixui_disabled mb-1 mt-3" onClick={compileAndRun} disabled={(configFilePath === '' && state.useFileConfiguration) || disableCompileButton}> |
|
|
|
|
<OverlayTrigger overlay={ |
|
|
|
|
<Tooltip id="overlay-tooltip-compile-run"> |
|
|
|
|
<div className="text-left"> |
|
|
|
|
<div><b>Ctrl+Shift+S</b> for compiling and script execution</div> |
|
|
|
|
{ !(configFilePath === '' && state.useFileConfiguration) && <div><b>Ctrl+Shift+S</b> for compiling and script execution</div> } |
|
|
|
|
{ (configFilePath === '' && state.useFileConfiguration) && <div> No config file selected</div> } |
|
|
|
|
</div> |
|
|
|
|
</Tooltip> |
|
|
|
|
}> |
|
|
|
@ -806,18 +844,18 @@ export const CompilerContainer = (props: CompilerContainerProps) => { |
|
|
|
|
<OverlayTrigger overlay={ |
|
|
|
|
<Tooltip id="overlay-tooltip-compile-run-doc"> |
|
|
|
|
<div className="text-left p-2"> |
|
|
|
|
<div>Choose the script to execute right after compilation by adding the `dev-run-script` natspec tag, as in:</div> |
|
|
|
|
<pre> |
|
|
|
|
<code> |
|
|
|
|
/**<br /> |
|
|
|
|
* @title ContractName<br /> |
|
|
|
|
* @dev ContractDescription<br /> |
|
|
|
|
* @custom:dev-run-script file_path<br /> |
|
|
|
|
*/<br /> |
|
|
|
|
contract ContractName {'{}'}<br /> |
|
|
|
|
</code> |
|
|
|
|
</pre> |
|
|
|
|
Click to know more |
|
|
|
|
<div>Choose the script to execute right after compilation by adding the `dev-run-script` natspec tag, as in:</div> |
|
|
|
|
<pre> |
|
|
|
|
<code> |
|
|
|
|
/**<br /> |
|
|
|
|
* @title ContractName<br /> |
|
|
|
|
* @dev ContractDescription<br /> |
|
|
|
|
* @custom:dev-run-script file_path<br /> |
|
|
|
|
*/<br /> |
|
|
|
|
contract ContractName {'{}'}<br /> |
|
|
|
|
</code> |
|
|
|
|
</pre> |
|
|
|
|
Click to know more |
|
|
|
|
</div> |
|
|
|
|
</Tooltip> |
|
|
|
|
}> |
|
|
|
|