From b106cc8cdf68aa442bfbd708ac43f868891b4f1c Mon Sep 17 00:00:00 2001 From: filip mertens Date: Wed, 7 Jun 2023 17:22:30 +0200 Subject: [PATCH] fs support --- apps/1test/src/remix/lib/electronPlugin.ts | 13 +- apps/remix-ide/src/app/files/fileManager.ts | 8 +- apps/remix-ide/src/app/files/fileProvider.js | 2 + apps/remix-ide/src/app/plugins/fsPlugin.ts | 111 +++++++++++--- apps/remixdesktop/src/engine.ts | 5 + apps/remixdesktop/src/fsPlugin.ts | 37 +++-- apps/remixdesktop/src/gitPlugin.ts | 15 +- apps/remixdesktop/src/main.ts | 36 ++++- apps/remixdesktop/src/menus/commands.ts | 24 +++ apps/remixdesktop/src/menus/darwin.ts | 56 +++++++ apps/remixdesktop/src/menus/file.ts | 28 ++++ apps/remixdesktop/src/menus/main.ts | 26 ++++ apps/remixdesktop/src/xtermPlugin.ts | 15 +- .../workspace/src/lib/actions/events.ts | 5 + .../workspace/src/lib/remix-ui-workspace.tsx | 99 ++++++++----- package.json | 21 +-- yarn.lock | 139 +++++++++--------- 17 files changed, 450 insertions(+), 190 deletions(-) create mode 100644 apps/remixdesktop/src/menus/commands.ts create mode 100644 apps/remixdesktop/src/menus/darwin.ts create mode 100644 apps/remixdesktop/src/menus/file.ts create mode 100644 apps/remixdesktop/src/menus/main.ts diff --git a/apps/1test/src/remix/lib/electronPlugin.ts b/apps/1test/src/remix/lib/electronPlugin.ts index 9412c98c83..181fb46c71 100644 --- a/apps/1test/src/remix/lib/electronPlugin.ts +++ b/apps/1test/src/remix/lib/electronPlugin.ts @@ -47,16 +47,11 @@ export abstract class ElectronPlugin extends Plugin { * @param name The name of the plugin should connect to */ protected async connect(name: string) { - console.log('ElectronPluginConnector connect', name) - const r = await window.electronAPI.activatePlugin(name) - console.log('ElectronPluginConnector is connected', name, r) - - /* - if(await window.electronAPI.activatePlugin(name) && !this.loaded){ - console.log('ElectronPluginConnector calling handshake', name) + const connected = await window.electronAPI.activatePlugin(name) + if(connected && !this.loaded){ this.handshake() } - */ + } /** Close connection with the plugin */ protected disconnect(): any | Promise { @@ -89,7 +84,6 @@ export abstract class ElectronPlugin extends Plugin { /** Perform handshake with the client if not loaded yet */ protected async handshake() { - console.log('ElectronPluginConnector handshake', this.loaded) if (!this.loaded) { this.loaded = true let methods: string[]; @@ -170,7 +164,6 @@ export abstract class ElectronPlugin extends Plugin { // Return result from exposed method case 'response': { const { id, payload, error } = message - console.log('ElectronPluginConnector getMessage response', message, this.pendingRequest) this.pendingRequest[id](payload, error) delete this.pendingRequest[id] break diff --git a/apps/remix-ide/src/app/files/fileManager.ts b/apps/remix-ide/src/app/files/fileManager.ts index 63c1a8d009..ef1883f524 100644 --- a/apps/remix-ide/src/app/files/fileManager.ts +++ b/apps/remix-ide/src/app/files/fileManager.ts @@ -155,8 +155,12 @@ class FileManager extends Plugin { refresh() { const provider = this.fileProviderOf('/') // emit rootFolderChanged so that File Explorer reloads the file tree - provider.event.emit('rootFolderChanged', provider.workspace || '/') - this.emit('rootFolderChanged', provider.workspace || '/') + if(isElectron()){ + provider.event.emit('refresh') + }else{ + provider.event.emit('rootFolderChanged', provider.workspace || '/') + this.emit('rootFolderChanged', provider.workspace || '/') + } } /** diff --git a/apps/remix-ide/src/app/files/fileProvider.js b/apps/remix-ide/src/app/files/fileProvider.js index e78f68cf14..7a43bf6f8e 100644 --- a/apps/remix-ide/src/app/files/fileProvider.js +++ b/apps/remix-ide/src/app/files/fileProvider.js @@ -286,12 +286,14 @@ class FileProvider { if (path.indexOf('/') !== 0) path = '/' + path try { const files = await window.remixFileSystem.readdir(path) + console.log(files, 'files resolveDirectory') const ret = {} if (files) { for (let element of files) { path = path.replace(/^\/|\/$/g, '') // remove first and last slash element = element.replace(/^\/|\/$/g, '') // remove first and last slash const absPath = (path === '/' ? '' : path) + '/' + element + console.log(absPath, 'absPath') ret[absPath.indexOf('/') === 0 ? absPath.substr(1, absPath.length) : absPath] = { isDirectory: (await window.remixFileSystem.stat(absPath)).isDirectory() } // ^ ret does not accept path starting with '/' } diff --git a/apps/remix-ide/src/app/plugins/fsPlugin.ts b/apps/remix-ide/src/app/plugins/fsPlugin.ts index d3f1b2e7b7..078d5fbd72 100644 --- a/apps/remix-ide/src/app/plugins/fsPlugin.ts +++ b/apps/remix-ide/src/app/plugins/fsPlugin.ts @@ -1,23 +1,25 @@ import { ElectronPlugin } from '@remixproject/engine-electron'; +import once from 'just-once'; -let workingDir = '/Volumes/bunsen/code/rmproject2/remix-project/apps/remix-ide/contracts/' -const fixPath = (path: string) => { - /* - // if it starts with /, it's an absolute path remove it - if (path.startsWith('/')) { - path = path.slice(1) - } +let workingDir = null - path = workingDir + path - */ - - +const fixPath = (path: string) => { return path } +function wrapCallback(opts, cb) { + if (typeof opts === "function") { + cb = opts; + } + cb = once(cb); + const resolve = (...args) => cb(null, ...args) + return [resolve, cb]; +} + export class fsPlugin extends ElectronPlugin { public fs: any + public fsSync: any constructor() { super({ @@ -27,6 +29,20 @@ export class fsPlugin extends ElectronPlugin { }) this.methods = ['readdir', 'readFile', 'writeFile', 'mkdir', 'rmdir', 'unlink', 'rename', 'stat', 'exists', 'setWorkingDir'] + // List of commands all filesystems are expected to provide. `rm` is not + // included since it may not exist and must be handled as a special case + const commands = [ + 'readFile', + 'writeFile', + 'mkdir', + 'rmdir', + 'unlink', + 'stat', + 'lstat', + 'readdir', + 'readlink', + 'symlink', + ] this.fs = { @@ -43,7 +59,7 @@ export class fsPlugin extends ElectronPlugin { readdir: async (path: string) => { path = fixPath(path) console.log('readdir', path) - const files = await this.call('fs', 'readdir', path) + const files = await this.call('fs', 'readdir', path) console.log('readdir', path, files) return files }, @@ -55,9 +71,12 @@ export class fsPlugin extends ElectronPlugin { path = fixPath(path) return await this.call('fs', 'mkdir', path) }, - readFile: async (path: string) => { + readFile: async (path: string, options) => { + console.log('readFile', path, options) path = fixPath(path) - return await this.call('fs', 'readFile', path) + const file = await this.call('fs', 'readFile', path) + console.log('readFile', path, file) + return file } , rename: async (from: string, to: string) => { @@ -70,28 +89,86 @@ export class fsPlugin extends ElectronPlugin { , stat: async (path: string) => { path = fixPath(path) - const stat = await this.call('fs', 'stat', path) + const stat = await this.call('fs', 'stat', path) + stat.isDirectory = () => stat.isDirectoryValue + stat.isFile = () => !stat.isDirectoryValue + //console.log('stat', path, stat) + return stat + }, + lstat: async (path: string) => { + path = fixPath(path) + const stat = await this.call('fs', 'lstat', path) stat.isDirectory = () => stat.isDirectoryValue stat.isFile = () => !stat.isDirectoryValue //console.log('stat', path, stat) return stat + }, + readlink: async (path: string) => { + path = fixPath(path) + return await this.call('fs', 'readlink', path) + }, + symlink: async (target: string, path: string) => { + path = fixPath(path) + return await this.call('fs', 'symlink', target, path) } + + } + + + + } + + async onActivation() { console.log('fsPluginClient onload', this.fs); - (window as any).remixFileSystem = this.fs + (window as any).remixFileSystem = this.fs; + /*(window as any).remixFileSystemCallback = { + readdir: (filepath, opts, cb) => { + console.log('readdir', filepath, opts) + const [resolve, reject] = wrapCallback(opts, cb); + (window as any).remixFileSystem.fs.readdir(filepath, opts).then(resolve).catch(reject); + }, + readFile: (filepath, opts, cb) => { + console.log('readFile', filepath, opts) + const [resolve, reject] = wrapCallback(opts, cb); + (window as any).remixFileSystem.fs.readFile(filepath, opts).then(resolve).catch(reject) + }, + writeFile: (filepath, content, opts, cb) => { + const [resolve, reject] = wrapCallback(opts, cb); + (window as any).remixFileSystem.fs.writeFile(filepath, content, opts).then(resolve).catch(reject) + }, + mkdir: (filepath, opts, cb) => { + const [resolve, reject] = wrapCallback(opts, cb); + (window as any).remixFileSystem.fs.mkdir(filepath, opts).then(resolve).catch(reject) + }, + rmdir: (filepath, opts, cb) => { + const [resolve, reject] = wrapCallback(opts, cb); + (window as any).remixFileSystem.fs.rmdir(filepath, opts).then(resolve).catch(reject) + }, + unlink: (filepath, opts, cb) => { + const [resolve, reject] = wrapCallback(opts, cb); + (window as any).remixFileSystem.fs.unlink(filepath, opts).then(resolve).catch(reject) + }, + stat: (filepath, opts, cb) => { + const [resolve, reject] = wrapCallback(opts, cb); + (window as any).remixFileSystem.fs.stat(filepath, opts).then(resolve).catch(reject) + } + }; + */ - this.on('fs', 'workingDirChanged', (path: string) => { + this.on('fs', 'workingDirChanged', async (path: string) => { console.log('change working dir', path) workingDir = path + await this.call('fileManager', 'refresh') }) } diff --git a/apps/remixdesktop/src/engine.ts b/apps/remixdesktop/src/engine.ts index d611ce6af5..0493fc20df 100644 --- a/apps/remixdesktop/src/engine.ts +++ b/apps/remixdesktop/src/engine.ts @@ -22,6 +22,11 @@ ipcMain.handle('manager:activatePlugin', async (event, plugin) => { return await appManager.call(plugin, 'createClient', event.sender.id) }) +ipcMain.on('fs:openFolder', async (event) => { + console.log('fs:openFolder', event) + fsPlugin.openFolder(event) +}) + ipcMain.handle('getWebContentsID', (event, message) => { return event.sender.id }) diff --git a/apps/remixdesktop/src/fsPlugin.ts b/apps/remixdesktop/src/fsPlugin.ts index 2911826495..e802cf8fd3 100644 --- a/apps/remixdesktop/src/fsPlugin.ts +++ b/apps/remixdesktop/src/fsPlugin.ts @@ -13,25 +13,23 @@ const profile: Profile = { export class FSPlugin extends ElectronBasePlugin { clients: FSPluginClient[] = [] constructor() { - super(profile) + super(profile, clientProfile, FSPluginClient) this.methods = [...super.methods, 'closeWatch'] } - async createClient(webContentsId: number): Promise { - this.clients.push(new FSPluginClient(webContentsId)) - } - - async closeClient(webContentsId: number): Promise { - console.log('closeClient', webContentsId) - } - - async closeWatch(): Promise { for (const client of this.clients) { await client.closeWatch() } } + openFolder(webContentsId: any): void { + const client = this.clients.find(c => c.webContentsId === webContentsId) + if (client) { + client.setWorkingDir() + } + } + } const clientProfile: Profile = { @@ -45,13 +43,14 @@ class FSPluginClient extends ElectronBasePluginClient { watcher: chokidar.FSWatcher workingDir: string = '/Volumes/bunsen/code/rmproject2/remix-project/apps/remix-ide/contracts/' - constructor(webContentsId: number) { - super(webContentsId, clientProfile) + constructor(webContentsId: number, profile: Profile) { + super(webContentsId, profile) this.onload(() => { console.log('fsPluginClient onload') }) } + async readdir(path: string): Promise { // call node fs.readdir console.log('readdir', path) @@ -59,8 +58,8 @@ class FSPluginClient extends ElectronBasePluginClient { return files } - async readFile(path: string): Promise { - return fs.readFile(this.fixPath(path), 'utf8') + async readFile(path: string, options: any ): Promise { + return fs.readFile(this.fixPath(path), 'utf8') } async writeFile(path: string, content: string): Promise { @@ -84,7 +83,7 @@ class FSPluginClient extends ElectronBasePluginClient { } async stat(path: string): Promise { - const stat = await fs.stat(path) + const stat = await fs.stat(this.fixPath(path)) //console.log('stat', path, stat) const isDirectory = stat.isDirectory() return { @@ -93,6 +92,13 @@ class FSPluginClient extends ElectronBasePluginClient { } } + async lstat(path: string): Promise { + const lstat = await fs.lstat(this.fixPath(path)) + return lstat + } + + + async exists(path: string): Promise { return fs.access(this.fixPath(path)).then(() => true).catch(() => false) } @@ -131,6 +137,7 @@ class FSPluginClient extends ElectronBasePluginClient { if (path.startsWith('/')) { path = path.slice(1) } + if(!this.workingDir.endsWith('/')) this.workingDir = this.workingDir + '/' path = this.workingDir + path return path } diff --git a/apps/remixdesktop/src/gitPlugin.ts b/apps/remixdesktop/src/gitPlugin.ts index 3ecd82d646..36faca385c 100644 --- a/apps/remixdesktop/src/gitPlugin.ts +++ b/apps/remixdesktop/src/gitPlugin.ts @@ -12,18 +12,9 @@ const profile: Profile = { export class GitPlugin extends ElectronBasePlugin { client: PluginClient constructor() { - super(profile) + super(profile, clientProfile, GitPluginClient) } - async createClient(webContentsId: number): Promise { - this.clients.push(new GitPluginClient(webContentsId)) - } - - async closeClient(webContentsId: number): Promise { - console.log('closeClient', webContentsId) - } - - } const clientProfile: Profile = { @@ -35,8 +26,8 @@ const clientProfile: Profile = { class GitPluginClient extends ElectronBasePluginClient { - constructor(webContentsId: number) { - super(webContentsId, clientProfile) + constructor(webContentsId: number, profile: Profile) { + super(webContentsId, profile) this.onload(() => { console.log('GitPluginClient onload') }) diff --git a/apps/remixdesktop/src/main.ts b/apps/remixdesktop/src/main.ts index 86d870811e..37ec88e352 100644 --- a/apps/remixdesktop/src/main.ts +++ b/apps/remixdesktop/src/main.ts @@ -1,4 +1,4 @@ -import { app, BrowserWindow } from 'electron'; +import { app, BrowserWindow, dialog, Menu } from 'electron'; import path from 'path'; @@ -13,13 +13,8 @@ if ( isPackaged = true; } - -// Handle creating/removing shortcuts on Windows when installing/uninstalling. -if (require('electron-squirrel-startup')) { - app.quit(); -} export let mainWindow: BrowserWindow; -const createWindow = (): void => { +export const createWindow = (): void => { // Create the browser window. mainWindow = new BrowserWindow({ height: 800, @@ -62,5 +57,32 @@ app.on('activate', () => { } }); +const showAbout = () => { + + + void dialog.showMessageBox({ + title: `About Remix`, + message: `Remix`, + detail: `Remix`, + buttons: [], + }); +}; + // In this file you can include the rest of your app's specific main process // code. You can also put them in separate files and import them here. + +const isMac = process.platform === 'darwin' + +import FileMenu from './menus/file'; +import MainMenu from './menus/main'; +import darwinMenu from './menus/darwin'; +import { execCommand } from './menus/commands'; + +const commandKeys: Record = { + 'window:new': 'CmdOrCtrl+N', + 'folder:open': 'CmdOrCtrl+O', +}; + + +const menu = [...(process.platform === 'darwin' ? [darwinMenu(commandKeys, execCommand, showAbout)] : []), FileMenu(commandKeys, execCommand)] +Menu.setApplicationMenu(Menu.buildFromTemplate(menu)) diff --git a/apps/remixdesktop/src/menus/commands.ts b/apps/remixdesktop/src/menus/commands.ts new file mode 100644 index 0000000000..79f36cb28b --- /dev/null +++ b/apps/remixdesktop/src/menus/commands.ts @@ -0,0 +1,24 @@ +import {app, Menu, BrowserWindow, ipcMain} from 'electron'; +import { createWindow } from '../main'; + + +const commands: Record void> = { + 'window:new': () => { + // If window is created on the same tick, it will consume event too + setTimeout(createWindow, 0); + }, + 'folder:open': (focusedWindow) => { + if (focusedWindow) { + ipcMain.emit('fs:openFolder', focusedWindow.webContents.id); + } + } + +}; + + +export const execCommand = (command: string, focusedWindow?: BrowserWindow) => { + const fn = commands[command]; + if (fn) { + fn(focusedWindow); + } +}; diff --git a/apps/remixdesktop/src/menus/darwin.ts b/apps/remixdesktop/src/menus/darwin.ts new file mode 100644 index 0000000000..f12bbb692e --- /dev/null +++ b/apps/remixdesktop/src/menus/darwin.ts @@ -0,0 +1,56 @@ +// This menu label is overrided by OSX to be the appName +// The label is set to appName here so it matches actual behavior +import {app, BrowserWindow, MenuItemConstructorOptions} from 'electron'; + +export default ( + commandKeys: Record, + execCommand: (command: string, focusedWindow?: BrowserWindow) => void, + showAbout: () => void +): MenuItemConstructorOptions => { + return { + label: `${app.name}`, + submenu: [ + { + label: 'About Remix', + click() { + showAbout(); + } + }, + { + type: 'separator' + }, + { + label: 'Preferences...', + accelerator: commandKeys['window:preferences'], + click() { + execCommand('window:preferences'); + } + }, + { + type: 'separator' + }, + { + role: 'services', + submenu: [] + }, + { + type: 'separator' + }, + { + role: 'hide' + }, + { + role: 'hideOthers' + }, + { + role: 'unhide' + }, + { + type: 'separator' + }, + { + role: 'quit' + } + ] + }; +}; diff --git a/apps/remixdesktop/src/menus/file.ts b/apps/remixdesktop/src/menus/file.ts new file mode 100644 index 0000000000..37b6331568 --- /dev/null +++ b/apps/remixdesktop/src/menus/file.ts @@ -0,0 +1,28 @@ +import {BrowserWindow, MenuItemConstructorOptions} from 'electron'; + +export default ( + commandKeys: Record, + execCommand: (command: string, focusedWindow?: BrowserWindow) => void +): MenuItemConstructorOptions => { + const isMac = process.platform === 'darwin'; + + return { + label: 'File', + submenu: [ + { + label: 'New Window', + accelerator: commandKeys['window:new'], + click(item, focusedWindow) { + execCommand('window:new', focusedWindow); + } + }, + { + label: 'Open Folder', + accelerator: commandKeys['folder:open'], + click(item, focusedWindow) { + execCommand('folder:open', focusedWindow); + } + } + ] + }; +}; diff --git a/apps/remixdesktop/src/menus/main.ts b/apps/remixdesktop/src/menus/main.ts new file mode 100644 index 0000000000..8fa154eea6 --- /dev/null +++ b/apps/remixdesktop/src/menus/main.ts @@ -0,0 +1,26 @@ +import {BrowserWindow, MenuItemConstructorOptions} from 'electron'; + +export default ( + commandKeys: Record, + execCommand: (command: string, focusedWindow?: BrowserWindow) => void +): MenuItemConstructorOptions => { + const isMac = process.platform === 'darwin'; + + return { + label: 'REMIX', + submenu: [ + { + label: 'Close', + accelerator: commandKeys['pane:close'], + click(item, focusedWindow) { + execCommand('pane:close', focusedWindow); + } + }, + { + label: isMac ? 'Close Window' : 'Quit', + role: 'close', + accelerator: commandKeys['window:close'] + } + ] + }; +}; diff --git a/apps/remixdesktop/src/xtermPlugin.ts b/apps/remixdesktop/src/xtermPlugin.ts index 59e28cc6ee..be61ed7096 100644 --- a/apps/remixdesktop/src/xtermPlugin.ts +++ b/apps/remixdesktop/src/xtermPlugin.ts @@ -14,16 +14,7 @@ const profile: Profile = { export class XtermPlugin extends ElectronBasePlugin { client: PluginClient constructor() { - super(profile) - } - - async createClient(webContentsId: number): Promise { - console.log('createClient', webContentsId) - this.clients.push(new XtermPluginClient(webContentsId)) - } - - async closeClient(webContentsId: number): Promise { - console.log('closeClient', webContentsId) + super(profile, clientProfile, XtermPluginClient) } } @@ -38,8 +29,8 @@ const clientProfile: Profile = { class XtermPluginClient extends ElectronBasePluginClient { terminals: pty.IPty[] = [] - constructor(webContentsId: number) { - super(webContentsId, clientProfile) + constructor(webContentsId: number, profile: Profile) { + super(webContentsId, profile) this.onload(() => { console.log('XtermPluginClient onload') }) diff --git a/libs/remix-ui/workspace/src/lib/actions/events.ts b/libs/remix-ui/workspace/src/lib/actions/events.ts index 5c9b03141c..8da0b74971 100644 --- a/libs/remix-ui/workspace/src/lib/actions/events.ts +++ b/libs/remix-ui/workspace/src/lib/actions/events.ts @@ -49,6 +49,7 @@ export const listenOnPluginEvents = (filePanelPlugin) => { }) plugin.on('fileManager', 'rootFolderChanged', async (path: string) => { + console.log('rootFolderChanged', path) rootFolderChanged(path) }) @@ -96,6 +97,10 @@ export const listenOnProviderEvents = (provider) => (reducerDispatch: React.Disp await switchToWorkspace(workspaceProvider.workspace) }) + provider.event.on('refresh', () => { + fetchWorkspaceDirectory('/') + }) + provider.event.on('connected', () => { plugin.fileManager.setMode('localhost') dispatch(setMode('localhost')) diff --git a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx index c1030be2f2..b7b88e2318 100644 --- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx +++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx @@ -12,6 +12,7 @@ import { MenuItems, WorkSpaceState } from './types' import { contextMenuActions } from './utils' import FileExplorerContextMenu from './components/file-explorer-context-menu' import { customAction } from '@remixproject/plugin-api' +import isElectron from 'is-electron' const _paq = window._paq = window._paq || [] @@ -684,45 +685,66 @@ export function Workspace () {
-
-
- {currentWorkspace !== LOCALHOST ? ( - hideIconsMenu(!showIconsMenu)} show={showIconsMenu}> - { - hideIconsMenu(!showIconsMenu) - }} - icon={'fas fa-bars'} - > - - - - - ) : null} - - - +
+
+ {!isElectron() ? + + + : null} + {currentWorkspace !== LOCALHOST && !isElectron() ? ( + } + > + + + hideIconsMenu(!showIconsMenu)} show={showIconsMenu}> + { + hideIconsMenu(!showIconsMenu) + }} + icon={'fas fa-bars'} + > + + + + + ) : null}
+ {!isElectron() ? ( { switchWorkspace(NO_WORKSPACE) }}>{ NO_WORKSPACE } } + ) : null}
diff --git a/package.json b/package.json index f3edc5bd99..1161e88f53 100644 --- a/package.json +++ b/package.json @@ -134,15 +134,15 @@ "@openzeppelin/contracts": "^4.7.3", "@openzeppelin/upgrades-core": "^1.22.0", "@openzeppelin/wizard": "0.2.0", - "@remixproject/engine": "0.3.36", - "@remixproject/engine-electron": "0.3.36", - "@remixproject/engine-web": "0.3.36", - "@remixproject/plugin": "0.3.36", - "@remixproject/plugin-api": "0.3.36", - "@remixproject/plugin-electron": "0.3.36", - "@remixproject/plugin-utils": "0.3.36", - "@remixproject/plugin-webview": "0.3.36", - "@remixproject/plugin-ws": "0.3.36", + "@remixproject/engine": "0.3.37", + "@remixproject/engine-electron": "0.3.37", + "@remixproject/engine-web": "0.3.37", + "@remixproject/plugin": "0.3.37", + "@remixproject/plugin-api": "0.3.37", + "@remixproject/plugin-electron": "0.3.37", + "@remixproject/plugin-utils": "0.3.37", + "@remixproject/plugin-webview": "0.3.37", + "@remixproject/plugin-ws": "0.3.37", "@types/nightwatch": "^2.3.1", "@walletconnect/ethereum-provider": "^2.6.2", "@walletconnect/sign-client": "^2.6.0", @@ -178,11 +178,12 @@ "http-server": "^14.1.1", "intro.js": "^4.1.0", "isbinaryfile": "^3.0.2", - "isomorphic-git": "^1.8.2", + "isomorphic-git": "^1.24.0", "jquery": "^3.3.1", "js-yaml": "^4.1.0", "jspdf": "^2.5.1", "jszip": "^3.6.0", + "just-once": "^2.2.0", "latest-version": "^5.1.0", "merge": "^2.1.1", "npm-install-version": "^6.0.2", diff --git a/yarn.lock b/yarn.lock index bf87ffdc05..ac23ec798a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5131,82 +5131,82 @@ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.10.2.tgz#0798c03351f0dea1a5a4cabddf26a55a7cbee590" integrity sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ== -"@remixproject/engine-electron@0.3.36": - version "0.3.36" - resolved "https://registry.yarnpkg.com/@remixproject/engine-electron/-/engine-electron-0.3.36.tgz#24304072b102d23ea76d88dd142c28ed991aa46b" - integrity sha512-ueiO48ViKyYgZgZmMreXyEk62cSlAzwukSyXnxI3T4G5ykKL0G461ocK3cSYfTKoZ/g0/j7oUz25I8wXtU3boA== - dependencies: - "@remixproject/engine" "0.3.36" - "@remixproject/plugin-api" "0.3.36" - "@remixproject/plugin-utils" "0.3.36" - -"@remixproject/engine-web@0.3.36": - version "0.3.36" - resolved "https://registry.yarnpkg.com/@remixproject/engine-web/-/engine-web-0.3.36.tgz#105328588fee0eee692f2e64aeb3faf2749ea56c" - integrity sha512-rNYZiEFplg9A3Vfb72zVxqrUE3rVFOss8uBcAhWPt0um8vl7cZ8nRoFc5pxgnvDh+ozRo5YbWR0fqmDA4OiIUw== - dependencies: - "@remixproject/engine" "0.3.36" - "@remixproject/plugin-api" "0.3.36" - "@remixproject/plugin-utils" "0.3.36" - -"@remixproject/engine@0.3.36": - version "0.3.36" - resolved "https://registry.yarnpkg.com/@remixproject/engine/-/engine-0.3.36.tgz#aa93210716ab959b1d39e08ea38c7357495381f3" - integrity sha512-D5sf8WJBS5cbjqZBDWo/hN5kT6YhkZysGy0Y1QWcQj48WhOYHawl6VMExMsqVXtPZzJTWHs2N/hXuoc6MF6xfg== - dependencies: - "@remixproject/plugin-api" "0.3.36" - "@remixproject/plugin-utils" "0.3.36" - -"@remixproject/plugin-api@0.3.36": - version "0.3.36" - resolved "https://registry.yarnpkg.com/@remixproject/plugin-api/-/plugin-api-0.3.36.tgz#58a77184c17ddece59fc2b8e7dd30a92ddb164a2" - integrity sha512-T7/9FAhm499sFbOh/iuK05GRpTZwYJtXrlMUAGE9qhfo4ep62sJg0TLss1BRnfhkDBvlS10rqdF2wWTPQ9JSPA== - dependencies: - "@remixproject/plugin-utils" "0.3.36" - -"@remixproject/plugin-electron@0.3.36": - version "0.3.36" - resolved "https://registry.yarnpkg.com/@remixproject/plugin-electron/-/plugin-electron-0.3.36.tgz#4b0067f3b42454f95625ed774a10751a6557b3ee" - integrity sha512-WM4u4zUs95adZxbC/GrMzfuCXfBde9TuoPeS2Nb9ysRQKj5eRfTIWiYrh9PxoezrEF8EYPo8gVrf9A+PGlKf3w== - dependencies: - "@remixproject/engine" "0.3.36" - "@remixproject/plugin" "0.3.36" - "@remixproject/plugin-api" "0.3.36" - "@remixproject/plugin-utils" "0.3.36" - -"@remixproject/plugin-utils@0.3.36": - version "0.3.36" - resolved "https://registry.yarnpkg.com/@remixproject/plugin-utils/-/plugin-utils-0.3.36.tgz#92478cd820e23b42a911a3e6e3f88d759f34d395" - integrity sha512-gbTzp3rHVITVn45vgb/f+huo6C/zogUCTmzqOj+D9INaQR1Fr6XtOL8erKjD0pNBbyw3lxpRsDKEpRQVE7sMbg== +"@remixproject/engine-electron@0.3.37": + version "0.3.37" + resolved "https://registry.yarnpkg.com/@remixproject/engine-electron/-/engine-electron-0.3.37.tgz#5e14bcf08201603cfccff0761d6f8612b1f3d62f" + integrity sha512-XQea0a5SPtYtOl1XH8qu9AN+Fkc/LSZ8FYuxenFUeczqy9t4gxlPibLrCQXSlrcNEdoGhDE/DW/wltQoX8JLtg== + dependencies: + "@remixproject/engine" "0.3.37" + "@remixproject/plugin-api" "0.3.37" + "@remixproject/plugin-utils" "0.3.37" + +"@remixproject/engine-web@0.3.37": + version "0.3.37" + resolved "https://registry.yarnpkg.com/@remixproject/engine-web/-/engine-web-0.3.37.tgz#cb9e09a135f9083202207039b2f5104278d4db1b" + integrity sha512-9FcJOm5xMOta5DE/JVMu2TnGcJpoe6MagG/NC89QrxJq8mCQSDgiFeSfqJhgFXye/hjlCmaO96aLgXIeoXMhWQ== + dependencies: + "@remixproject/engine" "0.3.37" + "@remixproject/plugin-api" "0.3.37" + "@remixproject/plugin-utils" "0.3.37" + +"@remixproject/engine@0.3.37": + version "0.3.37" + resolved "https://registry.yarnpkg.com/@remixproject/engine/-/engine-0.3.37.tgz#995abd53c505f6f37eaa6550d81ec36f2e60d106" + integrity sha512-+dO32Bdgm2GLlamCnCWIPYX0v57Ft2vWGkFwXil1xiLvPttVOjnSPkqz9Xu0DAqDIqXIr4A15E2pHklVR+shLQ== + dependencies: + "@remixproject/plugin-api" "0.3.37" + "@remixproject/plugin-utils" "0.3.37" + +"@remixproject/plugin-api@0.3.37": + version "0.3.37" + resolved "https://registry.yarnpkg.com/@remixproject/plugin-api/-/plugin-api-0.3.37.tgz#2b5c628f81632bb0063e4c6afbce62085d20e883" + integrity sha512-bJ8oIpaI4qP3/Ku7jxXW3XRkTyQ2hjWX6N8yob3d/jjHtaJ/IorDx/vieGXQoJTPKAMPol0KVKCVCxx+xmzcUQ== + dependencies: + "@remixproject/plugin-utils" "0.3.37" + +"@remixproject/plugin-electron@0.3.37": + version "0.3.37" + resolved "https://registry.yarnpkg.com/@remixproject/plugin-electron/-/plugin-electron-0.3.37.tgz#e850b6aae55af1e7b0cd74f4583e8eeb946735ce" + integrity sha512-ZmkYLk9LEewPCqXIiMPJC8ZpgRjMW3dh2LbgeSGhKG0ly8pD5VuZj3/07iP/ZvjDNuTliX08gqvCru9/oOskqA== + dependencies: + "@remixproject/engine" "0.3.37" + "@remixproject/plugin" "0.3.37" + "@remixproject/plugin-api" "0.3.37" + "@remixproject/plugin-utils" "0.3.37" + +"@remixproject/plugin-utils@0.3.37": + version "0.3.37" + resolved "https://registry.yarnpkg.com/@remixproject/plugin-utils/-/plugin-utils-0.3.37.tgz#7068523398164976c2470f55837e93c6fa210489" + integrity sha512-Ow4gFf15ym7Sysza4hx4+QEYQHvluu0pDEj3GlNAMWAbvbjBGxb7O81b3Tvu7n8ywESYJlbIifNr++vYY63+PQ== dependencies: tslib "2.0.1" -"@remixproject/plugin-webview@0.3.36": - version "0.3.36" - resolved "https://registry.yarnpkg.com/@remixproject/plugin-webview/-/plugin-webview-0.3.36.tgz#38997745608952cc40ce5c668d0836d0d5279b12" - integrity sha512-9C/GQLDQzzX6g8MH9L54C+K/2FxBa4tCdlxUbPH9infTFvk/jcMjpd/CSAIBK4EfZCs1mL+1Opc8bX3VrfchpA== +"@remixproject/plugin-webview@0.3.37": + version "0.3.37" + resolved "https://registry.yarnpkg.com/@remixproject/plugin-webview/-/plugin-webview-0.3.37.tgz#b38882fc8f05ba22405c0baa4bef9662652fec1a" + integrity sha512-LeKS05MXnVUM4xS9IUmKBE5HJzs3L5hvuqWcRosB6ASbhzzFu4h7zeDtBbjSK46dL6/3Ym/dDqdJM9e6I+Gltw== dependencies: - "@remixproject/plugin" "0.3.36" - "@remixproject/plugin-api" "0.3.36" - "@remixproject/plugin-utils" "0.3.36" + "@remixproject/plugin" "0.3.37" + "@remixproject/plugin-api" "0.3.37" + "@remixproject/plugin-utils" "0.3.37" axios "^0.21.1" -"@remixproject/plugin-ws@0.3.36": - version "0.3.36" - resolved "https://registry.yarnpkg.com/@remixproject/plugin-ws/-/plugin-ws-0.3.36.tgz#a80ccf5e7ae866bc53a79a7da4f36b67a0a33972" - integrity sha512-+vGwHd7KAgGsPoPph8T5mGkGthJagtwsb53LopZwbwDziMEWP7IVu44TcI46qR/+oBHLm0MmH1ukCzRAkbDu+w== +"@remixproject/plugin-ws@0.3.37": + version "0.3.37" + resolved "https://registry.yarnpkg.com/@remixproject/plugin-ws/-/plugin-ws-0.3.37.tgz#1f29d037a1743eb8b3da438f8a9dbdb3d322b9a4" + integrity sha512-fjGBrj3qP0UnraiG/opzMySxk0SdfABrx1PuM8f3c3tmZDdjTrVcsJ11NlNNvztOPkyY5fL4e2gXDUkpELKztg== dependencies: - "@remixproject/plugin" "0.3.36" - "@remixproject/plugin-api" "0.3.36" - "@remixproject/plugin-utils" "0.3.36" + "@remixproject/plugin" "0.3.37" + "@remixproject/plugin-api" "0.3.37" + "@remixproject/plugin-utils" "0.3.37" -"@remixproject/plugin@0.3.36": - version "0.3.36" - resolved "https://registry.yarnpkg.com/@remixproject/plugin/-/plugin-0.3.36.tgz#393867208ace117c8dbfd08adb4d5feec1b17d4b" - integrity sha512-+lFgfLI3vbiB6OQIkeX2Yx1EyKdIUGU1lJ7K51HwPfbGet5Y4w8qDMXBblRM1HhVe7bDYlBOzzbcil8/03Dsnw== +"@remixproject/plugin@0.3.37": + version "0.3.37" + resolved "https://registry.yarnpkg.com/@remixproject/plugin/-/plugin-0.3.37.tgz#d7b41a7fd03d712717eeb44526399e6c6ce6647c" + integrity sha512-3DgGCPE78ThfqGUJlrWwdArRol2nLZMBHTZpPxLE9K4tpspY7G1KV8HLB55mkX/uPVvVbNTRoFI4TNm87Jjiwg== dependencies: - "@remixproject/plugin-api" "0.3.36" - "@remixproject/plugin-utils" "0.3.36" + "@remixproject/plugin-api" "0.3.37" + "@remixproject/plugin-utils" "0.3.37" events "3.2.0" "@restart/context@^2.1.4": @@ -18344,6 +18344,11 @@ just-once@1.1.0: resolved "https://registry.yarnpkg.com/just-once/-/just-once-1.1.0.tgz#fe81a185ebaeeb0947a7e705bf01cb6808db0ad8" integrity sha512-+rZVpl+6VyTilK7vB/svlMPil4pxqIJZkbnN7DKZTOzyXfun6ZiFeq2Pk4EtCEHZ0VU4EkdFzG8ZK5F3PErcDw== +just-once@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/just-once/-/just-once-2.2.0.tgz#e8ebc8c80838d0fdb0d3c888f1591d88ad4be4d7" + integrity sha512-Wo547FgUOUZ98jbrZ1KX8nRezdEdtgIlC2NK1u1RvR1oZ/WoU++FjprP8J8hRbaox776MHyeMZZED4DvhhHVjg== + keccak@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0"