pull/5370/head
bunsenstraat 3 years ago
parent 462bf41fd2
commit 959def2783
  1. 4
      apps/remix-ide/src/app.js
  2. 3
      apps/remix-ide/src/app/components/panel.ts
  3. 36
      apps/remix-ide/src/app/components/side-panel.tsx
  4. 115
      apps/remix-ide/src/app/components/vertical-icons.js
  5. 117
      apps/remix-ide/src/app/components/vertical-icons.tsx
  6. 4
      apps/remix-ide/src/remixAppManager.js
  7. 2
      libs/remix-ui/panel/src/lib/types/index.ts
  8. 20
      libs/remix-ui/vertical-icons-panel/.eslintrc.json
  9. 3
      libs/remix-ui/vertical-icons-panel/src/index.ts
  10. 11
      libs/remix-ui/vertical-icons-panel/src/lib/components/Badge.tsx
  11. 2
      libs/remix-ui/vertical-icons-panel/src/lib/components/BasicLogo.tsx
  12. 4
      libs/remix-ui/vertical-icons-panel/src/lib/components/Chevron.tsx
  13. 41
      libs/remix-ui/vertical-icons-panel/src/lib/components/Debugger.tsx
  14. 59
      libs/remix-ui/vertical-icons-panel/src/lib/components/FilePanel.tsx
  15. 7
      libs/remix-ui/vertical-icons-panel/src/lib/components/Home.tsx
  16. 65
      libs/remix-ui/vertical-icons-panel/src/lib/components/Icon.tsx
  17. 33
      libs/remix-ui/vertical-icons-panel/src/lib/components/IconList.tsx
  18. 43
      libs/remix-ui/vertical-icons-panel/src/lib/components/OtherIcons.tsx
  19. 36
      libs/remix-ui/vertical-icons-panel/src/lib/components/PluginManager.tsx
  20. 73
      libs/remix-ui/vertical-icons-panel/src/lib/components/RequiredSection.tsx
  21. 61
      libs/remix-ui/vertical-icons-panel/src/lib/components/Settings.tsx
  22. 41
      libs/remix-ui/vertical-icons-panel/src/lib/components/Solidity.tsx
  23. 41
      libs/remix-ui/vertical-icons-panel/src/lib/components/SolidityStaticAnalysis.tsx
  24. 42
      libs/remix-ui/vertical-icons-panel/src/lib/components/Udapp.tsx
  25. 29
      libs/remix-ui/vertical-icons-panel/src/lib/reducers/iconBadgeReducer.ts
  26. 3
      libs/remix-ui/vertical-icons-panel/src/lib/reducers/verticalScrollReducer.ts
  27. 10
      libs/remix-ui/vertical-icons-panel/src/lib/remix-ui-vertical-icons-panel.css
  28. 10
      libs/remix-ui/vertical-icons-panel/src/lib/types/index.ts
  29. 46
      libs/remix-ui/vertical-icons-panel/src/lib/vertical-icons-context-menu.tsx
  30. 12
      libs/remix-ui/vertical-icons-panel/tsconfig.json
  31. 3
      libs/remix-ui/vertical-icons-panel/tsconfig.lib.json
  32. 111
      libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel.d.ts

@ -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(

@ -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
})

@ -5,7 +5,6 @@ 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')
@ -19,18 +18,17 @@ const sidePanel = {
// 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 +42,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,26 +51,22 @@ export class SidePanel extends AbstractPanel {
})
}
onActivation () {
this.renderComponent()
}
focus (name) {
focus(name) {
this.emit('focusChanged', name)
super.focus(name)
}
removeView (profile) {
if(this.plugins[profile.name].active) this.call('menuicons', 'select', 'filePanel')
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()
}
@ -80,17 +74,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(<RemixPluginPanel header={<RemixUIPanelHeader plugins={this.plugins}></RemixUIPanelHeader>} plugins={this.plugins}/>, this.sideelement)
renderComponent() {
ReactDOM.render(<RemixPluginPanel header={<RemixUIPanelHeader plugins={this.plugins}></RemixUIPanelHeader>} plugins={this.plugins} />, this.sideelement)
}
}

