Merge branch 'master' into modal-check

pull/5370/head
bunsenstraat 2 years ago committed by GitHub
commit fca9b025f6
  1. 2
      apps/remix-ide-e2e/.eslintrc
  2. 1
      apps/remix-ide-e2e/src/helpers/hardhat_compilation.ts
  3. 113556
      apps/remix-ide-e2e/src/helpers/hardhat_compilation_8a7ab689ec618720f53ce867a3031c03.json
  4. 20
      apps/remix-ide-e2e/src/tests/remixd.test.ts
  5. 3
      apps/remix-ide-e2e/tsconfig.e2e.json
  6. 3
      apps/remix-ide-e2e/tsconfig.json
  7. 0
      apps/remix-ide/contracts/artifacts/build-info/.gitgnore
  8. 1
      apps/remix-ide/contracts/hardhat.config.js
  9. 43
      apps/remix-ide/src/app/editor/editor.js
  10. 3
      apps/remix-ide/src/app/tabs/compile-tab.js
  11. 2
      apps/remix-ide/src/app/tabs/web3-provider.js
  12. 2
      apps/remix-ide/src/blockchain/execution-context.js
  13. 3
      apps/remix-ide/src/blockchain/helper.ts
  14. 3
      apps/remix-ide/src/remixAppManager.js
  15. 5
      libs/remix-core-plugin/src/lib/compiler-artefacts.ts
  16. 3
      libs/remix-debug/src/init.ts
  17. 1
      libs/remix-ui/app/src/lib/remix-app/components/dragbar/dragbar.tsx
  18. 1
      libs/remix-ui/panel/src/lib/dragbar/dragbar.tsx
  19. 17
      libs/remix-ui/run-tab/src/lib/actions/events.ts
  20. 10
      libs/remix-ui/run-tab/src/lib/actions/payload.ts
  21. 21
      libs/remix-ui/run-tab/src/lib/components/contractDropdownUI.tsx
  22. 1
      libs/remix-ui/run-tab/src/lib/constants/index.ts
  23. 16
      libs/remix-ui/run-tab/src/lib/reducers/runTab.ts
  24. 1
      libs/remix-ui/run-tab/src/lib/types/index.ts
  25. 10
      libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx
  26. 55
      libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx
  27. 28
      libs/remixd/src/services/hardhatClient.ts
  28. 12
      libs/remixd/src/services/remixdClient.ts

@ -12,5 +12,5 @@
} }
], ],
"extends": ["../../.eslintrc"], "extends": ["../../.eslintrc"],
"ignorePatterns": ["!**/*"] "ignorePatterns": ["!**/*", "hardhat_compilation.ts"]
} }

File diff suppressed because one or more lines are too long

@ -1,6 +1,8 @@
'use strict' 'use strict'
import { NightwatchBrowser } from 'nightwatch' import { NightwatchBrowser } from 'nightwatch'
import { writeFileSync } from 'fs'
import init from '../helpers/init' import init from '../helpers/init'
import * as hardhatCompilation from '../helpers/hardhat_compilation_8a7ab689ec618720f53ce867a3031c03.json'
const assetsTestContract = `import "./contract.sol"; const assetsTestContract = `import "./contract.sol";
contract Assets { contract Assets {
@ -112,8 +114,22 @@ module.exports = {
browser browser
.clickLaunchIcon('pluginManager') .clickLaunchIcon('pluginManager')
.scrollAndClick('#pluginManager *[data-id="pluginManagerComponentDeactivateButtonremixd"]') .scrollAndClick('#pluginManager *[data-id="pluginManagerComponentDeactivateButtonremixd"]')
.end() },
}
'Should listen on compilation result from hardhat #group5': function (browser: NightwatchBrowser) {
browser.perform((done) => {
console.log('working directory', process.cwd())
writeFileSync('./apps/remix-ide/contracts/artifacts/build-info/c7062fdd360381a85af23eeef31c98f8.json', JSON.stringify(hardhatCompilation))
done()
})
.expect.element('*[data-id="terminalJournal"]').text.to.contain('received compilation result from hardhat').before(60000)
browser.clickLaunchIcon('udapp')
.assert.textContains('*[data-id="udappCompiledBy"]', 'Compiled by hardhat')
.selectContract('Lock')
.createContract('1')
.expect.element('*[data-id="terminalJournal"]').text.to.contain('Unlock time should be in the future').before(60000)
}
} }
function startRemixd (browser: NightwatchBrowser) { function startRemixd (browser: NightwatchBrowser) {

@ -3,7 +3,8 @@
"compilerOptions": { "compilerOptions": {
"sourceMap": false, "sourceMap": false,
"outDir": "../../dist", "outDir": "../../dist",
"allowJs": true "allowJs": true,
"resolveJsonModule": true
}, },
"include": ["**/*.ts", "**/*.js"] "include": ["**/*.ts", "**/*.js"]
} }

@ -2,7 +2,8 @@
"extends": "../../tsconfig.base.json", "extends": "../../tsconfig.base.json",
"compilerOptions": { "compilerOptions": {
"types": ["node", "nightwatch"], "types": ["node", "nightwatch"],
"esModuleInterop": true "esModuleInterop": true,
"resolveJsonModule": true
}, },
"include": ["**/*.ts", "**/*.js"] "include": ["**/*.ts", "**/*.js"]
} }

@ -0,0 +1 @@
// simulate a hardhat project

