refactor contextview to be added in the editor

pull/5370/head
yann300 3 years ago
parent 15e4976345
commit 10365638d5
  1. 34
      apps/remix-ide/src/app/panels/main-view.js
  2. 2
      libs/remix-core-plugin/src/lib/editor-context-listener.ts
  3. 59
      libs/remix-ui/editor-context-view/src/lib/remix-ui-editor-context-view.tsx
  4. 7
      libs/remix-ui/editor/src/lib/remix-ui-editor.css
  5. 20
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx

@ -1,7 +1,6 @@
import React from 'react' // eslint-disable-line
import ReactDOM from 'react-dom'
import { RemixUiEditorContextView } from '@remix-ui/editor-context-view'
var yo = require('yo-yo')
var EventManager = require('../../lib/events')
@ -17,11 +16,7 @@ var css = csjs`
flex-direction : column;
height : 100%;
width : 100%;
}
.contextview {
opacity : 1;
position : relative;
}
}
`
// @todo(#650) Extract this into two classes: MainPanel (TabsProxy + Iframe/Editor) & BottomPanel (Terminal)
@ -33,7 +28,6 @@ export class MainView {
self._components = {}
self._components.registry = globalRegistry
self.contextualListener = contextualListener
self.hideContextView = false
self.editor = editor
self.fileManager = fileManager
self.mainPanel = mainPanel
@ -47,8 +41,6 @@ export class MainView {
this.fileManager.unselectCurrentFile()
this.mainPanel.showContent(name)
this._view.editor.style.display = 'none'
this.hideContextView = true
this.renderContextView()
this._view.mainPanel.style.display = 'block'
}
@ -72,22 +64,16 @@ export class MainView {
// we check upstream for "fileChanged"
self._view.editor.style.display = 'block'
self._view.mainPanel.style.display = 'none'
this.hideContextView = false
this.renderContextView()
})
self.tabProxy.event.on('openFile', (file) => {
self._view.editor.style.display = 'block'
self._view.mainPanel.style.display = 'none'
this.hideContextView = false
this.renderContextView()
self._view.mainPanel.style.display = 'none'
})
self.tabProxy.event.on('closeFile', (file) => {
})
self.tabProxy.event.on('switchApp', self.showApp.bind(self))
self.tabProxy.event.on('closeApp', (name) => {
self._view.editor.style.display = 'block'
this.hideContextView = false
this.renderContextView()
self._view.mainPanel.style.display = 'none'
})
self.tabProxy.event.on('tabCountChanged', (count) => {
@ -210,22 +196,6 @@ export class MainView {
return self._view.mainview
}
renderContextView () {
if (!this.contextualListener.activated) return
ReactDOM.render(
<RemixUiEditorContextView
hide={this.hideContextView}
contextualListener={this.contextualListener}
gotoLine={(line, column) => this.contextualListener.call('editor', 'gotoLine', line, column)}
openFile={(file) => this.contextualListener.call('editor', 'openFile', file)}
getLastCompilationResult={_ => { return this.contextualListener.call('compilerArtefacts', 'getLastCompilationResult') } }
offsetToLineColumn={(position, file, sources, asts) => { return this.contextualListener.call('offsetToLineColumnConverter', 'offsetToLineColumn', position, file, sources, asts) } }
getCurrentFileName={() => { return this.contextualListener.call('fileManager', 'file') } }
/>
, this._view.mainview.querySelector('.contextview'))
}
registerCommand (name, command, opts) {
var self = this
return self._components.terminal.registerCommand(name, command, opts)

@ -6,7 +6,7 @@ const { AstWalker } = require('@remix-project/remix-astwalker')
const profile = {
name: 'contextualListener',
methods: [],
methods: ['referencesOf', 'getActiveHighlights', 'gasEstimation', 'declarationOf'],
events: [],
version: '0.0.1'
}

@ -3,15 +3,21 @@ import { sourceMappingDecoder } from '@remix-project/remix-debug'
import './remix-ui-editor-context-view.css';
export type onContextListenerChangedListener = (nodes: Array<astNode>) => void
/* eslint-disable-next-line */
export interface RemixUiEditorContextViewProps {
hide: boolean,
contextualListener: any,
gotoLine: (line: number, column: number) => void,
openFile: (fileName: string) => void,
getLastCompilationResult: () => any,
offsetToLineColumn: (position: any, file: any, sources: any, asts: any) => any,
getCurrentFileName: () => String
onContextListenerChanged: (listener: onContextListenerChangedListener) => void
referencesOf: (nodes: astNode) => Array<astNode>
getActiveHighlights: () => Array<astNode>
gasEstimation: (node: astNode) => gasEstimation
declarationOf: (node: astNode) => astNode
}
function isDefinition (node: any) {
@ -23,7 +29,12 @@ function isDefinition (node: any) {
node.nodeType === 'EventDefinition'
}
type astNode = {
export type gasEstimationType = {
executionCost: string,
codeDepositCost: string
}
export type astNode = {
name: string,
id: number,
children: Array<any>,
@ -42,36 +53,50 @@ export function RemixUiEditorContextView(props: RemixUiEditorContextViewProps) {
gotoLineDisableRef is used to temporarily disable the update of the view.
e.g when the user ask the component to "gotoLine" we don't want to rerender the component (but just to put the mouse on the desired line)
*/
const gotoLineDisableRef = useRef(false)
const referencesRef = useRef([])
const activeHighlightsRef = useRef([])
const currentNodeRef = useRef(null as nullableAstNode)
const gasEstimationRef = useRef({} as gasEstimationType)
const gotoLineDisableRef = useRef(false)
const [nodesState, setNode] = useState<Array<astNode>>([])
const contextualListener = props.contextualListener
useEffect(() => {
contextualListener.on('contextualListener', 'contextChanged', (nodes: Array<astNode>) => {
props.onContextListenerChanged(async (nodes: Array<astNode>) => {
if (gotoLineDisableRef.current) {
gotoLineDisableRef.current = false
return
}
nodesRef.current = nodes
if (!props.hide && nodesRef.current && nodesRef.current.length) {
currentNodeRef.current = nodesRef.current[nodesRef.current.length - 1]
if (!isDefinition(currentNodeRef.current)) {
currentNodeRef.current = await props.declarationOf(currentNodeRef.current)
}
}
if (currentNodeRef.current) {
referencesRef.current = await props.referencesOf(currentNodeRef.current)
gasEstimationRef.current = await props.gasEstimation(currentNodeRef.current)
}
activeHighlightsRef.current = await props.getActiveHighlights()
setNode(nodes)
})
}, [])
const _render = (node: nullableAstNode) => {
if (!node) return (<div></div>)
let references = contextualListener.referencesOf(node)
let references = referencesRef.current
const type = node.typeDescriptions && node.typeDescriptions.typeString ? node.typeDescriptions.typeString : node.nodeType
references = `${references ? references.length : '0'} reference(s)`
let referencesCount = `${references ? references.length : '0'} reference(s)`
let ref = 0
const nodes: Array<astNode> = contextualListener.getActiveHighlights()
const nodes: Array<astNode> = activeHighlightsRef.current
/*
* show gas estimation
*/
const gasEstimation = () => {
if (node.nodeType === 'FunctionDefinition') {
const result = contextualListener.gasEstimation(node)
const result: gasEstimationType = gasEstimationRef.current
const executionCost = ' Execution cost: ' + result.executionCost + ' gas'
const codeDepositCost = 'Code deposit cost: ' + result.codeDepositCost + ' gas'
const estimatedGas = result.codeDepositCost ? `${codeDepositCost}, ${executionCost}` : `${executionCost}`
@ -134,24 +159,16 @@ export function RemixUiEditorContextView(props: RemixUiEditorContextViewProps) {
<div title={type} className="type">{type}</div>
<div title={node.name} className="name mr-2">{node.name}</div>
<i className="fas fa-share jump" data-action='gotoref' aria-hidden="true" onClick={jumpTo}></i>
<span className="referencesnb">{references}</span>
<span className="referencesnb">{referencesCount}</span>
<i data-action='previous' className="fas fa-chevron-up jump" aria-hidden="true" onClick={jump}></i>
<i data-action='next' className="fas fa-chevron-down jump" aria-hidden="true" onClick={jump}></i>
</div>
)
}
let last: nullableAstNode = null
if (!props.hide && nodesRef.current && nodesRef.current.length) {
last = nodesRef.current[nodesRef.current.length - 1]
if (!isDefinition(last)) {
last = contextualListener.declarationOf(last)
}
}
}
return (
!props.hide && <div className="container-context-view contextviewcontainer bg-light text-dark border-0 py-1">
{_render(last)}
{_render(currentNodeRef.current)}
</div>
);
}

@ -8,4 +8,9 @@
border-radius : 10px;
height: auto;
width: auto;
}
}
.contextview {
opacity : 1;
position : relative;
}

@ -1,4 +1,5 @@
import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint-disable-line
import { RemixUiEditorContextView, astNode } from '@remix-ui/editor-context-view'
import Editor, { loader } from '@monaco-editor/react'
import { reducerActions, reducerListener, initialState } from './actions/editor'
import { language, conf } from './syntax'
@ -49,6 +50,7 @@ loader.config({ paths: { vs: 'assets/js/monaco-editor/dev/vs' } })
/* eslint-disable-next-line */
export interface EditorUIProps {
contextualListener: any
activated: boolean
themeType: string
currentFile: string
@ -62,6 +64,7 @@ export interface EditorUIProps {
}
plugin: {
on: (plugin: string, event: string, listener: any) => void
call: (plugin: string, method: string, arg1?: any, arg2?: any, arg3?: any, arg4?: any) => any
}
editorAPI: {
findMatches: (uri: string, value: string) => any
@ -377,6 +380,7 @@ export const EditorUI = (props: EditorUIProps) => {
}
return (
<div className="w-100 h-100 position-relative">
<Editor
width="100%"
height="100%"
@ -386,6 +390,22 @@ export const EditorUI = (props: EditorUIProps) => {
beforeMount={handleEditorWillMount}
options={{ glyphMargin: true }}
/>
<div className="contextview position-absolute">
<RemixUiEditorContextView
hide={false}
gotoLine={(line, column) => props.plugin.call('editor', 'gotoLine', line, column)}
openFile={(file) => props.plugin.call('editor', 'openFile', file)}
getLastCompilationResult={() => { return props.plugin.call('compilerArtefacts', 'getLastCompilationResult') } }
offsetToLineColumn={(position, file, sources, asts) => { return props.plugin.call('offsetToLineColumnConverter', 'offsetToLineColumn', position, file, sources, asts) } }
getCurrentFileName={() => { return props.plugin.call('fileManager', 'file') } }
onContextListenerChanged={(listener) => { props.plugin.on('contextualListener', 'contextChanged', listener) }}
referencesOf={(node: astNode) => { return props.plugin.call('contextualListener', 'referencesOf', node) }}
getActiveHighlights={() => { return props.plugin.call('contextualListener', 'getActiveHighlights') }}
gasEstimation={(node: astNode) => { return props.plugin.call('contextualListener', 'gasEstimation', node) }}
declarationOf={(node: astNode) => { return props.plugin.call('contextualListener', 'declarationOf', node) }}
/>
</div>
</div>
)
}

Loading…
Cancel
Save