@ -1,115 +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(
<RemixUiVerticalIconsPanel
verticalIconsPlugin={this}
/>,
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) {
}
async activateHome() {
await this.call('manager', 'activatePlugin', 'home')
await this.call('tabs', 'focus', 'home')
}
/**
* 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
}
}

@ -0,0 +1,117 @@
// 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']
}
// TODO merge with side-panel.js. VerticalIcons should not be a plugin
export class VerticalIcons extends Plugin {
events: EventEmitter
htmlElement: HTMLDivElement
icons: Record<string, IconRecord> = {}
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(
<RemixUiVerticalIconsPanel
verticalIconsPlugin={this}
icons={sorted}
/>,
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
}
}

@ -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),

@ -6,4 +6,4 @@ export type PluginRecord = {
active: boolean
class?: string
minimized?: boolean
}
}

@ -1,19 +1,19 @@
{
"env": {
"browser": true,
"es6": true
"browser": true,
"es6": true
},
"extends": ["../../../.eslintrc"],
"ignorePatterns": ["!**/*"],
"extends": "../../../.eslintrc.json",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 11,
"sourceType": "module"
"ecmaVersion": 11,
"sourceType": "module"
},
"rules": {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error"
"standard/no-callback-literal": "off"
}
}
}

@ -1 +1,2 @@
export * from './lib/remix-ui-vertical-icons-panel'
export { default as RemixUiVerticalIconsPanel } from './lib/remix-ui-vertical-icons-panel'
export { IconRecord } from './lib/types'

@ -1,10 +1,5 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
// eslint-disable-next-line no-use-before-define
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
// eslint-disable-next-line no-use-before-define
import React, { Fragment, useEffect, useReducer } from 'react'
import { iconBadgeReducer, IconBadgeReducerAction } from '../reducers/iconBadgeReducer'
import { BadgeStatus, IconProfile, IconStatus } from './Icon'
import React from 'react'
import { BadgeStatus } from './Icon'
interface BadgeProps {
badgeStatus?: BadgeStatus
@ -65,4 +60,4 @@ function Badge ({ badgeStatus }: BadgeProps) {
)
}
export default Badge
export default Badge

@ -1,5 +1,3 @@
/* eslint-disable no-use-before-define */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import React from 'react'
function BasicLogo () {

@ -10,9 +10,9 @@ export interface ChevronProps {
function Chevron (props: ChevronProps) {
const click = () => {
if (props.direction === 'down') {
props.divElementRef.current.scrollBy(0, 40)
props.divElementRef.current.scrollBy({ top: 40, behavior: 'smooth' })
} else {
props.divElementRef.current.scrollBy(0, -40)
props.divElementRef.current.scrollBy({ top: -40, behavior: 'smooth' })
}
}

@ -1,41 +0,0 @@
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
// eslint-disable-next-line no-use-before-define
import React, { Fragment } from 'react'
import Icon from './Icon'
interface DebuggerProps {
verticalIconsPlugin: VerticalIcons
itemContextAction: (e: any, name: string, documentation: string) => Promise<void>
addActive: (name: string) => void
removeActive: () => void
}
function Debugger ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: DebuggerProps) {
return (
<Fragment>
{verticalIconsPlugin.targetProfileForChange &&
Object.keys(verticalIconsPlugin.targetProfileForChange).length
? Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p === 'debugger')
.map(p => (
<div id="debuggingIcons" data-id="verticalIconsDebuggingIcons" key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}>
<Icon
profile={verticalIconsPlugin.targetProfileForChange[p]}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
/>
</div>
))
: null}
</Fragment>
)
}
export default Debugger

