compiler loader

desktopoffline
filip mertens 1 year ago
parent 0aa13de1a8
commit be1785b832
  1. 1
      apps/remix-ide/src/app/plugins/electron/compilerLoaderPlugin.ts
  2. 1
      apps/remix-ide/src/remixEngine.js
  3. 2
      apps/remixdesktop/package.json
  4. 69
      apps/remixdesktop/src/plugins/compilerLoader.ts
  5. 0
      apps/remixdesktop/src/plugins/scriptRunner.ts
  6. 152
      apps/remixdesktop/yarn.lock
  7. 1
      libs/remix-ui/app/src/lib/remix-app/context/context.tsx
  8. 6
      libs/remix-ui/app/src/lib/remix-app/remix-app.tsx
  9. 100
      libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx
  10. 113
      libs/remix-ui/solidity-compiler/src/lib/components/compiler-dropdown.tsx
  11. 66
      libs/remix-ui/solidity-compiler/src/lib/components/compiler-menu.tsx
  12. 19
      libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.tsx

@ -19,7 +19,6 @@ export class compilerLoaderPlugin extends ElectronPlugin {
this.on('solidity', 'loadingCompiler', async (url) => {
console.log('loadingCompiler in compilerloader', url, this)
this.call('terminal', 'logHtml', 'Downloading compiler from ' + url)
await this.call('compilerloader', 'downloadCompiler', url)
const compilerList = await this.call('compilerloader', 'listCompilers')
console.log('compilerList', compilerList)

@ -23,6 +23,7 @@ export class RemixEngine extends Engine {
if (name === 'fs') return { queueTimeout: 60000 * 4 }
if (name === 'isogit') return { queueTimeout: 60000 * 4 }
if (name === 'circuit-compiler') return { queueTimeout: 60000 * 4 }
if (name === 'compilerloader') return { queueTimeout: 60000 * 4 }
return { queueTimeout: 10000 }
}

@ -42,8 +42,10 @@
"@remixproject/plugin-electron": "0.3.37",
"@vscode/ripgrep": "^1.15.6",
"add": "^2.0.6",
"axios": "^1.6.1",
"byline": "^5.0.0",
"chokidar": "^3.5.3",
"esbuild": "^0.19.5",
"express": "^4.18.2",
"isomorphic-git": "^1.24.2",
"node-pty": "^0.10.1",

@ -1,21 +1,21 @@
import {Profile} from '@remixproject/plugin-utils'
import {
ElectronBasePlugin,
ElectronBasePluginClient,
} from '@remixproject/plugin-electron'
import {ElectronBasePlugin, ElectronBasePluginClient} from '@remixproject/plugin-electron'
import fs from 'fs/promises'
import axios from 'axios'
import express from 'express'
import {cacheDir} from '../utils/config'
import express from 'express';
import { cacheDir } from '../utils/config'
export const baseURLBin = 'https://binaries.soliditylang.org/bin'
export const baseURLWasm = 'https://binaries.soliditylang.org/wasm'
const appExpress = express()
console.log('cacheDir', cacheDir)
appExpress.use(express.static(cacheDir))
const server = appExpress.listen(0, () => {
console.log('Listening on port:', (server.address() as any));
});
console.log('Listening on port:', server.address() as any)
})
const profile: Profile = {
displayName: 'compilerLoader',
@ -53,16 +53,47 @@ class CompilerLoaderPluginClient extends ElectronBasePluginClient {
async downloadCompiler(url: string): Promise<void> {
console.log('downloadCompiler', url)
this.emit('downloadStarted', url)
const res = await fetch(url)
const buffer = await res.arrayBuffer()
const file = Buffer.from(buffer)
const fileName = url.split('/').pop()
if (fileName) {
const filePath = cacheDir + '/compilers/' + fileName
await fs.writeFile(filePath, file)
console.log('downloaded', filePath)
this.emit('downloadFinished', fileName, url)
const plugin = this
try {
const fileName = url.split('/').pop()
if (fileName) {
const filePath = cacheDir + '/compilers/' + fileName
try{
if (await fs.stat(filePath)) {
return
}}
catch(e){
// do nothing
}
}
this.emit('downloadStarted', url)
this.call('terminal' as any, 'logHtml', 'Downloading compiler from ' + url)
const res = await axios.get(url, {
responseType: 'arraybuffer',
onDownloadProgress(progressEvent) {
if (progressEvent.total) {
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
plugin.call('terminal' as any, 'logHtml', 'percent loaded: ' + percentCompleted)
} else {
plugin.call('terminal' as any, 'logHtml', 'bytes loaded: ' + progressEvent.loaded)
}
},
})
const buffer = await res.data
const file = Buffer.from(buffer)
if (fileName) {
const filePath = cacheDir + '/compilers/' + fileName
await fs.writeFile(filePath, file)
console.log('downloaded', filePath)
this.emit('downloadFinished', fileName, url)
}
} catch (e: any) {
plugin.call('terminal' as any, 'log', {
type: 'error',
value: `Failed to download ${url}: ${e.message}`,
})
}
}
@ -71,4 +102,4 @@ class CompilerLoaderPluginClient extends ElectronBasePluginClient {
const compilers = await fs.readdir(compilersDir)
return compilers
}
}
}

@ -62,6 +62,116 @@
minimatch "^3.0.4"
plist "^3.0.4"
"@esbuild/android-arm64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.5.tgz#276c5f99604054d3dbb733577e09adae944baa90"
integrity sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==
"@esbuild/android-arm@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.5.tgz#4a3cbf14758166abaae8ba9c01a80e68342a4eec"
integrity sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==
"@esbuild/android-x64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.5.tgz#21a3d11cd4613d2d3c5ccb9e746c254eb9265b0a"
integrity sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==
"@esbuild/darwin-arm64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.5.tgz#714cb839f467d6a67b151ee8255886498e2b9bf6"
integrity sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==
"@esbuild/darwin-x64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.5.tgz#2c553e97a6d2b4ae76a884e35e6cbab85a990bbf"
integrity sha512-Ly8cn6fGLNet19s0X4unjcniX24I0RqjPv+kurpXabZYSXGM4Pwpmf85WHJN3lAgB8GSth7s5A0r856S+4DyiA==
"@esbuild/freebsd-arm64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.5.tgz#d554f556718adb31917a0da24277bf84b6ee87f3"
integrity sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==
"@esbuild/freebsd-x64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.5.tgz#288f7358a3bb15d99e73c65c9adaa3dabb497432"
integrity sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==
"@esbuild/linux-arm64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.5.tgz#95933ae86325c93cb6b5e8333d22120ecfdc901b"
integrity sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==
"@esbuild/linux-arm@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.5.tgz#0acef93aa3e0579e46d33b666627bddb06636664"
integrity sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==
"@esbuild/linux-ia32@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.5.tgz#b6e5c9e80b42131cbd6b1ddaa48c92835f1ed67f"
integrity sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==
"@esbuild/linux-loong64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.5.tgz#e5f0cf95a180158b01ff5f417da796a1c09dfbea"
integrity sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==
"@esbuild/linux-mips64el@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.5.tgz#ae36fb86c7d5f641f3a0c8472e83dcb6ea36a408"
integrity sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==
"@esbuild/linux-ppc64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.5.tgz#7960cb1666f0340ddd9eef7b26dcea3835d472d0"
integrity sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==
"@esbuild/linux-riscv64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.5.tgz#32207df26af60a3a9feea1783fc21b9817bade19"
integrity sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==
"@esbuild/linux-s390x@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.5.tgz#b38d5681db89a3723862dfa792812397b1510a7d"
integrity sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==
"@esbuild/linux-x64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.5.tgz#46feba2ad041a241379d150f415b472fe3885075"
integrity sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==
"@esbuild/netbsd-x64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.5.tgz#3b5c1fb068f26bfc681d31f682adf1bea4ef0702"
integrity sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==
"@esbuild/openbsd-x64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.5.tgz#ca6830316ca68056c5c88a875f103ad3235e00db"
integrity sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==
"@esbuild/sunos-x64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.5.tgz#9efc4eb9539a7be7d5a05ada52ee43cda0d8e2dd"
integrity sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==
"@esbuild/win32-arm64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.5.tgz#29f8184afa7a02a956ebda4ed638099f4b8ff198"
integrity sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==
"@esbuild/win32-ia32@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.5.tgz#f3de07afb292ecad651ae4bb8727789de2d95b05"
integrity sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==
"@esbuild/win32-x64@0.19.5":
version "0.19.5"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.5.tgz#faad84c41ba12e3a0acb52571df9bff37bee75f6"
integrity sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==
"@ethereumjs/common@2.6.5", "@ethereumjs/common@^2.6.4":
version "2.6.5"
resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.5.tgz#0a75a22a046272579d91919cb12d84f2756e8d30"
@ -1030,6 +1140,15 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3"
integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==
axios@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.1.tgz#76550d644bf0a2d469a01f9244db6753208397d7"
integrity sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==
dependencies:
follow-redirects "^1.15.0"
form-data "^4.0.0"
proxy-from-env "^1.1.0"
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
@ -2045,6 +2164,34 @@ es6-symbol@^3.1.1, es6-symbol@^3.1.3:
d "^1.0.1"
ext "^1.1.2"
esbuild@^0.19.5:
version "0.19.5"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.5.tgz#53a0e19dfbf61ba6c827d51a80813cf071239a8c"
integrity sha512-bUxalY7b1g8vNhQKdB24QDmHeY4V4tw/s6Ak5z+jJX9laP5MoQseTOMemAr0gxssjNcH0MCViG8ONI2kksvfFQ==
optionalDependencies:
"@esbuild/android-arm" "0.19.5"
"@esbuild/android-arm64" "0.19.5"
"@esbuild/android-x64" "0.19.5"
"@esbuild/darwin-arm64" "0.19.5"
"@esbuild/darwin-x64" "0.19.5"
"@esbuild/freebsd-arm64" "0.19.5"
"@esbuild/freebsd-x64" "0.19.5"
"@esbuild/linux-arm" "0.19.5"
"@esbuild/linux-arm64" "0.19.5"
"@esbuild/linux-ia32" "0.19.5"
"@esbuild/linux-loong64" "0.19.5"
"@esbuild/linux-mips64el" "0.19.5"
"@esbuild/linux-ppc64" "0.19.5"
"@esbuild/linux-riscv64" "0.19.5"
"@esbuild/linux-s390x" "0.19.5"
"@esbuild/linux-x64" "0.19.5"
"@esbuild/netbsd-x64" "0.19.5"
"@esbuild/openbsd-x64" "0.19.5"
"@esbuild/sunos-x64" "0.19.5"
"@esbuild/win32-arm64" "0.19.5"
"@esbuild/win32-ia32" "0.19.5"
"@esbuild/win32-x64" "0.19.5"
escalade@^3.1.1:
version "3.1.1"
resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz"
@ -2324,6 +2471,11 @@ finalhandler@1.2.0:
statuses "2.0.1"
unpipe "~1.0.0"
follow-redirects@^1.15.0:
version "1.15.3"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a"
integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==
for-each@^0.3.3:
version "0.3.3"
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"

@ -9,6 +9,7 @@ export type appProviderContextType = {
modal: any
layout: any
platform: appPlatformTypes
online: boolean
}
export enum appPlatformTypes {

@ -19,6 +19,7 @@ const RemixApp = (props: IRemixAppUi) => {
const [hideSidePanel, setHideSidePanel] = useState<boolean>(false)
const [maximiseTrigger, setMaximiseTrigger] = useState<number>(0)
const [resetTrigger, setResetTrigger] = useState<number>(0)
const [online, setOnline] = useState<boolean>(true)
const [locale, setLocale] = useState<{code: string; messages: any}>({
code: 'en',
messages: {}
@ -71,6 +72,10 @@ const RemixApp = (props: IRemixAppUi) => {
props.app.localeModule.events.on('localeChanged', (nextLocale) => {
setLocale(nextLocale)
})
setInterval(() => {
setOnline(window.navigator.onLine)
}, 1000)
}
const value: appProviderContextType = {
@ -80,6 +85,7 @@ const RemixApp = (props: IRemixAppUi) => {
modal: props.app.notification,
layout: props.app.layout,
platform: props.app.platform,
online: online
}
return (

@ -3,7 +3,7 @@ import {FormattedMessage, useIntl} from 'react-intl'
import semver from 'semver'
import {CompilerContainerProps} from './types'
import {ConfigurationSettings} from '@remix-project/remix-lib'
import {checkSpecialChars, CustomMenu, CustomToggle, CustomTooltip, extractNameFromKey} from '@remix-ui/helper'
import {checkSpecialChars, CustomTooltip, extractNameFromKey} from '@remix-ui/helper'
import {canUseWorker, baseURLBin, baseURLWasm, urlFromVersion, pathToURL} from '@remix-project/remix-solidity'
import {compilerReducer, compilerInitialState} from './reducers/compiler'
import {resetEditorMode, listenToEvents} from './actions/compiler'
@ -15,6 +15,8 @@ import { AppContext, appPlatformTypes } from '@remix-ui/app'
import './css/style.css'
import { Dropdown } from 'react-bootstrap'
import { hidden } from 'colors'
import { CompilerDropdown } from './components/compiler-dropdown'
const defaultPath = 'compiler_config.json'
declare global {
@ -26,7 +28,7 @@ declare global {
const _paq = (window._paq = window._paq || []) //eslint-disable-line
export const CompilerContainer = (props: CompilerContainerProps) => {
const {platform} = useContext(AppContext)
const {platform, online} = useContext(AppContext)
const {
api,
compileTabLogic,
@ -104,6 +106,12 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
}
}, [state.useFileConfiguration])
useEffect(() => {
setState((prevState) => {
return {...prevState, onlyDownloaded: !online}
})
},[online])
useEffect(() => {
const listener = (event) => {
if (configFilePathInput.current !== event.target && event.target.innerText !== 'Create') {
@ -335,10 +343,18 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
longVersion: 'latest local version - ' + state.defaultVersion
}
]
// fetch normal builds
const binRes: AxiosResponse = await axios(`${baseURLBin}/list.json`)
// fetch wasm builds
const wasmRes: AxiosResponse = await axios(`${baseURLWasm}/list.json`)
let binRes: AxiosResponse
let wasmRes: AxiosResponse
try {
// fetch normal builds
binRes = await axios(`${baseURLBin}/list.json`)
// fetch wasm builds
wasmRes = await axios(`${baseURLWasm}/list.json`)
} catch (e) {
selectedVersion = 'builtin'
console.log('Error while fetching compiler list', e.message)
return callback(allVersions, selectedVersion)
}
if (binRes.status !== 200 && wasmRes.status !== 200) {
selectedVersion = 'builtin'
return callback(allVersions, selectedVersion)
@ -813,65 +829,15 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
<CustomTooltip placement="top" tooltipId="showCompilerTooltip" tooltipClasses="text-nowrap" tooltipText={<FormattedMessage id="solidity.seeCompilerLicense" />}>
<span className="fa fa-file-text-o border-0 p-0 ml-2" onClick={() => showCompilerLicense()}></span>
</CustomTooltip>
<Dropdown id="versionSelector" data-id="versionSelector">
<Dropdown.Toggle as={CustomToggle} id="dropdown-custom-components" className="btn btn-light btn-block w-100 d-inline-block border border-dark form-control" icon={null}>
{state.allversions.map((build, i) => {
if ((state.selectedVersion || state.defaultVersion) === build.path) {
return (<span key={i}>{build.longVersion}</span>)
}})}
</Dropdown.Toggle>
<Dropdown.Menu as={CustomMenu} className="w-100 custom-dropdown-items overflow-hidden" data-id="custom-dropdown-items">
{state.allversions.map((build, i) => {
return _shouldBeAdded(build.longVersion) ? (
<Dropdown.Item
key={i}
data-id={`dropdown-item-${build.value}`}
>
<div className='d-flex w-100'>
{state.selectedVersion === build.path ? <span className='fas fa-check text-success mr-2'></span> : null}
<span className="">
{build.longVersion}
</span>
{build.isDownloaded?<span className='fas fa-arrow-circle-down text-success'></span>:<span className='far fa-arrow-circle-down'></span>}
</div>
</Dropdown.Item>
) : null
})}
</Dropdown.Menu>
</Dropdown>
<select
value={state.selectedVersion || state.defaultVersion}
onChange={(e) => handleLoadVersion(e.target.value)}
className="custom-select"
id="versionSelector"
disabled={state.allversions.length <= 0}
>
{state.allversions.length <= 0 && (
<option disabled data-id={state.selectedVersion === state.defaultVersion ? 'selected' : ''}>
{state.defaultVersion}
</option>
)}
{state.allversions.length <= 0 && (
<option disabled data-id={state.selectedVersion === 'builtin' ? 'selected' : ''}>
builtin
</option>
)}
{state.customVersions.map((url, i) => (
<option key={i} data-id={state.selectedVersion === url ? 'selected' : ''} value={url}>
custom
</option>
))}
{state.allversions.map((build, i) => {
return _shouldBeAdded(build.longVersion) ? (
<option key={i} value={build.path} data-id={state.selectedVersion === build.path ? 'selected' : ''}>
{build.longVersion}
</option>
) : null
})}
</select>
<CompilerDropdown
allversions={state.allversions}
customVersions={state.customVersions}
selectedVersion={state.selectedVersion}
defaultVersion={state.defaultVersion}
handleLoadVersion={handleLoadVersion}
_shouldBeAdded={_shouldBeAdded}
onlyDownloaded={state.onlyDownloaded}
></CompilerDropdown>
</div>
<div className="mb-2 flex-row-reverse remixui_nightlyBuilds custom-control custom-checkbox">
<input className="mr-2 custom-control-input" id="nightlies" type="checkbox" onChange={handleNightliesChange} checked={state.includeNightlies} />
@ -880,8 +846,8 @@ export const CompilerContainer = (props: CompilerContainerProps) => {
</label>
</div>
<div className="mb-2 flex-row-reverse remixui_nightlyBuilds custom-control custom-checkbox">
<input className="mr-2 custom-control-input" id="nightlies" type="checkbox" onChange={handleOnlyDownloadedChange} checked={state.includeNightlies} />
<label htmlFor="nightlies" data-id="compilerNightliesBuild" className="form-check-label custom-control-label">
<input className="mr-2 custom-control-input" id="downloadedcompilers" type="checkbox" onChange={handleOnlyDownloadedChange} checked={state.onlyDownloaded} />
<label htmlFor="downloadedcompilers" data-id="compilerNightliesBuild" className="form-check-label custom-control-label">
<FormattedMessage id="solidity.downloadedCompilers" />
</label>
</div>

@ -0,0 +1,113 @@
import React, { useEffect, useState, useRef, useReducer, useContext } from 'react' // eslint-disable-line
import { Dropdown } from 'react-bootstrap';
import { CompilerMenu, CompilerMenuToggle } from './compiler-menu';
export type compilerVersion = {
path: string,
longVersion: string,
isDownloaded: boolean
}
interface compilerDropdownProps {
customVersions: string[],
selectedVersion: string,
defaultVersion: string,
allversions: compilerVersion[],
handleLoadVersion: (url: string) => void,
_shouldBeAdded: (version: string) => {},
onlyDownloaded: boolean
}
export const CompilerDropdown = (props: compilerDropdownProps) => {
const { customVersions, selectedVersion, defaultVersion, allversions, handleLoadVersion, _shouldBeAdded, onlyDownloaded } = props
return (
<Dropdown id="versionSelector" data-id="versionSelector">
<Dropdown.Toggle as={CompilerMenuToggle} id="dropdown-custom-components" className="btn btn-light btn-block w-100 d-inline-block border border-dark form-control" icon={null}>
<div style={{ flexGrow: 1, overflow: 'hidden', display:'flex', justifyContent:'left' }}>
<div className="text-truncate">
{customVersions.map((url, i) => {
if (selectedVersion === url) return (<span key={i}>custom</span>)
})}
{allversions.map((build, i) => {
if ((selectedVersion || defaultVersion) === build.path) {
return (<span key={i}>{build.longVersion}</span>)
}
})}
</div>
</div>
</Dropdown.Toggle>
<Dropdown.Menu as={CompilerMenu} className="w-100 custom-dropdown-items overflow-hidden" data-id="custom-dropdown-items">
{allversions.length <= 0 && (
<Dropdown.Item
key={`default`}
data-id='builtin'
onClick={() => {}}
>
<div className='d-flex w-100 justify-content-between'>
{selectedVersion === defaultVersion ? <span className='fas fa-check text-success mr-2'></span> : null}
<div style={{ flexGrow: 1, overflow: 'hidden' }}>
<div className="text-truncate">
{defaultVersion}
</div>
</div>
</div>
</Dropdown.Item>
)}
{allversions.length <= 0 && (
<Dropdown.Item
key={`builtin`}
data-id='builtin'
onClick={() => {}}
>
<div className='d-flex w-100 justify-content-between'>
{selectedVersion === "builtin" ? <span className='fas fa-check text-success mr-2'></span> : null}
<div style={{ flexGrow: 1, overflow: 'hidden' }}>
<div className="text-truncate">
builtin
</div>
</div>
</div>
</Dropdown.Item>
)}
{customVersions.map((url, i) => (
<Dropdown.Item
key={`custom-${i}`}
data-id={`dropdown-item-${url}`}
onClick={() => handleLoadVersion(url)}
>
<div className='d-flex w-100 justify-content-between'>
{selectedVersion === url ? <span className='fas fa-check text-success mr-2'></span> : null}
<div style={{ flexGrow: 1, overflow: 'hidden' }}>
<div className="text-truncate">
custom: {url}
</div>
</div>
</div>
</Dropdown.Item>
))}
{allversions.map((build, i) => {
if (onlyDownloaded && !build.isDownloaded) return null
return _shouldBeAdded(build.longVersion) ? (
<Dropdown.Item
key={`soljson-${i}`}
data-id={`dropdown-item-${build.path}`}
onClick={() => handleLoadVersion(build.path)}
>
<div className='d-flex w-100 justify-content-between'>
{selectedVersion === build.path ? <span className='fas fa-check text-success mr-2'></span> : null}
<div style={{ flexGrow: 1, overflow: 'hidden' }}>
<div className="text-truncate">
{build.longVersion}
</div>
</div>
{build.isDownloaded ? <div className='fas fa-arrow-circle-down text-success ml-auto'></div> : <div className='far fa-arrow-circle-down'></div>}
</div>
</Dropdown.Item>
) : null
})}
</Dropdown.Menu>
</Dropdown>
);
}

@ -0,0 +1,66 @@
import React, { useEffect, useState, useRef, useReducer, useContext, Ref } from 'react'
export const CompilerMenu = React.forwardRef(
(
{
children,
style,
'data-id': dataId,
className,
'aria-labelledby': labeledBy
}: {
'children': React.ReactNode
'style'?: React.CSSProperties
'data-id'?: string
'className': string
'aria-labelledby'?: string
},
ref: Ref<HTMLDivElement>
) => {
const height = window.innerHeight * 0.6
return (
<div ref={ref} style={style} className={className} aria-labelledby={labeledBy} data-id={dataId}>
<ul className="list-unstyled mb-0" style={{maxHeight: height + 'px',overflowY:'auto'}}>
{children}
</ul>
</div>
)
}
)
export const CompilerMenuToggle = React.forwardRef(
(
{
children,
onClick,
icon,
className = ''
}: {
children: React.ReactNode
onClick: (e) => void
icon: string
className: string
},
ref: Ref<HTMLButtonElement>
) => (
<button
ref={ref}
onClick={(e) => {
e.preventDefault()
onClick(e)
}}
className={className.replace('dropdown-toggle', '')}
>
<div className="d-flex">
{children}
{icon && (
<div className="pr-1">
<i className={`${icon} pr-1`}></i>
</div>
)}
<div>
<i className="fad fa-sort-circle"></i>
</div>
</div>
</button>
)
)

@ -1,4 +1,4 @@
import React, {Fragment, useEffect, useReducer, useRef, useState} from 'react'
import React, {Fragment, useContext, useEffect, useReducer, useRef, useState} from 'react'
import {Plugin} from '@remixproject/engine'
import './remix-ui-vertical-icons-panel.css'
import IconList from './components/IconList'
@ -6,6 +6,8 @@ import Home from './components/Home'
import {verticalScrollReducer} from './reducers/verticalScrollReducer'
import {Chevron} from './components/Chevron'
import {IconRecord} from './types'
import { AppContext } from '@remix-ui/app'
import { CustomTooltip } from '@remix-ui/helper'
export interface RemixUiVerticalIconsPanelProps {
verticalIconsPlugin: Plugin
icons: IconRecord[]
@ -22,6 +24,7 @@ const RemixUiVerticalIconsPanel = ({verticalIconsPlugin, icons}: RemixUiVertical
const iconPanelRef = useRef<any>()
const [activateScroll, dispatchScrollAction] = useReducer(verticalScrollReducer, initialState)
const [theme, setTheme] = useState<string>('dark')
const {online} = useContext(AppContext)
const evaluateScrollability = () => {
dispatchScrollAction({
@ -116,6 +119,20 @@ const RemixUiVerticalIconsPanel = ({verticalIconsPlugin, icons}: RemixUiVertical
itemContextAction={itemContextAction}
/>
</div>
{online ?
<CustomTooltip
placement="top"
tooltipText={'You are online'}
>
<i className="fa-solid fa-wifi text-success p-2"></i>
</CustomTooltip>
:
<CustomTooltip
placement="top"
tooltipText={'You are offline'}
>
<i className="fa-solid fa-wifi-exclamation text-danger p-2"></i>
</CustomTooltip>}
</div>
</div>
)

Loading…
Cancel
Save