@ -5,6 +5,7 @@ import { EditorUI } from '@remix-ui/editor' // eslint-disable-line
import { Plugin } from '@remixproject/engine' import { Plugin } from '@remixproject/engine'
import * as packageJson from '../../../../../package.json' import * as packageJson from '../../../../../package.json'
import { PluginViewWrapper } from '@remix-ui/helper' import { PluginViewWrapper } from '@remix-ui/helper'
import { exists } from 'fs'
const EventManager = require('../../lib/events') const EventManager = require('../../lib/events')
@ -74,30 +75,15 @@ class Editor extends Plugin {
updateComponent(state) { updateComponent(state) {
return <EditorUI return <EditorUI
editorAPI={state.api} editorAPI={state.api}
themeType={state.currentThemeType} themeType={state.currentThemeType}
currentFile={state.currentFile} currentFile={state.currentFile}
events={state.events} events={state.events}
plugin={state.plugin} plugin={state.plugin}
/> />
} }
render () { render () {
/* if (this.el) return this.el
this.el = document.createElement('div')
this.el.setAttribute('id', 'editorView')
this.el.currentContent = () => this.currentContent() // used by e2e test
this.el.setCurrentContent = (value) => {
if (this.sessions[this.currentFile]) {
this.sessions[this.currentFile].setValue(value)
this._onChange(this.currentFile)
}
}
this.el.gotoLine = (line, column) => this.gotoLine(line, column || 0)
this.el.getCursorPosition = () => this.getCursorPosition() */
return <div ref={(element)=>{ return <div ref={(element)=>{
this.ref = element this.ref = element
this.ref.currentContent = () => this.currentContent() // used by e2e test this.ref.currentContent = () => this.currentContent() // used by e2e test
@ -113,7 +99,7 @@ class Editor extends Plugin {
this.ref.clearDecorationsByPlugin = (filePath, plugin, typeOfDecoration) => this.clearDecorationsByPlugin(filePath, plugin, typeOfDecoration) this.ref.clearDecorationsByPlugin = (filePath, plugin, typeOfDecoration) => this.clearDecorationsByPlugin(filePath, plugin, typeOfDecoration)
this.ref.keepDecorationsFor = (name, typeOfDecoration) => this.keepDecorationsFor(name, typeOfDecoration) this.ref.keepDecorationsFor = (name, typeOfDecoration) => this.keepDecorationsFor(name, typeOfDecoration)
}} id='editorView'> }} id='editorView'>
<PluginViewWrapper plugin={this} /> <PluginViewWrapper plugin={this} />
</div> </div>
} }
@ -229,15 +215,20 @@ class Editor extends Plugin {
try { try {
// we can't use the fileManager plugin call directly // we can't use the fileManager plugin call directly
// because it's itself called in a plugin context, and that causes a timeout in the plugin stack // because it's itself called in a plugin context, and that causes a timeout in the plugin stack
const contentDep = await readFile(pathDep) const pathExists = await exists(pathDep)
if (contentDep !== null) { let contentDep = ''
this.emit('addModel', contentDep, 'typescript', pathDep, false) if (pathExists) {
contentDep = await readFile(pathDep)
if (contentDep !== '') {
this.emit('addModel', contentDep, 'typescript', pathDep, false)
}
} else {
console.log("The file ", pathDep, " can't be found.")
} }
} catch (e) { } catch (e) {
console.log(e) console.log(e)
} }
} }
} }
} }