@ -1,59 +0,0 @@
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
// eslint-disable-next-line no-use-before-define
import React, { Fragment, useEffect, useRef } from 'react'
import Icon from './Icon'
interface FilePanelProps {
verticalIconsPlugin: VerticalIcons
itemContextAction: (e: any, name: string, documentation: string) => Promise<void>
addActive: (name: string) => void
removeActive: () => void
}
function FilePanel ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: FilePanelProps) {
const filePanelRef = useRef(null)
function onThemeChanged (themeType: any) {
const invert = themeType === 'dark' ? 1 : 0
// @ts-ignore
const active = filePanelRef.current && filePanelRef.current.querySelector('.active')
if (active) {
// @ts-ignore
const image = filePanelRef.current.querySelector('.remixui_image')
image.style.setProperty('filter', `invert(${invert})`)
}
}
useEffect(() => {
const themeModule = verticalIconsPlugin.registry.get('themeModule').api
themeModule.events.on('themeChanged', (theme: any) => {
onThemeChanged(theme.quality)
})
}, [])
return (
<Fragment>
{verticalIconsPlugin.targetProfileForChange &&
Object.keys(verticalIconsPlugin.targetProfileForChange).length
? Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p === 'filePanel')
.map(p => (
<div id="fileExplorerIcons" key={
verticalIconsPlugin.targetProfileForChange[p].displayName
} data-id="verticalIconsFileExplorerIcons"
ref={filePanelRef}
>
<Icon
profile={verticalIconsPlugin.targetProfileForChange[p]}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
/>
</div>
))
: null}
</Fragment>
)
}
export default FilePanel

