diff --git a/apps/remix-ide-e2e/src/tests/generalSettings.test.ts b/apps/remix-ide-e2e/src/tests/generalSettings.test.ts
index 30346994bc..f36d042950 100644
--- a/apps/remix-ide-e2e/src/tests/generalSettings.test.ts
+++ b/apps/remix-ide-e2e/src/tests/generalSettings.test.ts
@@ -19,7 +19,7 @@ module.exports = {
browser.waitForElementVisible('*[data-id="remixIdeSidePanel"]', 5000)
.waitForElementVisible('*[data-id="settingsTabGenerateContractMetadataLabel"]', 5000)
.verify.elementPresent('[data-id="settingsTabGenerateContractMetadata"]:checked')
- .click('*[data-id="verticalIconsFileExplorerIcons"]')
+ .click('*[data-id="verticalIconsKindfilePanel"]')
.click('[data-id="treeViewLitreeViewItemcontracts"]')
.openFile('contracts/3_Ballot.sol')
.click('*[data-id="verticalIconsKindsolidity"]')
diff --git a/apps/remix-ide/src/app.js b/apps/remix-ide/src/app.js
index d327647549..71360c1e9d 100644
--- a/apps/remix-ide/src/app.js
+++ b/apps/remix-ide/src/app.js
@@ -225,8 +225,8 @@ class AppComponent {
self.engine.register([appPanel, tabProxy])
// those views depend on app_manager
- self.menuicons = new VerticalIcons(appManager)
- self.sidePanel = new SidePanel(appManager, self.menuicons)
+ self.menuicons = new VerticalIcons()
+ self.sidePanel = new SidePanel()
self.hiddenPanel = new HiddenPanel()
const pluginManagerComponent = new PluginManagerComponent(
diff --git a/apps/remix-ide/src/app/components/panel.ts b/apps/remix-ide/src/app/components/panel.ts
index a5747188af..3b3bd6d33b 100644
--- a/apps/remix-ide/src/app/components/panel.ts
+++ b/apps/remix-ide/src/app/components/panel.ts
@@ -49,8 +49,7 @@ export class AbstractPanel extends HostPlugin {
* @param {String} name The name of the plugin to display the content
*/
showContent (name) {
- if (!this.plugins[name]) throw new Error(`Plugin ${name} is not yet activated`)
-
+ if (!this.plugins[name]) throw new Error(`Plugin ${name} is not yet activated`)
Object.values(this.plugins).forEach(plugin => {
plugin.active = false
})
diff --git a/apps/remix-ide/src/app/components/side-panel.tsx b/apps/remix-ide/src/app/components/side-panel.tsx
index 8b64d64e45..b5e9dcd3df 100644
--- a/apps/remix-ide/src/app/components/side-panel.tsx
+++ b/apps/remix-ide/src/app/components/side-panel.tsx
@@ -4,8 +4,6 @@ import ReactDOM from 'react-dom'
import { AbstractPanel } from './panel'
import { RemixPluginPanel } from '@remix-ui/panel'
import packageJson from '../../../../../package.json'
-import { RemixAppManager } from '../../remixAppManager'
-import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
import RemixUIPanelHeader from 'libs/remix-ui/panel/src/lib/plugins/panel-header'
// const csjs = require('csjs-inject')
@@ -17,20 +15,18 @@ const sidePanel = {
methods: ['addView', 'removeView']
}
-// TODO merge with vertical-icons.js
export class SidePanel extends AbstractPanel {
- appManager: RemixAppManager
sideelement: any
- verticalIcons: VerticalIcons;
- constructor (appManager: RemixAppManager, verticalIcons: VerticalIcons) {
+ constructor() {
super(sidePanel)
- this.appManager = appManager
this.sideelement = document.createElement('section')
this.sideelement.setAttribute('class', 'panel plugin-manager')
- this.verticalIcons = verticalIcons
+ }
+ onActivation() {
+ this.renderComponent()
// Toggle content
- verticalIcons.events.on('toggleContent', (name) => {
+ this.on('menuicons', 'toggleContent', (name) => {
if (!this.plugins[name]) return
if (this.plugins[name].active) {
// TODO: Only keep `this.emit` (issue#2210)
@@ -44,7 +40,7 @@ export class SidePanel extends AbstractPanel {
this.events.emit('showing', name)
})
// Force opening
- verticalIcons.events.on('showContent', (name) => {
+ this.on('menuicons', 'showContent', (name) => {
if (!this.plugins[name]) return
this.showContent(name)
// TODO: Only keep `this.emit` (issue#2210)
@@ -53,25 +49,22 @@ export class SidePanel extends AbstractPanel {
})
}
- onActivation () {
- this.renderComponent()
- }
-
- focus (name) {
+ focus(name) {
this.emit('focusChanged', name)
super.focus(name)
}
- removeView (profile) {
+ removeView(profile) {
+ if (this.plugins[profile.name].active) this.call('menuicons', 'select', 'filePanel')
super.removeView(profile)
this.emit('pluginDisabled', profile.name)
this.call('menuicons', 'unlinkContent', profile)
this.renderComponent()
}
- addView (profile, view) {
+ addView(profile, view) {
super.addView(profile, view)
- this.verticalIcons.linkContent(profile)
+ this.call('menuicons', 'linkContent', profile)
this.renderComponent()
}
@@ -79,17 +72,17 @@ export class SidePanel extends AbstractPanel {
* Display content and update the header
* @param {String} name The name of the plugin to display
*/
- async showContent (name) {
+ async showContent(name) {
super.showContent(name)
this.emit('focusChanged', name)
this.renderComponent()
}
- render () {
+ render() {
return this.sideelement
}
- renderComponent () {
- ReactDOM.render(} plugins={this.plugins}/>, this.sideelement)
+ renderComponent() {
+ ReactDOM.render(} plugins={this.plugins} />, this.sideelement)
}
}
diff --git a/apps/remix-ide/src/app/components/vertical-icons.js b/apps/remix-ide/src/app/components/vertical-icons.js
deleted file mode 100644
index c458e9e5ef..0000000000
--- a/apps/remix-ide/src/app/components/vertical-icons.js
+++ /dev/null
@@ -1,110 +0,0 @@
-import * as packageJson from '../../../../../package.json'
-import ReactDOM from 'react-dom'
-import React from 'react' // eslint-disable-line
-// eslint-disable-next-line no-unused-vars
-import { RemixUiVerticalIconsPanel } from '@remix-ui/vertical-icons-panel'
-import Registry from '../state/registry'
-const { Plugin } = require('@remixproject/engine')
-const EventEmitter = require('events')
-
-const profile = {
- name: 'menuicons',
- displayName: 'Vertical Icons',
- description: '',
- version: packageJson.version,
- methods: ['select', 'unlinkContent']
-}
-
-// TODO merge with side-panel.js. VerticalIcons should not be a plugin
-export class VerticalIcons extends Plugin {
- constructor (appManager) {
- super(profile)
- this.events = new EventEmitter()
- this.appManager = appManager
- this.htmlElement = document.createElement('div')
- this.htmlElement.setAttribute('id', 'icon-panel')
- this.icons = {}
- this.iconKind = {}
- this.iconStatus = {}
- this.defaultProfile = profile
- this.targetProfileForChange = {}
- this.targetProfileForRemoval = {}
- this.registry = Registry.getInstance()
- this.keys = ['succeed', 'edited', 'none', 'loading', 'failed']
- this.types = ['error', 'warning', 'success', 'info', '']
- }
-
- renderComponent () {
- ReactDOM.render(
- ,
- this.htmlElement)
- }
-
- onActivation () {
- this.renderComponent()
- }
-
- linkContent (profile) {
- if (!profile.icon) return
- if (!profile.kind) profile.kind = 'none'
- this.targetProfileForChange[profile.name] = profile
- this.listenOnStatus(profile)
- this.renderComponent()
- }
-
- unlinkContent (profile) {
- this.targetProfileForRemoval = profile
- this.removeIcon(profile)
- this.renderComponent()
- }
-
- listenOnStatus (profile) {
-
- }
-
- /**
- * Remove an icon from the map
- * @param {ModuleProfile} profile The profile of the module
- */
- removeIcon ({ name }) {
- if (this.targetProfileForChange[name]) delete this.targetProfileForChange[name]
- setTimeout(() => {
- this.renderComponent()
- }, 150)
- }
-
- /**
- * Set an icon as active
- * @param {string} name Name of profile of the module to activate
- */
- select (name) {
- // TODO: Only keep `this.emit` (issue#2210)
- this.emit('showContent', name)
- this.events.emit('showContent', name)
- }
-
- onThemeChanged (themeType) {
- const invert = themeType === 'dark' ? 1 : 0
- const active = this.view.querySelector('.active')
- if (active) {
- const image = active.querySelector('.image')
- image.style.setProperty('filter', `invert(${invert})`)
- }
- }
-
- /**
- * Toggles the side panel for plugin
- * @param {string} name Name of profile of the module to activate
- */
- toggle (name) {
- // TODO: Only keep `this.emit` (issue#2210)
- this.emit('toggleContent', name)
- this.events.emit('toggleContent', name)
- }
-
- render () {
- return this.htmlElement
- }
-}
diff --git a/apps/remix-ide/src/app/components/vertical-icons.tsx b/apps/remix-ide/src/app/components/vertical-icons.tsx
new file mode 100644
index 0000000000..2e8deaa182
--- /dev/null
+++ b/apps/remix-ide/src/app/components/vertical-icons.tsx
@@ -0,0 +1,116 @@
+// eslint-disable-next-line no-use-before-define
+import React from 'react'
+import ReactDOM from 'react-dom'
+import Registry from '../state/registry'
+import packageJson from '../../../../../package.json'
+import { Plugin } from '@remixproject/engine'
+import { EventEmitter } from 'events'
+import { IconRecord, RemixUiVerticalIconsPanel } from '@remix-ui/vertical-icons-panel'
+import { Profile } from '@remixproject/plugin-utils'
+import { timeStamp } from 'console'
+
+const profile = {
+ name: 'menuicons',
+ displayName: 'Vertical Icons',
+ description: '',
+ version: packageJson.version,
+ methods: ['select', 'unlinkContent', 'linkContent'],
+ events: ['toggleContent', 'showContent']
+}
+
+export class VerticalIcons extends Plugin {
+ events: EventEmitter
+ htmlElement: HTMLDivElement
+ icons: Record = {}
+ constructor () {
+ super(profile)
+ this.events = new EventEmitter()
+ this.htmlElement = document.createElement('div')
+ this.htmlElement.setAttribute('id', 'icon-panel')
+ }
+
+ renderComponent () {
+ const fixedOrder = ['filePanel', 'solidity','udapp', 'debugger', 'solidityStaticAnalysis', 'solidityUnitTesting', 'pluginManager']
+
+ const divived = Object.values(this.icons).map((value) => { return {
+ ...value,
+ isRequired: fixedOrder.indexOf(value.profile.name) > -1
+ }}).sort((a,b) => {
+ return a.timestamp - b.timestamp
+ })
+
+ const required = divived.filter((value) => value.isRequired).sort((a,b) => {
+ return fixedOrder.indexOf(a.profile.name) - fixedOrder.indexOf(b.profile.name)
+ })
+
+ const sorted: IconRecord[] = [
+ ...required,
+ ...divived.filter((value) => { return !value.isRequired })
+ ]
+
+ ReactDOM.render(
+ ,
+ this.htmlElement)
+ }
+
+ onActivation () {
+ this.renderComponent()
+ this.on('sidePanel', 'focusChanged', (name: string) => {
+ Object.keys(this.icons).map((o) => {
+ this.icons[o].active = false
+ })
+ this.icons[name].active = true
+ this.renderComponent()
+ })
+ }
+
+ async linkContent (profile: Profile) {
+ if (!profile.icon) return
+ if (!profile.kind) profile.kind = 'none'
+ this.icons[profile.name] = {
+ profile: profile,
+ active: false,
+ canbeDeactivated: await this.call('manager', 'canDeactivate', this.profile, profile),
+ timestamp: Date.now()
+ }
+ this.renderComponent()
+ }
+
+ unlinkContent (profile: Profile) {
+ delete this.icons[profile.name]
+ this.renderComponent()
+ }
+
+ async activateHome() {
+ await this.call('manager', 'activatePlugin', 'home')
+ await this.call('tabs', 'focus', 'home')
+ }
+
+ /**
+ * Set an icon as active
+ * @param {string} name Name of profile of the module to activate
+ */
+ select (name: string) {
+ // TODO: Only keep `this.emit` (issue#2210)
+ console.log(name, this)
+ this.emit('showContent', name)
+ this.events.emit('showContent', name)
+ }
+
+ /**
+ * Toggles the side panel for plugin
+ * @param {string} name Name of profile of the module to activate
+ */
+ toggle (name: string) {
+ // TODO: Only keep `this.emit` (issue#2210)
+ this.emit('toggleContent', name)
+ this.events.emit('toggleContent', name)
+ }
+
+ render () {
+ return this.htmlElement
+ }
+}
diff --git a/apps/remix-ide/src/remixAppManager.js b/apps/remix-ide/src/remixAppManager.js
index d3cc735b3f..7967336579 100644
--- a/apps/remix-ide/src/remixAppManager.js
+++ b/apps/remix-ide/src/remixAppManager.js
@@ -50,6 +50,10 @@ export class RemixAppManager extends PluginManager {
return isNative(from.name)
}
+ async canDeactivate(from,to) {
+ return this.canDeactivatePlugin(from, to)
+ }
+
async deactivatePlugin (name) {
const [to, from] = [
await this.getProfile(name),
diff --git a/apps/remix-ide/src/walkthroughService.js b/apps/remix-ide/src/walkthroughService.js
index e68da1b421..b9ffab4416 100644
--- a/apps/remix-ide/src/walkthroughService.js
+++ b/apps/remix-ide/src/walkthroughService.js
@@ -31,7 +31,7 @@ export class WalkthroughService extends Plugin {
position: 'right'
},
{
- element: document.querySelector('#compileIcons'),
+ element: document.querySelector('#verticalIconsKindsolidity'),
title: 'Solidity Compiler',
intro: 'Having selected a .sol file in the File Explorers (the icon above), compile it with the Solidity Compiler.',
tooltipClass: 'bg-light text-dark',
diff --git a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.css b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.css
index 54c71b16c5..4464c8d2fa 100644
--- a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.css
+++ b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.css
@@ -36,7 +36,7 @@
.remixui_home_rightPanel {
right: 0;
position: absolute;
- z-index: 3;
+ z-index: 3000;
}
.remixui_home_remixHomeMedia {
overflow-y: auto;
diff --git a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx
index ecbca46eb7..73bd4f0357 100644
--- a/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx
+++ b/libs/remix-ui/home-tab/src/lib/remix-ui-home-tab.tsx
@@ -80,6 +80,7 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => {
const remiAudioEl = useRef(null)
const inputValue = useRef(null)
+ const rightPanel = useRef(null)
useEffect(() => {
plugin.call('theme', 'currentTheme').then((theme) => {
@@ -97,7 +98,7 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => {
window.addEventListener('click', (event) => {
const target = event.target as Element
const id = target.id
- if (id !== 'remixIDEHomeTwitterbtn' && id !== 'remixIDEHomeMediumbtn') {
+ if (id !== 'remixIDEHomeTwitterbtn' && id !== 'remixIDEHomeMediumbtn' && !rightPanel.current.contains(event.target)) {
// todo check event.target
setState(prevState => { return { ...prevState, showMediaPanel: 'none' } })
}
@@ -266,7 +267,7 @@ export const RemixUiHomeTab = (props: RemixUiHomeTabProps) => {
-