@ -8,6 +8,7 @@ import { QueryParams } from '@remix-project/remix-lib'
// import { ICompilerApi } from '@remix-project/remix-lib-ts' // import { ICompilerApi } from '@remix-project/remix-lib-ts'
import * as packageJson from '../../../../../package.json' import * as packageJson from '../../../../../package.json'
import { compilerConfigChangedToastMsg, compileToastMsg } from '@remix-ui/helper' import { compilerConfigChangedToastMsg, compileToastMsg } from '@remix-ui/helper'
import { isNative } from '../../remixAppManager'
const profile = { const profile = {
name: 'solidity', name: 'solidity',
@ -104,7 +105,7 @@ class CompileTab extends CompilerApiMixin(ViewPlugin) { // implements ICompilerA
} }
compile (fileName) { compile (fileName) {
this.call('notification', 'toast', compileToastMsg(this.currentRequest.from, fileName)) if (!isNative(this.currentRequest.from)) this.call('notification', 'toast', compileToastMsg(this.currentRequest.from, fileName))
super.compile(fileName) super.compile(fileName)
} }

@ -30,7 +30,7 @@ export class Web3ProviderModule extends Plugin {
// see https://github.com/ethereum/web3.js/pull/1018/files#diff-d25786686c1053b786cc2626dc6e048675050593c0ebaafbf0814e1996f22022R129 // see https://github.com/ethereum/web3.js/pull/1018/files#diff-d25786686c1053b786cc2626dc6e048675050593c0ebaafbf0814e1996f22022R129
provider[provider.sendAsync ? 'sendAsync' : 'send'](payload, async (error, message) => { provider[provider.sendAsync ? 'sendAsync' : 'send'](payload, async (error, message) => {
if (error) { if (error) {
const errorData = error.data ? error.data : error.message const errorData = error.data ? error.data : error.message ? error.message : error
// See: https://github.com/ethers-io/ethers.js/issues/901 // See: https://github.com/ethers-io/ethers.js/issues/901
if (!(typeof errorData === 'string' && errorData.includes("unknown method eth_chainId"))) this.call('terminal', 'log', error.data ? error.data : error.message) if (!(typeof errorData === 'string' && errorData.includes("unknown method eth_chainId"))) this.call('terminal', 'log', error.data ? error.data : error.message)
return reject(errorData) return reject(errorData)

@ -93,6 +93,7 @@ export class ExecutionContext {
else if (id === 4) name = 'Rinkeby' else if (id === 4) name = 'Rinkeby'
else if (id === 5) name = 'Goerli' else if (id === 5) name = 'Goerli'
else if (id === 42) name = 'Kovan' else if (id === 42) name = 'Kovan'
else if (id === 11155111) name = 'Sepolia'
else name = 'Custom' else name = 'Custom'
if (id === '1') { if (id === '1') {
@ -250,6 +251,7 @@ export class ExecutionContext {
Main: 'https://www.etherscan.io/tx/', Main: 'https://www.etherscan.io/tx/',
Rinkeby: 'https://rinkeby.etherscan.io/tx/', Rinkeby: 'https://rinkeby.etherscan.io/tx/',
Ropsten: 'https://ropsten.etherscan.io/tx/', Ropsten: 'https://ropsten.etherscan.io/tx/',
Sepolia: 'https://sepolia.etherscan.io/tx/',
Kovan: 'https://kovan.etherscan.io/tx/', Kovan: 'https://kovan.etherscan.io/tx/',
Goerli: 'https://goerli.etherscan.io/tx/' Goerli: 'https://goerli.etherscan.io/tx/'
} }

@ -3,7 +3,8 @@ const transactionDetailsLinks = {
Rinkeby: 'https://rinkeby.etherscan.io/tx/', Rinkeby: 'https://rinkeby.etherscan.io/tx/',
Ropsten: 'https://ropsten.etherscan.io/tx/', Ropsten: 'https://ropsten.etherscan.io/tx/',
Kovan: 'https://kovan.etherscan.io/tx/', Kovan: 'https://kovan.etherscan.io/tx/',
Goerli: 'https://goerli.etherscan.io/tx/' Goerli: 'https://goerli.etherscan.io/tx/',
Sepolia: 'https://sepolia.etherscan.io/tx/'
} }
export function etherScanLink (network: string, hash: string): string { export function etherScanLink (network: string, hash: string): string {

@ -25,7 +25,8 @@ const sensitiveCalls = {
export function isNative(name) { export function isNative(name) {
// nativePlugin allows to bypass the permission request // nativePlugin allows to bypass the permission request
const nativePlugins = ['vyper', 'workshops', 'debugger', 'remixd', 'menuicons', 'solidity', 'solidity-logic', 'solidityStaticAnalysis', 'solidityUnitTesting', const nativePlugins = ['vyper', 'workshops', 'debugger', 'remixd', 'menuicons', 'solidity', 'solidity-logic', 'solidityStaticAnalysis', 'solidityUnitTesting',
'layout', 'notification', 'hardhat-provider', 'ganache-provider', 'foundry-provider', 'basic-http-provider', 'injected-optimism-provider', 'injected-arbitrum-one-provider'] 'layout', 'notification', 'hardhat-provider', 'ganache-provider', 'foundry-provider', 'basic-http-provider', 'injected-optimism-provider',
'tabs', 'injected-arbitrum-one-provider']
return nativePlugins.includes(name) || requiredModules.includes(name) return nativePlugins.includes(name) || requiredModules.includes(name)
} }

@ -58,6 +58,11 @@ export class CompilerArtefacts extends Plugin {
this.compilersArtefacts.__last = new CompilerAbstract(languageVersion, data, source) this.compilersArtefacts.__last = new CompilerAbstract(languageVersion, data, source)
saveCompilationPerFileResult(file, source, languageVersion, data) saveCompilationPerFileResult(file, source, languageVersion, data)
}) })
this.on('hardhat', 'compilationFinished', (file, source, languageVersion, data) => {
this.compilersArtefacts.__last = new CompilerAbstract(languageVersion, data, source)
saveCompilationPerFileResult(file, source, languageVersion, data)
})
} }
/** /**

@ -22,7 +22,8 @@ export function web3DebugNode (network) {
Main: 'https://rpc.archivenode.io/e50zmkroshle2e2e50zm0044i7ao04ym', Main: 'https://rpc.archivenode.io/e50zmkroshle2e2e50zm0044i7ao04ym',
Rinkeby: 'https://remix-rinkeby.ethdevops.io', Rinkeby: 'https://remix-rinkeby.ethdevops.io',
Ropsten: 'https://remix-ropsten.ethdevops.io', Ropsten: 'https://remix-ropsten.ethdevops.io',
Goerli: 'https://remix-goerli.ethdevops.io' Goerli: 'https://remix-goerli.ethdevops.io',
Sepolia: 'https://remix-sepolia.ethdevops.io'
} }
if (web3DebugNodes[network]) { if (web3DebugNodes[network]) {
return loadWeb3(web3DebugNodes[network]) return loadWeb3(web3DebugNodes[network])

@ -45,6 +45,7 @@ const DragBar = (props: IRemixDragBarUi) => {
}, [props.resetTrigger]) }, [props.resetTrigger])
const handleResize = () => { const handleResize = () => {
if (!props.refObject.current) return
setOffSet(props.refObject.current.offsetLeft) setOffSet(props.refObject.current.offsetLeft)
setDragBarPosX(props.refObject.current.offsetLeft + props.refObject.current.offsetWidth) setDragBarPosX(props.refObject.current.offsetLeft + props.refObject.current.offsetWidth)
} }

@ -23,6 +23,7 @@ const DragBar = (props: IRemixDragBarUi) => {
props.setHideStatus(false) props.setHideStatus(false)
} }
const handleResize = () => { const handleResize = () => {
if (!props.refObject.current) return
setDragBarPosY(window.innerHeight - props.refObject.current.offsetHeight) setDragBarPosY(window.innerHeight - props.refObject.current.offsetHeight)
} }

@ -2,7 +2,7 @@ import { envChangeNotification } from "@remix-ui/helper"
import { RunTab } from "../types/run-tab" import { RunTab } from "../types/run-tab"
import { setExecutionContext, setFinalContext, updateAccountBalances } from "./account" import { setExecutionContext, setFinalContext, updateAccountBalances } from "./account"
import { addExternalProvider, addInstance, removeExternalProvider, setNetworkNameFromProvider } from "./actions" import { addExternalProvider, addInstance, removeExternalProvider, setNetworkNameFromProvider } from "./actions"
import { addDeployOption, clearAllInstances, clearRecorderCount, fetchContractListSuccess, resetUdapp, setCurrentContract, setCurrentFile, setLoadType, setProxyEnvAddress, setRecorderCount, setSendValue } from "./payload" import { addDeployOption, clearAllInstances, clearRecorderCount, fetchContractListSuccess, resetUdapp, setCompilationSource, setCurrentContract, setCurrentFile, setLoadType, setProxyEnvAddress, setRecorderCount, setSendValue } from "./payload"
import { CompilerAbstract } from '@remix-project/remix-solidity' import { CompilerAbstract } from '@remix-project/remix-solidity'
import * as ethJSUtil from 'ethereumjs-util' import * as ethJSUtil from 'ethereumjs-util'
import Web3 from 'web3' import Web3 from 'web3'
@ -41,15 +41,17 @@ export const setupEvents = (plugin: RunTab, dispatch: React.Dispatch<any>) => {
plugin.blockchain.event.register('removeProvider', name => removeExternalProvider(dispatch, name)) plugin.blockchain.event.register('removeProvider', name => removeExternalProvider(dispatch, name))
plugin.on('solidity', 'compilationFinished', (file, source, languageVersion, data, input, version) => broadcastCompilationResult(plugin, dispatch, file, source, languageVersion, data, input)) plugin.on('solidity', 'compilationFinished', (file, source, languageVersion, data, input, version) => broadcastCompilationResult('remix', plugin, dispatch, file, source, languageVersion, data, input))
plugin.on('vyper', 'compilationFinished', (file, source, languageVersion, data) => broadcastCompilationResult(plugin, dispatch, file, source, languageVersion, data)) plugin.on('vyper', 'compilationFinished', (file, source, languageVersion, data) => broadcastCompilationResult('vyper', plugin, dispatch, file, source, languageVersion, data))
plugin.on('lexon', 'compilationFinished', (file, source, languageVersion, data) => broadcastCompilationResult(plugin, dispatch, file, source, languageVersion, data)) plugin.on('lexon', 'compilationFinished', (file, source, languageVersion, data) => broadcastCompilationResult('lexon', plugin, dispatch, file, source, languageVersion, data))
plugin.on('yulp', 'compilationFinished', (file, source, languageVersion, data) => broadcastCompilationResult(plugin, dispatch, file, source, languageVersion, data)) plugin.on('yulp', 'compilationFinished', (file, source, languageVersion, data) => broadcastCompilationResult('yulp', plugin, dispatch, file, source, languageVersion, data))
plugin.on('nahmii-compiler', 'compilationFinished', (file, source, languageVersion, data) => broadcastCompilationResult(plugin, dispatch, file, source, languageVersion, data)) plugin.on('nahmii-compiler', 'compilationFinished', (file, source, languageVersion, data) => broadcastCompilationResult('nahmii', plugin, dispatch, file, source, languageVersion, data))
plugin.on('hardhat', 'compilationFinished', (file, source, languageVersion, data) => broadcastCompilationResult('hardhat', plugin, dispatch, file, source, languageVersion, data))
plugin.on('udapp', 'setEnvironmentModeReducer', (env: { context: string, fork: string }, from: string) => { plugin.on('udapp', 'setEnvironmentModeReducer', (env: { context: string, fork: string }, from: string) => {
plugin.call('notification', 'toast', envChangeNotification(env, from)) plugin.call('notification', 'toast', envChangeNotification(env, from))
@ -92,7 +94,7 @@ export const setupEvents = (plugin: RunTab, dispatch: React.Dispatch<any>) => {
}) })
} }
const broadcastCompilationResult = async (plugin: RunTab, dispatch: React.Dispatch<any>, file, source, languageVersion, data, input?) => { const broadcastCompilationResult = async (compilerName: string, plugin: RunTab, dispatch: React.Dispatch<any>, file, source, languageVersion, data, input?) => {
// TODO check whether the tab is configured // TODO check whether the tab is configured
const compiler = new CompilerAbstract(languageVersion, data, source, input) const compiler = new CompilerAbstract(languageVersion, data, source, input)
plugin.compilersArtefacts[languageVersion] = compiler plugin.compilersArtefacts[languageVersion] = compiler
@ -119,6 +121,7 @@ const broadcastCompilationResult = async (plugin: RunTab, dispatch: React.Dispat
} }
dispatch(fetchContractListSuccess({ [file]: contracts })) dispatch(fetchContractListSuccess({ [file]: contracts }))
dispatch(setCurrentFile(file)) dispatch(setCurrentFile(file))
dispatch(setCompilationSource(compilerName))
// TODO: set current contract // TODO: set current contract
} }

@ -1,6 +1,6 @@
import { ContractList } from '../reducers/runTab' import { ContractList } from '../reducers/runTab'
import { ContractData } from '@remix-project/core-plugin' import { ContractData } from '@remix-project/core-plugin'
import { ADD_DEPLOY_OPTION, ADD_INSTANCE, ADD_PROVIDER, CLEAR_INSTANCES, CLEAR_RECORDER_COUNT, DISPLAY_NOTIFICATION, DISPLAY_POPUP_MESSAGE, FETCH_ACCOUNTS_LIST_FAILED, FETCH_ACCOUNTS_LIST_REQUEST, FETCH_ACCOUNTS_LIST_SUCCESS, FETCH_CONTRACT_LIST_FAILED, FETCH_CONTRACT_LIST_REQUEST, FETCH_CONTRACT_LIST_SUCCESS, HIDE_NOTIFICATION, HIDE_POPUP_MESSAGE, REMOVE_DEPLOY_OPTION, REMOVE_INSTANCE, REMOVE_PROVIDER, RESET_STATE, SET_BASE_FEE_PER_GAS, SET_CONFIRM_SETTINGS, SET_CURRENT_CONTRACT, SET_CURRENT_FILE, SET_DECODED_RESPONSE, SET_DEPLOY_OPTIONS, SET_EXECUTION_ENVIRONMENT, SET_EXTERNAL_WEB3_ENDPOINT, SET_GAS_LIMIT, SET_GAS_PRICE, SET_GAS_PRICE_STATUS, SET_IPFS_CHECKED_STATE, SET_LOAD_TYPE, SET_MATCH_PASSPHRASE, SET_MAX_FEE, SET_MAX_PRIORITY_FEE, SET_NETWORK_NAME, SET_PASSPHRASE, SET_PATH_TO_SCENARIO, SET_PERSONAL_MODE, SET_PROXY_ENV_ADDRESS, SET_RECORDER_COUNT, SET_SELECTED_ACCOUNT, SET_SEND_UNIT, SET_SEND_VALUE } from '../constants' import { ADD_DEPLOY_OPTION, ADD_INSTANCE, ADD_PROVIDER, CLEAR_INSTANCES, CLEAR_RECORDER_COUNT, DISPLAY_NOTIFICATION, DISPLAY_POPUP_MESSAGE, FETCH_ACCOUNTS_LIST_FAILED, FETCH_ACCOUNTS_LIST_REQUEST, FETCH_ACCOUNTS_LIST_SUCCESS, FETCH_CONTRACT_LIST_FAILED, FETCH_CONTRACT_LIST_REQUEST, FETCH_CONTRACT_LIST_SUCCESS, HIDE_NOTIFICATION, HIDE_POPUP_MESSAGE, REMOVE_DEPLOY_OPTION, REMOVE_INSTANCE, REMOVE_PROVIDER, RESET_STATE, SET_BASE_FEE_PER_GAS, SET_CONFIRM_SETTINGS, SET_CURRENT_CONTRACT, SET_CURRENT_FILE, SET_COMPILATION_SOURCE, SET_DECODED_RESPONSE, SET_DEPLOY_OPTIONS, SET_EXECUTION_ENVIRONMENT, SET_EXTERNAL_WEB3_ENDPOINT, SET_GAS_LIMIT, SET_GAS_PRICE, SET_GAS_PRICE_STATUS, SET_IPFS_CHECKED_STATE, SET_LOAD_TYPE, SET_MATCH_PASSPHRASE, SET_MAX_FEE, SET_MAX_PRIORITY_FEE, SET_NETWORK_NAME, SET_PASSPHRASE, SET_PATH_TO_SCENARIO, SET_PERSONAL_MODE, SET_PROXY_ENV_ADDRESS, SET_RECORDER_COUNT, SET_SELECTED_ACCOUNT, SET_SEND_UNIT, SET_SEND_VALUE } from '../constants'
import { DeployMode, DeployOptions } from '../types' import { DeployMode, DeployOptions } from '../types'
export const fetchAccountsListRequest = () => { export const fetchAccountsListRequest = () => {
@ -167,6 +167,14 @@ export const setCurrentFile = (file: string) => {
payload: file payload: file
} }
} }
export const setCompilationSource = (source: string) => {
return {
type: SET_COMPILATION_SOURCE,
payload: source
}
}
export const setIpfsCheckedState = (state: boolean) => { export const setIpfsCheckedState = (state: boolean) => {
return { return {
type: SET_IPFS_CHECKED_STATE, type: SET_IPFS_CHECKED_STATE,

@ -23,13 +23,16 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
title: 'Please compile *.sol file to deploy or access a contract', title: 'Please compile *.sol file to deploy or access a contract',
disabled: true disabled: true
}) })
const [compFails, setCompFails] = useState<'none' | 'block'>('none')
const [loadedContractData, setLoadedContractData] = useState<ContractData>(null) const [loadedContractData, setLoadedContractData] = useState<ContractData>(null)
const [constructorInterface, setConstructorInterface] = useState<FuncABI>(null) const [constructorInterface, setConstructorInterface] = useState<FuncABI>(null)
const [constructorInputs, setConstructorInputs] = useState(null) const [constructorInputs, setConstructorInputs] = useState(null)
const contractsRef = useRef<HTMLSelectElement>(null) const contractsRef = useRef<HTMLSelectElement>(null)
const atAddressValue = useRef<HTMLInputElement>(null) const atAddressValue = useRef<HTMLInputElement>(null)
const { contractList, loadType, currentFile, currentContract, compilationCount, deployOptions, proxyKey } = props.contracts const { contractList, loadType, currentFile, compilationSource, currentContract, compilationCount, deployOptions, proxyKey } = props.contracts
useEffect(() => {
enableContractNames(Object.keys(props.contracts.contractList).length > 0)
}, [Object.keys(props.contracts.contractList).length])
useEffect(() => { useEffect(() => {
enableAtAddress(false) enableAtAddress(false)
@ -72,13 +75,6 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
}) })
if (!currentContract) enableAtAddress(false) if (!currentContract) enableAtAddress(false)
} }
if (currentFile) {
enableContractNames(true)
setCompFails('none')
} else {
enableContractNames(false)
setCompFails('block')
}
initSelectedContract() initSelectedContract()
}, [loadType, currentFile, compilationCount]) }, [loadType, currentFile, compilationCount])
@ -231,9 +227,12 @@ export function ContractDropdownUI (props: ContractDropdownProps) {
return ( return (
<div className="udapp_container" data-id="contractDropdownContainer"> <div className="udapp_container" data-id="contractDropdownContainer">
<label className="udapp_settingsLabel">Contract</label> <div className='d-flex justify-content-between'>
<label className="udapp_settingsLabel">Contract</label>
{ Object.keys(props.contracts.contractList).length > 0 && compilationSource !== '' && <label data-id="udappCompiledBy">Compiled by {compilationSource} </label> }
</div>
<div className="udapp_subcontainer"> <div className="udapp_subcontainer">
<select ref={contractsRef} value={currentContract} onChange={handleContractChange} className="udapp_contractNames custom-select" disabled={contractOptions.disabled} title={contractOptions.title} style={{ display: loadType === 'abi' && !isContractFile(currentFile) ? 'none' : 'block' }}> <select ref={contractsRef} value={currentContract} onChange={handleContractChange} className="udapp_contractNames custom-select" disabled={contractOptions.disabled} title={contractOptions.title} style={{ display: loadType === 'abi' && !isContractFile(currentFile) ? 'none' : 'block' }}>
{ (contractList[currentFile] || []).map((contract, index) => { { (contractList[currentFile] || []).map((contract, index) => {
return <option key={index} value={contract.alias}>{contract.alias} - {contract.file}</option> return <option key={index} value={contract.alias}>{contract.alias} - {contract.file}</option>
}) } }) }

@ -25,6 +25,7 @@ export const FETCH_CONTRACT_LIST_SUCCESS = 'FETCH_CONTRACT_LIST_SUCCESS'
export const FETCH_CONTRACT_LIST_FAILED = 'FETCH_CONTRACT_LIST_FAILED' export const FETCH_CONTRACT_LIST_FAILED = 'FETCH_CONTRACT_LIST_FAILED'
export const SET_LOAD_TYPE = 'SET_LOAD_TYPE' export const SET_LOAD_TYPE = 'SET_LOAD_TYPE'
export const SET_CURRENT_FILE = 'SET_CURRENT_FILE' export const SET_CURRENT_FILE = 'SET_CURRENT_FILE'
export const SET_COMPILATION_SOURCE = 'SET_COMPILATION_SOURCE'
export const SET_IPFS_CHECKED_STATE = 'SET_IPFS_CHECKED_STATE' export const SET_IPFS_CHECKED_STATE = 'SET_IPFS_CHECKED_STATE'
export const SET_GAS_PRICE_STATUS = 'SET_GAS_PRICE_STATUS' export const SET_GAS_PRICE_STATUS = 'SET_GAS_PRICE_STATUS'
export const SET_CONFIRM_SETTINGS = 'SET_CONFIRM_SETTINGS' export const SET_CONFIRM_SETTINGS = 'SET_CONFIRM_SETTINGS'

@ -1,7 +1,7 @@
import { CompilerAbstract } from '@remix-project/remix-solidity-ts' import { CompilerAbstract } from '@remix-project/remix-solidity-ts'
import { ContractData } from '@remix-project/core-plugin' import { ContractData } from '@remix-project/core-plugin'
import { DeployOptions } from '../types' import { DeployOptions } from '../types'
import { ADD_INSTANCE, ADD_PROVIDER, CLEAR_INSTANCES, CLEAR_RECORDER_COUNT, DISPLAY_NOTIFICATION, DISPLAY_POPUP_MESSAGE, FETCH_ACCOUNTS_LIST_FAILED, FETCH_ACCOUNTS_LIST_REQUEST, FETCH_ACCOUNTS_LIST_SUCCESS, FETCH_CONTRACT_LIST_FAILED, FETCH_CONTRACT_LIST_REQUEST, FETCH_CONTRACT_LIST_SUCCESS, FETCH_PROVIDER_LIST_FAILED, FETCH_PROVIDER_LIST_REQUEST, FETCH_PROVIDER_LIST_SUCCESS, HIDE_NOTIFICATION, HIDE_POPUP_MESSAGE, REMOVE_INSTANCE, REMOVE_PROVIDER, RESET_STATE, SET_BASE_FEE_PER_GAS, SET_CONFIRM_SETTINGS, SET_CURRENT_CONTRACT, SET_CURRENT_FILE, SET_DECODED_RESPONSE, SET_DEPLOY_OPTIONS, SET_EXECUTION_ENVIRONMENT, SET_EXTERNAL_WEB3_ENDPOINT, SET_GAS_LIMIT, SET_GAS_PRICE, SET_GAS_PRICE_STATUS, SET_IPFS_CHECKED_STATE, SET_LOAD_TYPE, SET_MATCH_PASSPHRASE, SET_MAX_FEE, SET_MAX_PRIORITY_FEE, SET_NETWORK_NAME, SET_PASSPHRASE, SET_PATH_TO_SCENARIO, SET_PERSONAL_MODE, SET_RECORDER_COUNT, SET_SELECTED_ACCOUNT, SET_SEND_UNIT, SET_SEND_VALUE, SET_PROXY_ENV_ADDRESS, ADD_DEPLOY_OPTION, REMOVE_DEPLOY_OPTION } from '../constants' import { ADD_INSTANCE, ADD_PROVIDER, CLEAR_INSTANCES, CLEAR_RECORDER_COUNT, DISPLAY_NOTIFICATION, DISPLAY_POPUP_MESSAGE, FETCH_ACCOUNTS_LIST_FAILED, FETCH_ACCOUNTS_LIST_REQUEST, FETCH_ACCOUNTS_LIST_SUCCESS, FETCH_CONTRACT_LIST_FAILED, FETCH_CONTRACT_LIST_REQUEST, FETCH_CONTRACT_LIST_SUCCESS, FETCH_PROVIDER_LIST_FAILED, FETCH_PROVIDER_LIST_REQUEST, FETCH_PROVIDER_LIST_SUCCESS, HIDE_NOTIFICATION, HIDE_POPUP_MESSAGE, REMOVE_INSTANCE, REMOVE_PROVIDER, RESET_STATE, SET_BASE_FEE_PER_GAS, SET_CONFIRM_SETTINGS, SET_CURRENT_CONTRACT, SET_CURRENT_FILE, SET_DECODED_RESPONSE, SET_DEPLOY_OPTIONS, SET_EXECUTION_ENVIRONMENT, SET_EXTERNAL_WEB3_ENDPOINT, SET_GAS_LIMIT, SET_GAS_PRICE, SET_GAS_PRICE_STATUS, SET_IPFS_CHECKED_STATE, SET_LOAD_TYPE, SET_MATCH_PASSPHRASE, SET_MAX_FEE, SET_MAX_PRIORITY_FEE, SET_NETWORK_NAME, SET_PASSPHRASE, SET_PATH_TO_SCENARIO, SET_PERSONAL_MODE, SET_RECORDER_COUNT, SET_SELECTED_ACCOUNT, SET_SEND_UNIT, SET_SEND_VALUE, SET_PROXY_ENV_ADDRESS, ADD_DEPLOY_OPTION, REMOVE_DEPLOY_OPTION, SET_COMPILATION_SOURCE } from '../constants'
declare const window: any declare const window: any
interface Action { interface Action {
@ -70,6 +70,7 @@ export interface RunTabState {
proxyKey: string, proxyKey: string,
loadType: 'abi' | 'sol' | 'other' loadType: 'abi' | 'sol' | 'other'
currentFile: string, currentFile: string,
compilationSource: string,
currentContract: string, currentContract: string,
compilationCount: number, compilationCount: number,
isRequesting: boolean, isRequesting: boolean,
@ -156,6 +157,7 @@ export const runTabInitialState: RunTabState = {
contractList: {}, contractList: {},
deployOptions: {} as any, deployOptions: {} as any,
proxyKey: '', proxyKey: '',
compilationSource: '',
loadType: 'other', loadType: 'other',
currentFile: '', currentFile: '',
currentContract: '', currentContract: '',
@ -517,6 +519,18 @@ export const runTabReducer = (state: RunTabState = runTabInitialState, action: A
} }
} }
case SET_COMPILATION_SOURCE: {
const payload: string = action.payload
return {
...state,
contracts: {
...state.contracts,
compilationSource: payload,
}
}
}
case SET_IPFS_CHECKED_STATE: { case SET_IPFS_CHECKED_STATE: {
const payload: boolean = action.payload const payload: boolean = action.payload

@ -132,6 +132,7 @@ export interface ContractDropdownProps {
proxyKey: string, proxyKey: string,
loadType: 'abi' | 'sol' | 'other', loadType: 'abi' | 'sol' | 'other',
currentFile: string, currentFile: string,
compilationSource: string
currentContract: string, currentContract: string,
compilationCount: number, compilationCount: number,
isRequesting: boolean, isRequesting: boolean,

@ -863,7 +863,13 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
</OverlayTrigger> </OverlayTrigger>
</button> </button>
<div className='d-flex align-items-center'> <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={(configFilePath === '' && state.useFileConfiguration) || 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={ <OverlayTrigger overlay={
<Tooltip id="overlay-tooltip-compile-run"> <Tooltip id="overlay-tooltip-compile-run">
<div className="text-left"> <div className="text-left">
@ -875,7 +881,7 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
<span> <span>
Compile and Run script Compile and Run script
</span> </span>
</OverlayTrigger> </OverlayTrigger>
</button> </button>
<OverlayTrigger overlay={ <OverlayTrigger overlay={
<Tooltip id="overlay-tooltip-compile-run-doc"> <Tooltip id="overlay-tooltip-compile-run-doc">

@ -1,8 +1,8 @@
import { fileDecoration, FileDecorationIcons } from '@remix-ui/file-decorators' import { fileDecoration, FileDecorationIcons } from '@remix-ui/file-decorators'
import { Plugin } from '@remixproject/engine' import { Plugin } from '@remixproject/engine'
import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint-disable-line import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint-disable-line
import { OverlayTrigger, Tooltip } from 'react-bootstrap' // eslint-disable-line
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs' import { Tab, Tabs, TabList, TabPanel } from 'react-tabs'
import './remix-ui-tabs.css' import './remix-ui-tabs.css'
@ -17,26 +17,25 @@ export interface TabsUIProps {
onReady: (api: any) => void onReady: (api: any) => void
themeQuality: string themeQuality: string
} }
export interface TabsUIApi { export interface TabsUIApi {
activateTab: (namee: string) => void activateTab: (name: string) => void
active: () => string active: () => string
} }
interface ITabsState { interface ITabsState {
selectedIndex: number, selectedIndex: number,
fileDecorations: fileDecoration[], fileDecorations: fileDecoration[],
currentExt: string
} }
interface ITabsAction { interface ITabsAction {
type: string, type: string,
payload: any, payload: any,
ext?: string,
} }
const initialTabsState: ITabsState = { const initialTabsState: ITabsState = {
selectedIndex: -1, selectedIndex: -1,
fileDecorations: [], fileDecorations: [],
currentExt: ''
} }
const tabsReducer = (state: ITabsState, action: ITabsAction) => { const tabsReducer = (state: ITabsState, action: ITabsAction) => {
@ -44,6 +43,7 @@ const tabsReducer = (state: ITabsState, action: ITabsAction) => {
case 'SELECT_INDEX': case 'SELECT_INDEX':
return { return {
...state, ...state,
currentExt: action.ext,
selectedIndex: action.payload, selectedIndex: action.payload,
} }
case 'SET_FILE_DECORATIONS': case 'SET_FILE_DECORATIONS':
@ -71,8 +71,6 @@ export const TabsUI = (props: TabsUIProps) => {
} }
}, [tabsState.selectedIndex]) }, [tabsState.selectedIndex])
const getFileDecorationClasses = (tab: any) => { const getFileDecorationClasses = (tab: any) => {
const fileDecoration = tabsState.fileDecorations.find((fileDecoration: fileDecoration) => { const fileDecoration = tabsState.fileDecorations.find((fileDecoration: fileDecoration) => {
if(`${fileDecoration.workspace.name}/${fileDecoration.path}` === tab.name) return true if(`${fileDecoration.workspace.name}/${fileDecoration.path}` === tab.name) return true
@ -84,8 +82,7 @@ export const TabsUI = (props: TabsUIProps) => {
return <FileDecorationIcons file={{path: tab.name}} fileDecorations={tabsState.fileDecorations} /> return <FileDecorationIcons file={{path: tab.name}} fileDecorations={tabsState.fileDecorations} />
} }
const renderTab = (tab, index) => {
const renderTab = (tab, index) => {
const classNameImg = 'my-1 mr-1 text-dark ' + tab.iconClass const classNameImg = 'my-1 mr-1 text-dark ' + tab.iconClass
const classNameTab = 'nav-item nav-link d-flex justify-content-center align-items-center px-2 py-1 tab' + (index === currentIndexRef.current ? ' active' : '') const classNameTab = 'nav-item nav-link d-flex justify-content-center align-items-center px-2 py-1 tab' + (index === currentIndexRef.current ? ' active' : '')
const invert = props.themeQuality === 'dark' ? 'invert(1)' : 'invert(0)' const invert = props.themeQuality === 'dark' ? 'invert(1)' : 'invert(0)'
@ -106,10 +103,11 @@ export const TabsUI = (props: TabsUIProps) => {
if (currentIndexRef.current < 0) return '' if (currentIndexRef.current < 0) return ''
return tabs.current[currentIndexRef.current].name return tabs.current[currentIndexRef.current].name
} }
const activateTab = (name: string) => { const activateTab = (name: string) => {
const index = tabs.current.findIndex((tab) => tab.name === name) const index = tabs.current.findIndex((tab) => tab.name === name)
currentIndexRef.current = index currentIndexRef.current = index
dispatch({ type: 'SELECT_INDEX', payload: index }) dispatch({ type: 'SELECT_INDEX', payload: index, ext: getExt(name)})
} }
const setFileDecorations = (fileStates: fileDecoration[]) => { const setFileDecorations = (fileStates: fileDecoration[]) => {
@ -135,10 +133,41 @@ export const TabsUI = (props: TabsUIProps) => {
return () => { tabsElement.current.removeEventListener('wheel', transformScroll) } return () => { tabsElement.current.removeEventListener('wheel', transformScroll) }
}, []) }, [])
const getExt = (path) => {
const root = path.split('#')[0].split('?')[0]
const ext = root.indexOf('.') !== -1 ? /[^.]+$/.exec(root) : null
if (ext) return ext[0].toLowerCase()
else return ''
}
return ( return (
<div className="remix-ui-tabs d-flex justify-content-between border-0 header nav-tabs" data-id="tabs-component"> <div className="remix-ui-tabs d-flex justify-content-between border-0 header nav-tabs" data-id="tabs-component">
<div className="d-flex flex-row" style={{ maxWidth: 'fit-content', width: '97%' }}> <div className="d-flex flex-row" style={{ maxWidth: 'fit-content', width: '97%' }}>
<div className="d-flex flex-row justify-content-center align-items-center m-1 mt-2"> <div className="d-flex flex-row justify-content-center align-items-center m-1 mt-1">
<button
className="btn text-success py-0"
disabled={!(tabsState.currentExt === 'js' || tabsState.currentExt === 'ts' || tabsState.currentExt === 'sol')}
onClick={async () => {
const path = active().substr(active().indexOf('/') + 1, active().length)
const content = await props.plugin.call('fileManager', "readFile", path)
if (tabsState.currentExt === 'js' || tabsState.currentExt === 'ts') {
await props.plugin.call('scriptRunner', 'execute', content)
} else if (tabsState.currentExt === 'sol' || tabsState.currentExt === 'yul') {
await props.plugin.call('solidity', 'compile', path)
}
}}
>
<OverlayTrigger placement="bottom" overlay={
<Tooltip id="overlay-tooltip-run-script">
<span>
{(tabsState.currentExt === 'js' || tabsState.currentExt === 'ts') ? "Run script (CTRL + SHIFT + S)" :
tabsState.currentExt === 'sol' || tabsState.currentExt === 'yul'? "Compile CTRL + S" : "Select .sol or .yul file to compile or a .ts or .js file and run it"}
</span>
</Tooltip>
}>
<i className="fad fa-play"></i>
</OverlayTrigger>
</button>
<span data-id="tabProxyZoomOut" className="btn btn-sm px-2 fas fa-search-minus text-dark" title="Zoom out" onClick={() => props.onZoomOut()}></span> <span data-id="tabProxyZoomOut" className="btn btn-sm px-2 fas fa-search-minus text-dark" title="Zoom out" onClick={() => props.onZoomOut()}></span>
<span data-id="tabProxyZoomIn" className="btn btn-sm px-2 fas fa-search-plus text-dark" title="Zoom in" onClick={() => props.onZoomIn()}></span> <span data-id="tabProxyZoomIn" className="btn btn-sm px-2 fas fa-search-plus text-dark" title="Zoom in" onClick={() => props.onZoomIn()}></span>
</div> </div>
@ -153,7 +182,7 @@ export const TabsUI = (props: TabsUIProps) => {
onSelect={(index) => { onSelect={(index) => {
props.onSelect(index) props.onSelect(index)
currentIndexRef.current = index currentIndexRef.current = index
dispatch({ type: 'SELECT_INDEX', payload: index }) dispatch({ type: 'SELECT_INDEX', payload: index, ext: getExt(props.tabs[currentIndexRef.current].name)})
}} }}
> >
<TabList className="d-flex flex-row align-items-center"> <TabList className="d-flex flex-row align-items-center">

@ -1,11 +1,15 @@
import * as WS from 'ws' // eslint-disable-line import * as WS from 'ws' // eslint-disable-line
import { PluginClient } from '@remixproject/plugin' import { PluginClient } from '@remixproject/plugin'
import * as chokidar from 'chokidar'
import * as utils from '../utils'
import * as fs from 'fs-extra'
const { spawn } = require('child_process') // eslint-disable-line const { spawn } = require('child_process') // eslint-disable-line
export class HardhatClient extends PluginClient { export class HardhatClient extends PluginClient {
methods: Array<string> methods: Array<string>
websocket: WS websocket: WS
currentSharedFolder: string currentSharedFolder: string
watcher: chokidar.FSWatcher
constructor (private readOnly = false) { constructor (private readOnly = false) {
super() super()
@ -14,10 +18,14 @@ export class HardhatClient extends PluginClient {
setWebSocket (websocket: WS): void { setWebSocket (websocket: WS): void {
this.websocket = websocket this.websocket = websocket
this.websocket.addEventListener('close', () => {
if (this.watcher) this.watcher.close()
})
} }
sharedFolder (currentSharedFolder: string): void { sharedFolder (currentSharedFolder: string): void {
this.currentSharedFolder = currentSharedFolder this.currentSharedFolder = currentSharedFolder
this.listenOnHardhatCompilation()
} }
compile (configPath: string) { compile (configPath: string) {
@ -46,4 +54,24 @@ export class HardhatClient extends PluginClient {
}) })
}) })
} }
listenOnHardhatCompilation () {
try {
const buildPath = utils.absolutePath('artifacts/build-info', this.currentSharedFolder)
this.watcher = chokidar.watch(buildPath, { depth: 0, ignorePermissionErrors: true })
const processArtifact = async (path: string) => {
const content = await fs.readFile(path, { encoding: 'utf-8' })
const compilationResult = JSON.parse(content)
// @ts-ignore
this.call('terminal', 'log', 'received compilation result from hardhat')
this.emit('compilationFinished', '', compilationResult.input, 'soljson', compilationResult.output, compilationResult.solcVersion)
}
this.watcher.on('change', (path: string) => processArtifact(path))
this.watcher.on('add', (path: string) => processArtifact(path))
} catch (e) {
console.log(e)
}
}
} }

@ -11,6 +11,7 @@ export class RemixdClient extends PluginClient {
trackDownStreamUpdate: TrackDownStreamUpdate = {} trackDownStreamUpdate: TrackDownStreamUpdate = {}
websocket: WS websocket: WS
currentSharedFolder: string currentSharedFolder: string
watcher: chokidar.FSWatcher
constructor (private readOnly = false) { constructor (private readOnly = false) {
super() super()
@ -19,6 +20,9 @@ export class RemixdClient extends PluginClient {
setWebSocket (websocket: WS): void { setWebSocket (websocket: WS): void {
this.websocket = websocket this.websocket = websocket
this.websocket.addEventListener('close', () => {
if (this.watcher) this.watcher.close()
})
} }
sharedFolder (currentSharedFolder: string): void { sharedFolder (currentSharedFolder: string): void {
@ -246,7 +250,7 @@ export class RemixdClient extends PluginClient {
const absPath = utils.absolutePath('./', path) const absPath = utils.absolutePath('./', path)
if (!isRealPath(absPath)) return if (!isRealPath(absPath)) return
const watcher = chokidar.watch(path, { depth: 0, ignorePermissionErrors: true }) this.watcher = chokidar.watch(path, { depth: 0, ignorePermissionErrors: true })
console.log('setup notifications for ' + path) console.log('setup notifications for ' + path)
/* we can't listen on created file / folder /* we can't listen on created file / folder
watcher.on('add', (f, stat) => { watcher.on('add', (f, stat) => {
@ -260,7 +264,7 @@ export class RemixdClient extends PluginClient {
this.emit('created', { path: utils.relativePath(f, this.currentSharedFolder), isReadOnly: false, isFolder: true }) this.emit('created', { path: utils.relativePath(f, this.currentSharedFolder), isReadOnly: false, isFolder: true })
}) })
*/ */
watcher.on('change', async (f: string) => { this.watcher.on('change', async (f: string) => {
if (this.trackDownStreamUpdate[f]) { if (this.trackDownStreamUpdate[f]) {
delete this.trackDownStreamUpdate[f] delete this.trackDownStreamUpdate[f]
return return
@ -269,12 +273,12 @@ export class RemixdClient extends PluginClient {
this.emit('changed', utils.relativePath(f, this.currentSharedFolder)) this.emit('changed', utils.relativePath(f, this.currentSharedFolder))
} }
}) })
watcher.on('unlink', async (f: string) => { this.watcher.on('unlink', async (f: string) => {
if (this.isLoaded) { if (this.isLoaded) {
this.emit('removed', utils.relativePath(f, this.currentSharedFolder), false) this.emit('removed', utils.relativePath(f, this.currentSharedFolder), false)
} }
}) })
watcher.on('unlinkDir', async (f: string) => { this.watcher.on('unlinkDir', async (f: string) => {
if (this.isLoaded) { if (this.isLoaded) {
this.emit('removed', utils.relativePath(f, this.currentSharedFolder), true) this.emit('removed', utils.relativePath(f, this.currentSharedFolder), true)
} }

Loading…
Cancel
Save