@ -1,10 +1,7 @@
/* eslint-disable no-use-before-define */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
import React, { ReactNode } from 'react'
import React from 'react'
import BasicLogo from './BasicLogo'
interface HomeProps {
verticalIconPlugin: VerticalIcons
verticalIconPlugin: any
}
function Home ({ verticalIconPlugin }: HomeProps) {

@ -1,9 +1,10 @@
import VerticalIconsContextMenu from '../vertical-icons-context-menu'
// eslint-disable-next-line no-use-before-define
import React, { Fragment, SyntheticEvent, useEffect, useReducer, useRef, useState } from 'react'
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
import Badge from './Badge'
import { iconBadgeReducer, IconBadgeReducerAction } from '../reducers/iconBadgeReducer'
import { Plugin } from '@remixproject/engine'
import { IconRecord } from '../types'
export interface IconStatus {
key: string
@ -16,26 +17,11 @@ export interface BadgeStatus extends IconStatus {
text: string
}
export interface IconProfile {
description: string
displayName: string
documentation: string
events: any[]
icon: string
kind: string
location: string
methods: string[]
name: string
version: string
tooltip?: string
}
interface IconProps {
verticalIconPlugin: VerticalIcons
profile: IconProfile
verticalIconPlugin: Plugin
iconRecord: IconRecord
contextMenuAction: (evt: any, profileName: string, documentation: string) => void
addActive: (profileName: string) => void
removeActive: () => void
theme: string
}
const initialState = {
@ -46,18 +32,15 @@ const initialState = {
pluginName: ''
}
function Icon ({
profile,
const Icon = ({
iconRecord,
verticalIconPlugin,
contextMenuAction,
addActive,
removeActive
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}: IconProps) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { tooltip, displayName, name, kind, icon, documentation } = profile
theme
}: IconProps) => {
const { displayName, name, icon, documentation } = iconRecord.profile
const [title] = useState(() => {
const temp = tooltip || displayName || name
const temp = null || displayName || name
return temp.replace(/^\w/, (word: string) => word.toUpperCase())
})
const [links, setLinks] = useState<{ Documentation: string, CanDeactivate: boolean }>(
@ -71,11 +54,9 @@ function Icon ({
const [showContext, setShowContext] = useState(false)
const [canDeactivate] = useState(false)
const iconRef = useRef<any>(null)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const handleContextMenu = (e: SyntheticEvent & PointerEvent) => {
const deactivationState = verticalIconPlugin.appManager
.canDeactivatePlugin(verticalIconPlugin.defaultProfile, { name })
const deactivationState = iconRecord.canbeDeactivated
if (documentation && documentation.length > 0 && deactivationState) {
setLinks({ Documentation: documentation, CanDeactivate: deactivationState })
} else {
@ -102,21 +83,12 @@ function Icon ({
}, [])
return (
<Fragment>
<>
<div
className={name === 'pluginManager' ? 'remixui_icon ml-2 mt-2 mr-2 mb-0 pl-1' : 'remixui_icon m-2 pl-1'}
onLoad={() => {
if (name === 'filePanel') {
addActive(name)
}
}}
className={`remixui_icon m-2 pl-1`}
onClick={() => {
removeActive()
addActive(name)
verticalIconPlugin.toggle(name)
(verticalIconPlugin as any).toggle(name)
}}
// @ts-ignore
plugin={name}
title={title}
onContextMenu={(e: any) => {
e.preventDefault()
@ -127,11 +99,10 @@ function Icon ({
id={`verticalIconsKind${name}`}
ref={iconRef}
>
<img className="remixui_image" src={icon} alt={name} />
{ badgeStatus && badgeStatus.pluginName === name ? (
<img className={`${theme === 'dark' ? 'invert' : ''} ${theme} remixui_image ${iconRecord.active ? `selected-${theme}`:''}`} src={icon} alt={name} />
<Badge
badgeStatus={badgeStatus}
/>) : null }
/>
</div>
{showContext ? (
<VerticalIconsContextMenu
@ -145,7 +116,7 @@ function Icon ({
contextMenuAction={contextMenuAction}
/>
) : null}
</Fragment>
</>
)
}

@ -0,0 +1,33 @@
/* eslint-disable no-use-before-define */
/* eslint-disable @typescript-eslint/no-unused-vars */
import React, { useEffect } from 'react'
import { IconRecord } from '../types'
import Icon from './Icon'
interface OtherIconsProps {
verticalIconsPlugin: any
itemContextAction: (e: any, name: string, documentation: string) => Promise<void>
icons: IconRecord[]
theme: string
}
function IconList ({ verticalIconsPlugin, itemContextAction, icons, theme }: OtherIconsProps) {
return (
<div id="otherIcons">
{
icons
.map(p => (
<Icon
theme={theme}
iconRecord={p}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
key={
p.profile.name
}
/>
))}
</div>
)
}
export default IconList

@ -1,43 +0,0 @@
/* eslint-disable no-use-before-define */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
import React from 'react'
import Icon from './Icon'
function customFilter (p: string) {
if (p !== 'settings' && p !== 'pluginManager' &&
p !== 'filePanel' && p !== 'debugger' &&
p !== 'compiler' && p !== 'solidity' &&
p !== 'udapp' && p !== 'testing' && p !== 'solidityStaticAnalysis') return true
return false
}
interface OtherIconsProps {
verticalIconsPlugin: VerticalIcons
itemContextAction: (e: any, name: string, documentation: string) => Promise<void>
addActive: (name: string) => void
removeActive: () => void
}
function OtherIcons ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: OtherIconsProps) {
return (
<div id="otherIcons">
{
Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(customFilter)
.map(p => (
<Icon
profile={verticalIconsPlugin.targetProfileForChange[p]}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
/>
))}
</div>
)
}
export default OtherIcons

@ -1,36 +0,0 @@
/* eslint-disable no-use-before-define */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
import React, { Fragment } from 'react'
import Icon from './Icon'
interface PluginManagerProps {
verticalIconsPlugin: VerticalIcons
itemContextAction: (e: any, name: string, documentation: string) => Promise<void>
addActive: (name: string) => void
removeActive: () => void
}
function PluginManager ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: PluginManagerProps) {
return (
<Fragment>
{Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p === 'pluginManager')
.map(p => (
<Icon
profile={verticalIconsPlugin.targetProfileForChange[p]}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p]
.displayName
}
/>
))}
</Fragment>
)
}
export default PluginManager

@ -1,73 +0,0 @@
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
// eslint-disable-next-line no-use-before-define
import React, { Fragment, MutableRefObject } from 'react'
import { Chevron } from './Chevron'
import Debugger from './Debugger'
import FilePanel from './FilePanel'
import PluginManager from './PluginManager'
import Solidity from './Solidity'
import SolidityStaticAnalysis from './SolidityStaticAnalysis'
import Udapp from './Udapp'
interface RequiredSectionProps {
verticalIconsPlugin: VerticalIcons
itemContextAction: (e: any, name: string, documentation: string) => Promise<void>
addActive: (name: string) => void
removeActive: () => void
scrollableRef: MutableRefObject<any>
}
function RequiredSection ({ verticalIconsPlugin, itemContextAction, addActive, removeActive, scrollableRef }: RequiredSectionProps) {
return (
<Fragment>
<FilePanel
verticalIconsPlugin={verticalIconsPlugin}
addActive={addActive}
removeActive={removeActive}
itemContextAction={itemContextAction}
/>
<PluginManager
verticalIconsPlugin={verticalIconsPlugin}
addActive={addActive}
removeActive={removeActive}
itemContextAction={itemContextAction}
/>
<Solidity
verticalIconsPlugin={verticalIconsPlugin}
addActive={addActive}
removeActive={removeActive}
itemContextAction={itemContextAction}
/>
<Udapp
verticalIconsPlugin={verticalIconsPlugin}
addActive={addActive}
removeActive={removeActive}
itemContextAction={itemContextAction}
/>
<SolidityStaticAnalysis
verticalIconsPlugin={verticalIconsPlugin}
addActive={addActive}
removeActive={removeActive}
itemContextAction={itemContextAction}
/>
<Debugger
verticalIconsPlugin={verticalIconsPlugin}
addActive={addActive}
removeActive={removeActive}
itemContextAction={itemContextAction}
/>
{
scrollableRef.current && scrollableRef.current.scrollHeight > scrollableRef.current.clientHeight
? (
<Chevron
direction='up'
divElementRef={scrollableRef}
cssRule={'fa fa-chevron-up remixui_icon-chevron mt-0 mb-0 ml-1 pl-3'}
/>
) : null
}
</Fragment>
)
}
export { RequiredSection }

@ -1,61 +0,0 @@
/* eslint-disable no-use-before-define */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
import React, { useEffect, useRef } from 'react'
import { Chevron } from './Chevron'
import Icon from './Icon'
interface SettingsProps {
verticalIconsPlugin: VerticalIcons
itemContextAction: (e: any, name: string, documentation: string) => Promise<void>
addActive: (name: string) => void
removeActive: () => void
scrollableRef: React.MutableRefObject<any>
}
function Settings ({ scrollableRef, verticalIconsPlugin, itemContextAction, addActive, removeActive }: SettingsProps) {
const settingsRef = useRef(null)
function onThemeChanged (themeType: any) {
const invert = themeType === 'dark' ? 1 : 0
// @ts-ignore
const active = settingsRef.current.querySelector('.active')
if (active) {
// @ts-ignore
const image = settingsRef.current.querySelector('.remixui_image')
image.style.setProperty('filter', `invert(${invert})`)
}
}
useEffect(() => {
const themeModule = verticalIconsPlugin.registry.get('themeModule').api
themeModule.events.on('themeChanged', (theme: any) => {
onThemeChanged(theme.quality)
})
}, [])
return (
<div id="settingsIcons" className="remixui_settings mb-0 flex-grow-0" data-id="vertialIconsSettingsIcons" ref={settingsRef}>
{ scrollableRef.current && scrollableRef.current.scrollHeight > scrollableRef.current.clientHeight ? (<Chevron
divElementRef={scrollableRef}
direction='down'
cssRule={'fa fa-chevron-down remixui_icon-chevron mt-0 mb-0 ml-1 pl-3'}
/>) : null }
{Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p === 'settings')
.map(p => (
<Icon
profile={verticalIconsPlugin.targetProfileForChange[p]}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p]
.displayName
}
/>
))}
</div>
)
}
export default Settings

@ -1,41 +0,0 @@
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
// eslint-disable-next-line no-use-before-define
import React, { Fragment } from 'react'
import Icon from './Icon'
interface SolidityProps {
verticalIconsPlugin: VerticalIcons
itemContextAction: (e: any, name: string, documentation: string) => Promise<void>
addActive: (name: string) => void
removeActive: () => void
}
function Solidity ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: SolidityProps) {
return (
<Fragment>
{verticalIconsPlugin.targetProfileForChange &&
Object.keys(verticalIconsPlugin.targetProfileForChange).length
? Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p === 'solidity')
.map(p => (
<div id="compileIcons" key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}>
<Icon
profile={verticalIconsPlugin.targetProfileForChange[p]}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
/>
</div>
))
: null}
</Fragment>
)
}
export default Solidity

@ -1,41 +0,0 @@
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
// eslint-disable-next-line no-use-before-define
import React, { Fragment } from 'react'
import Icon from './Icon'
interface SolidityStaticAnalysisProps {
verticalIconsPlugin: VerticalIcons
itemContextAction: (e: any, name: string, documentation: string) => Promise<void>
addActive: (name: string) => void
removeActive: () => void
}
function SolidityStaticAnalysis ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: SolidityStaticAnalysisProps) {
return (
<Fragment>
{verticalIconsPlugin.targetProfileForChange &&
Object.keys(verticalIconsPlugin.targetProfileForChange).length
? Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p === 'solidityStaticAnalysis')
.map(p => (
<div id="analysisIcons" className="remixui_iconContainer" key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}>
<Icon
profile={verticalIconsPlugin.targetProfileForChange[p]}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
/>
</div>
))
: null}
</Fragment>
)
}
export default SolidityStaticAnalysis

@ -1,42 +0,0 @@
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
// eslint-disable-next-line no-use-before-define
import React, { Fragment } from 'react'
import Icon from './Icon'
interface UdappProps {
verticalIconsPlugin: VerticalIcons
itemContextAction: (e: any, name: string, documentation: string) => Promise<void>
addActive: (name: string) => void
removeActive: () => void
}
function Udapp ({ verticalIconsPlugin, itemContextAction, addActive, removeActive }: UdappProps) {
return (
<Fragment>
{verticalIconsPlugin.targetProfileForChange &&
Object.keys(verticalIconsPlugin.targetProfileForChange).length
? Object.keys(verticalIconsPlugin.targetProfileForChange)
.filter(p => p === 'udapp')
.map(p => (
<div id="runIcons" data-id="verticalIconsKindUdapp" key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
>
<Icon
profile={verticalIconsPlugin.targetProfileForChange[p]}
verticalIconPlugin={verticalIconsPlugin}
contextMenuAction={itemContextAction}
addActive={addActive}
removeActive={removeActive}
key={
verticalIconsPlugin.targetProfileForChange[p].displayName
}
/>
</div>
))
: null}
</Fragment>
)
}
export default Udapp

@ -1,8 +1,5 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import helper from 'apps/remix-ide/src/lib/helper'
import { checkSpecialChars } from '@remix-ui/helper'
import { BadgeStatus, IconStatus } from '../components/Icon'
import React, { MutableRefObject } from 'react'
import { VerticalIcons } from 'libs/remix-ui/vertical-icons-panel/types/vertical-icons-panel'
export type IconBadgeReducerAction = {
readonly type: string
@ -14,32 +11,30 @@ export type IconBadgeReducerAction = {
* @param {String} name
* @param {Object} status
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function setIconStatus (name: string, status: IconStatus) {
function setIconStatus(name: string, status: IconStatus) {
if (status.key === 'none') return { ...status, text: '' } // remove status
let text = ''
let key = ''
if (typeof status.key === 'number') {
key = status.key
// eslint-disable-next-line @typescript-eslint/no-unused-vars
text = key
} else key = helper.checkSpecialChars(status.key) ? '' : status.key
} else key = checkSpecialChars(status.key) ? '' : status.key
let thisType = ''
if (status.type === 'error') {
thisType = 'danger' // to use with bootstrap
} else thisType = helper.checkSpecialChars(status.type) ? '' : status.type!
const title = helper.checkSpecialChars(status.title) ? '' : status.title
} else thisType = checkSpecialChars(status.type) ? '' : status.type!
const title = checkSpecialChars(status.title) ? '' : status.title
const pluginName = status.pluginName
return { title, type: thisType, key, text, pluginName }
}
export function iconBadgeReducer (state: BadgeStatus, action: IconBadgeReducerAction) {
const { status, ref, verticalIconPlugin } = action.payload
if (Object.keys(verticalIconPlugin.targetProfileForChange).includes(action.type)) {
const setStatus = setIconStatus(action.type, status)
return setStatus
}
return state
export function iconBadgeReducer(state: BadgeStatus, action: IconBadgeReducerAction) {
const { status } = action.payload
const setStatus = setIconStatus(action.type, status)
return setStatus
}

@ -6,7 +6,8 @@ export type actionType = {
export function verticalScrollReducer (prevState: any, actionPayload: actionType) {
if (actionPayload.type === 'resize') {
let { scrollHeight, clientHeight, scrollState } = actionPayload.payload
const { scrollHeight, clientHeight } = actionPayload.payload
let { scrollState } = actionPayload.payload
if (scrollHeight > clientHeight) scrollState = true
return { scrollHeight, clientHeight, scrollState }
}

@ -31,6 +31,16 @@
padding: 4px;
filter: invert(0.5);
}
.remixui_icon .selected-dark {
filter: invert(1) grayscale(1);
}
.remixui_icon .selected-light {
filter: invert(0) grayscale(1);
}
.remixui_image {
}
.remixui_icon svg {

@ -0,0 +1,10 @@
import { Profile } from '@remixproject/plugin-utils'
export type IconRecord = {
profile: Profile
active: boolean
class?: string
canbeDeactivated?: boolean
isRequired?: boolean
timestamp: number
}

@ -1,9 +1,5 @@
/* eslint-disable @typescript-eslint/ban-ts-comment */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-use-before-define */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { Plugin } from '@remixproject/engine'
import React, { Fragment, useEffect, useRef } from 'react'
import { VerticalIcons } from '../../types/vertical-icons-panel'
export interface VerticalIconsContextMenuProps extends React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
pageX: number
@ -11,7 +7,7 @@ export interface VerticalIconsContextMenuProps extends React.DetailedHTMLProps<R
profileName: string
links: { Documentation: string, CanDeactivate: boolean }
canBeDeactivated: boolean
verticalIconPlugin: VerticalIcons
verticalIconPlugin: any
hideContextMenu: () => void
contextMenuAction: (evt: any, profileName: string, documentation: string) => void
}
@ -21,31 +17,22 @@ interface MenuLinksProps {
hide: () => void
profileName: string
canBeDeactivated: boolean
verticalIconPlugin: VerticalIcons
verticalIconPlugin: any
ref?: React.MutableRefObject<any>
toggle: (name: string) => void
contextMenuAction: (evt: any, profileName: string, documentation: string) => void
}
interface MenuProps {
verticalIconsPlugin: VerticalIcons
verticalIconsPlugin: Plugin
profileName: string
listItems: { Documentation: string, CanDeactivate: boolean }
hide: () => void
}
const requiredModules = [
'manager', 'compilerArtefacts', 'compilerMetadata', 'contextualListener', 'editor', 'offsetToLineColumnConverter', 'network', 'theme',
'fileManager', 'contentImport', 'blockchain', 'web3Provider', 'scriptRunner', 'fetchAndCompile', 'mainPanel', 'hiddenPanel', 'sidePanel', 'menuicons',
'filePanel', 'terminal', 'settings', 'pluginManager', 'tabs', 'udapp', 'dGitProvider', 'solidity-logic']
const nativePlugins = ['vyper', 'workshops', 'debugger', 'remixd', 'menuicons', 'solidity', 'hardhat-provider']
function VerticalIconsContextMenu (props: VerticalIconsContextMenuProps) {
const VerticalIconsContextMenu = (props: VerticalIconsContextMenuProps) =>{
const menuRef = useRef(null)
useEffect(() => {
document.addEventListener('click', props.hideContextMenu)
return () => document.removeEventListener('click', props.hideContextMenu)
}, [])
ClickOutside(menuRef, props.hideContextMenu)
useEffect(() => {
// @ts-ignore
menuRef.current.focus()
@ -54,7 +41,6 @@ function VerticalIconsContextMenu (props: VerticalIconsContextMenuProps) {
<div
id="menuItemsContainer"
className="p-1 remixui_verticalIconContextcontainer bg-light shadow border"
onBlur={props.hideContextMenu}
style={{
left: props.pageX,
top: props.pageY,
@ -80,15 +66,15 @@ function VerticalIconsContextMenu (props: VerticalIconsContextMenuProps) {
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function MenuForLinks ({
const MenuForLinks = ({
listItems,
hide,
profileName,
contextMenuAction
}: MenuLinksProps) {
}: MenuLinksProps) => {
return (
<Fragment>
{listItems.CanDeactivate && !requiredModules.includes(profileName)
{listItems.CanDeactivate
? <li
id="menuitemdeactivate"
onClick={(evt) => {
@ -118,4 +104,18 @@ function MenuForLinks ({
)
}
function ClickOutside(ref: React.MutableRefObject<HTMLElement>, hideFn: () => void) {
useEffect(() => {
function handleClickOutside(event: any) {
if (ref.current && !ref.current.contains(event.target)) {
hideFn()
}
}
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref]);
}
export default VerticalIconsContextMenu

@ -1,21 +1,19 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"jsx": "react",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"resolveJsonModule": true
"allowSyntheticDefaultImports": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

@ -2,8 +2,7 @@
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"types": ["node"],
"resolveJsonModule": true
"types": ["node"]
},
"files": [
"../../../node_modules/@nrwl/react/typings/cssmodule.d.ts",

@ -1,111 +0,0 @@
/* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable no-use-before-define */
import { Plugin } from '@remixproject/engine/lib/abstract'
import * as packageJson from '../../../../package.json'
import Registry from 'apps/remix-ide/src/app/state/registry'
import { RemixAppManager } from '@remix-ui/plugin-manager'
export type Kind =
| 'fileexplorer'
| 'compiler'
| 'udapp'
| 'testing'
| 'analysis'
| 'debugging'
| 'settings'
| 'none'
type IconKindType = {
kind: {}
}
interface defaultModuleProfile {
name: string
displayName: string
description: string
version: packageJson.version
methods: string[]
}
interface PassedProfile {
name: string
displayName: string
description: string
version: packageJson.version
methods: string[]
icon?: string
tooltip?: string
kind?: string
documentation?: string
}
interface targetProfileIcons {
profile: PassedProfile
}
export class VerticalIcons extends Plugin<any, any> {
events: EventEmitter
appManager: RemixAppManager
htmlElement: HTMLDivElement
icons: any
iconKind: {}
iconStatus: {}
defaultProfile: defaultModuleProfile
targetProfileForChange: any
targetProfileForRemoval: any
registry: Registry
keys: string[]
types: string[]
renderComponent(): void
linkContent(profile: any): void
unlinkContent(profile: any): void
listenOnStatus(profile: any): void
activateHome(): void
/**
* Add an icon to the map
* @param {ModuleProfile} profile The profile of the module
*/
addIcon({ kind, name, icon, displayName, tooltip, documentation }: any): void
/**
* resolve a classes list for @arg key
* @param {Object} key
* @param {Object} type
*/
resolveClasses(key: any, type: any): any
/**
* Set a new status for the @arg name
* @param {String} name
* @param {Object} status
*/
setIconStatus(name: string, status: any): void
/**
* Remove an icon from the map
* @param {ModuleProfile} profile The profile of the module
*/
removeIcon({ name }: any): void
/**
* Remove active for the current activated icons
*/
removeActive(): void
/**
* Add active for the new activated icon
* @param {string} name Name of profile of the module to activate
*/
addActive(name: string): void
/**
* Set an icon as active
* @param {string} name Name of profile of the module to activate
*/
select(name: string): void
/**
* Toggles the side panel for plugin
* @param {string} name Name of profile of the module to activate
*/
toggle(name: string): void
updateActivations(name: any): void
onThemeChanged(themeType: any): void
itemContextMenu(e: any, name: any, documentation: any): Promise<void>
render(): any
view: any
}
import EventEmitter = require('events')
Loading…
Cancel
Save