diff --git a/apps/remix-ide/src/app/panels/file-panel.js b/apps/remix-ide/src/app/panels/file-panel.js
index f2a423264b..9bd770b813 100644
--- a/apps/remix-ide/src/app/panels/file-panel.js
+++ b/apps/remix-ide/src/app/panels/file-panel.js
@@ -30,7 +30,7 @@ const { SlitherHandle } = require('../files/slither-handle.js')
const profile = {
name: 'filePanel',
displayName: 'File explorers',
- methods: ['createNewFile', 'uploadFile', 'getCurrentWorkspace', 'getWorkspaces', 'createWorkspace', 'setWorkspace', 'registerContextMenuItem', 'renameWorkspace', 'deleteWorkspace'],
+ methods: ['createNewFile', 'uploadFile', 'getCurrentWorkspace', 'getWorkspaces', 'createWorkspace', 'setWorkspace', 'registerContextMenuItem', 'renameWorkspace', 'deleteWorkspace', 'setFileState'],
events: ['setWorkspace', 'workspaceRenamed', 'workspaceDeleted', 'workspaceCreated'],
icon: 'assets/img/fileManager.webp',
description: ' - ',
@@ -85,6 +85,11 @@ module.exports = class Filepanel extends ViewPlugin {
})
}
+ async setFileState (items) {
+ console.log(items)
+ this.emit('setFileState', items)
+ }
+
getCurrentWorkspace () {
return this.currentWorkspaceMetadata
}
diff --git a/libs/remix-core-plugin/src/lib/code-parser.ts b/libs/remix-core-plugin/src/lib/code-parser.tsx
similarity index 91%
rename from libs/remix-core-plugin/src/lib/code-parser.ts
rename to libs/remix-core-plugin/src/lib/code-parser.tsx
index c0dfc3496b..010568e32d 100644
--- a/libs/remix-core-plugin/src/lib/code-parser.ts
+++ b/libs/remix-core-plugin/src/lib/code-parser.tsx
@@ -6,6 +6,10 @@ import { Compiler } from '@remix-project/remix-solidity'
import { AstNode, CompilationError, CompilationResult, CompilationSource } from '@remix-project/remix-solidity'
import { helper } from '@remix-project/remix-solidity'
+
+import React from 'react'
+// eslint-disable-next-line
+import { fileState, fileStateType } from '@remix-ui/workspace'
const SolidityParser = (window as any).SolidityParser = (window as any).SolidityParser || []
const profile = {
@@ -107,7 +111,48 @@ export class CodeParser extends Plugin {
}
console.log('allErrors', allErrors)
await this.call('editor', 'addErrorMarker', allErrors)
+ try {
+
+ let fileState:fileState = {
+ path: this.currentFile,
+ isDirectory: false,
+ fileStateType: [fileStateType.Custom],
+ fileStateLabelClass: 'text-success',
+ fileStateIconClass: '',
+ fileStateIcon: ,
+ comment: '',
+ owner: 'code-parser',
+ bubble: true
+ }
+ await this.call('filePanel', 'setFileState', [fileState])
+ fileState = {
+ ...fileState,
+ path: 'contracts/1_Storage.sol',
+ fileStateLabelClass: 'text-danger',
+ fileStateIcon: ,
+ }
+ await this.call('filePanel', 'setFileState', [fileState])
+ fileState = {
+ ...fileState,
+ path: 'scripts/ethers-lib.ts',
+ fileStateLabelClass: 'text-danger',
+ fileStateIcon:
call rob now!,
+ }
+ await this.call('filePanel', 'setFileState', [fileState])
+
+ } catch (e) {
+ console.log('error calling filePanel', e)
+ }
} else {
+ await this.call('filePanel', 'setFileState', [{
+ path: this.currentFile,
+ isDirectory: false,
+ fileStateType: [],
+ fileStateClass: '',
+ comment: '',
+ owner: 'code-parser',
+ bubble: true
+ }])
await this.call('editor', 'clearErrorMarkers', result.getSourceCode().sources)
}
@@ -605,7 +650,7 @@ export class CodeParser extends Plugin {
} else {
if (node.typeName && node.typeName.name) {
return `${node.typeName.name} ${node.visibility}${node.name && node.name.length ? ` ${node.name}` : ''}`
- }
+ }
else if (node.typeName && node.typeName.namePath) {
return `${node.typeName.namePath} ${node.visibility}${node.name && node.name.length ? ` ${node.name}` : ''}`
}
diff --git a/libs/remix-core-plugin/tsconfig.json b/libs/remix-core-plugin/tsconfig.json
index 7f163468b2..2845e6dae0 100644
--- a/libs/remix-core-plugin/tsconfig.json
+++ b/libs/remix-core-plugin/tsconfig.json
@@ -1,8 +1,9 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
+ "jsx": "react",
"types": ["node"],
"esModuleInterop": true
},
- "include": ["**/*.ts"]
+ "include": ["**/*.ts", "src/lib/code-parser.tsx"]
}
\ No newline at end of file
diff --git a/libs/remix-ui/editor/src/lib/providers/completionProvider.ts b/libs/remix-ui/editor/src/lib/providers/completionProvider.ts
index 18c4fd3797..69e7d4f178 100644
--- a/libs/remix-ui/editor/src/lib/providers/completionProvider.ts
+++ b/libs/remix-ui/editor/src/lib/providers/completionProvider.ts
@@ -2,7 +2,7 @@ import { isArray } from "lodash"
import { editor, languages, Position } from "monaco-editor"
import monaco from "../../types/monaco"
import { EditorUIProps } from "../remix-ui-editor"
-import { GeCompletionUnits, getBlockCompletionItems, GetCompletionKeywords, getCompletionSnippets, GetCompletionTypes, getContextualAutoCompleteByGlobalVariable, GetGlobalFunctions, GetGlobalVariable, getMsgCompletionItems, getTxCompletionItems } from "./completion/completionGlobals"
+import { GeCompletionUnits, GetCompletionKeywords, getCompletionSnippets, GetCompletionTypes, getContextualAutoCompleteByGlobalVariable, GetGlobalFunctions, GetGlobalVariable } from "./completion/completionGlobals"
export class RemixCompletionProvider implements languages.CompletionItemProvider {
diff --git a/libs/remix-ui/workspace/src/index.ts b/libs/remix-ui/workspace/src/index.ts
index 166467d115..660e0b217b 100644
--- a/libs/remix-ui/workspace/src/index.ts
+++ b/libs/remix-ui/workspace/src/index.ts
@@ -1,2 +1,3 @@
export * from './lib/providers/FileSystemProvider'
export * from './lib/contexts'
+export { fileState, fileStateType } from './lib/types/index'
\ No newline at end of file
diff --git a/libs/remix-ui/workspace/src/lib/actions/events.ts b/libs/remix-ui/workspace/src/lib/actions/events.ts
index a8bde65fd5..f9e76f1715 100644
--- a/libs/remix-ui/workspace/src/lib/actions/events.ts
+++ b/libs/remix-ui/workspace/src/lib/actions/events.ts
@@ -1,7 +1,7 @@
import { extractParentFromKey } from '@remix-ui/helper'
import React from 'react'
-import { action, WorkspaceTemplate } from '../types'
-import { displayNotification, displayPopUp, fileAddedSuccess, fileRemovedSuccess, fileRenamedSuccess, folderAddedSuccess, loadLocalhostError, loadLocalhostRequest, loadLocalhostSuccess, removeContextMenuItem, removeFocus, rootFolderChangedSuccess, setContextMenuItem, setMode, setReadOnlyMode } from './payload'
+import { action, WorkspaceTemplate, fileState } from '../types'
+import { displayNotification, displayPopUp, fileAddedSuccess, fileRemovedSuccess, fileRenamedSuccess, folderAddedSuccess, loadLocalhostError, loadLocalhostRequest, loadLocalhostSuccess, removeContextMenuItem, removeFocus, rootFolderChangedSuccess, setContextMenuItem, setMode, setReadOnlyMode, setFileStateSuccess } from './payload'
import { addInputField, createWorkspace, deleteWorkspace, fetchWorkspaceDirectory, renameWorkspace, switchToWorkspace, uploadFile } from './workspace'
const LOCALHOST = ' - connect to localhost - '
@@ -38,6 +38,10 @@ export const listenOnPluginEvents = (filePanelPlugin) => {
uploadFile(target, dir, cb)
})
+ plugin.on('filePanel', 'setFileState', async (items: fileState[]) => {
+ setFileState(items)
+ })
+
plugin.on('remixd', 'rootFolderChanged', async (path: string) => {
rootFolderChanged(path)
})
@@ -202,3 +206,8 @@ const fileRenamed = async (oldPath: string) => {
const rootFolderChanged = async (path) => {
await dispatch(rootFolderChangedSuccess(path))
}
+
+const setFileState = async (items: fileState[], cb?: (err: Error, result?: string | number | boolean | Record) => void) => {
+ await dispatch(setFileStateSuccess(items))
+ cb && cb(null, true)
+}
diff --git a/libs/remix-ui/workspace/src/lib/actions/payload.ts b/libs/remix-ui/workspace/src/lib/actions/payload.ts
index a0ed0850cb..338caffd45 100644
--- a/libs/remix-ui/workspace/src/lib/actions/payload.ts
+++ b/libs/remix-ui/workspace/src/lib/actions/payload.ts
@@ -1,4 +1,4 @@
-import { action } from '../types'
+import { action, fileState } from '../types'
export const setCurrentWorkspace = (workspace: string) => {
return {
@@ -239,3 +239,10 @@ export const fsInitializationCompleted = () => {
type: 'FS_INITIALIZATION_COMPLETED'
}
}
+
+export const setFileStateSuccess = (items: fileState[]) => {
+ return {
+ type: 'SET_FILE_STATE_SUCCESS',
+ payload: items
+ }
+}
diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx
index a0351ea3a1..adbad94a36 100644
--- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx
+++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx
@@ -12,7 +12,7 @@ import { checkSpecialChars, extractNameFromKey, extractParentFromKey, joinPath }
import { FileRender } from './file-render'
export const FileExplorer = (props: FileExplorerProps) => {
- const { name, contextMenuItems, removedContextMenuItems, files } = props
+ const { name, contextMenuItems, removedContextMenuItems, files, fileState } = props
const [state, setState] = useState({
ctrlKey: false,
newFileName: '',
@@ -432,6 +432,7 @@ export const FileExplorer = (props: FileExplorerProps) => {
{
files[props.name] && Object.keys(files[props.name]).map((key, index) => void
}
export const FileLabel = (props: FileLabelProps) => {
- const { file, focusEdit, editModeOff } = props
+ const { file, focusEdit, editModeOff, fileState } = props
const [isEditable, setIsEditable] = useState(false)
+ const [fileStateClasses, setFileStateClasses] = useState('')
const labelRef = useRef(null)
useEffect(() => {
@@ -24,6 +26,17 @@ export const FileLabel = (props: FileLabelProps) => {
}
}, [file.path, focusEdit])
+ useEffect(() => {
+ const state = props.fileState.find((state: fileState) => {
+ if(state.path === props.file.path) return true
+ if(state.bubble && props.file.isDirectory && state.path.startsWith(props.file.path)) return true
+ })
+ console.log(props)
+ if (state && state.fileStateLabelClass) {
+ setFileStateClasses(state.fileStateLabelClass)
+ }
+ }, [fileState])
+
useEffect(() => {
if (labelRef.current) {
setTimeout(() => {
@@ -57,10 +70,10 @@ export const FileLabel = (props: FileLabelProps) => {
>
- { file.name }
+ {file.name}
)
diff --git a/libs/remix-ui/workspace/src/lib/components/file-render.tsx b/libs/remix-ui/workspace/src/lib/components/file-render.tsx
index ac0054e96b..398a75f4ae 100644
--- a/libs/remix-ui/workspace/src/lib/components/file-render.tsx
+++ b/libs/remix-ui/workspace/src/lib/components/file-render.tsx
@@ -1,11 +1,12 @@
// eslint-disable-next-line no-use-before-define
import React, { SyntheticEvent, useEffect, useState } from 'react'
-import { FileType } from '../types'
+import { fileState, FileType } from '../types'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { TreeView, TreeViewItem } from '@remix-ui/tree-view'
import { getPathIcon } from '@remix-ui/helper'
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { FileLabel } from './file-label'
+import FileState from './file-state'
export interface RenderFileProps {
file: FileType,
@@ -19,6 +20,7 @@ export interface RenderFileProps {
handleClickFolder: (path: string, type: string) => void,
handleClickFile: (path: string, type: string) => void,
handleContextMenu: (pageX: number, pageY: number, path: string, content: string, type: string) => void
+ fileState: fileState[]
}
export const FileRender = (props: RenderFileProps) => {
@@ -76,7 +78,7 @@ export const FileRender = (props: RenderFileProps) => {
iconX='pr-3 fa fa-folder'
iconY='pr-3 fa fa-folder-open'
key={`${file.path + props.index}`}
- label={}
+ label={}
onClick={handleFolderClick}
onContextMenu={handleContextMenu}
labelClass={labelClass}
@@ -89,6 +91,7 @@ export const FileRender = (props: RenderFileProps) => {
file.child ? {
Object.keys(file.child).map((key, index) => {
}
+ label={
+ <>
+
+
+
+
+ >
+ }
onClick={handleFileClick}
onContextMenu={handleContextMenu}
icon={icon}
diff --git a/libs/remix-ui/workspace/src/lib/components/file-state.tsx b/libs/remix-ui/workspace/src/lib/components/file-state.tsx
new file mode 100644
index 0000000000..fbf660777a
--- /dev/null
+++ b/libs/remix-ui/workspace/src/lib/components/file-state.tsx
@@ -0,0 +1,56 @@
+// eslint-disable-next-line no-use-before-define
+import React, { useEffect, useState } from 'react'
+import { FileType, fileState, fileStateType } from '../types'
+import FileStateCustom from './filestates/file-state-custom'
+import FileStateError from './filestates/file-state-error'
+import FileStateWarning from './filestates/file-state-warning'
+// import FileStateModified from './filestates/file-state-modified'
+// import FileStateUntracked from './filestates/file-state-untracked'
+
+export type fileStateProps = {
+ file: FileType,
+ fileState: fileState[]
+}
+
+export const FileState = (props: fileStateProps) => {
+ const [state, setState] = useState(undefined)
+ useEffect(() => {
+ console.log(props.file)
+ console.log(props.fileState)
+ setState(props.fileState.find((st) => st.path === props.file.path))
+ }, [props.fileState])
+
+ const getTags = function () {
+ if (state) {
+ const types = state.fileStateType
+ const elements: any[] = []
+
+ for (const type of types) {
+ switch (type) {
+ case fileStateType.Modified:
+ //elements.push()
+ break
+ case fileStateType.Untracked:
+ //elements.push()
+ break
+ case fileStateType.Error:
+ elements.push()
+ break
+ case fileStateType.Warning:
+ elements.push()
+ break
+ case fileStateType.Custom:
+ elements.push()
+ break
+ }
+ }
+ return elements
+ }
+ }
+
+ return <>
+ {getTags()}
+ >
+}
+
+export default FileState
\ No newline at end of file
diff --git a/libs/remix-ui/workspace/src/lib/components/filestates/file-state-custom.tsx b/libs/remix-ui/workspace/src/lib/components/filestates/file-state-custom.tsx
new file mode 100644
index 0000000000..ef56538480
--- /dev/null
+++ b/libs/remix-ui/workspace/src/lib/components/filestates/file-state-custom.tsx
@@ -0,0 +1,13 @@
+// eslint-disable-next-line no-use-before-define
+import React from 'react'
+import { fileState } from '../../types'
+
+const FileStateError = (props: {
+ fileState: fileState
+}) => {
+ return <>
+ {props.fileState.fileStateIcon}
+ >
+}
+
+export default FileStateError
\ No newline at end of file
diff --git a/libs/remix-ui/workspace/src/lib/components/filestates/file-state-error.tsx b/libs/remix-ui/workspace/src/lib/components/filestates/file-state-error.tsx
new file mode 100644
index 0000000000..1e8a950218
--- /dev/null
+++ b/libs/remix-ui/workspace/src/lib/components/filestates/file-state-error.tsx
@@ -0,0 +1,11 @@
+// eslint-disable-next-line no-use-before-define
+import React from 'react'
+import { fileState } from '../../types'
+
+const FileStateError = (props: {
+ fileState: fileState
+}) => {
+ return <>⬤>
+}
+
+export default FileStateError
\ No newline at end of file
diff --git a/libs/remix-ui/workspace/src/lib/components/filestates/file-state-icon-properties.tsx b/libs/remix-ui/workspace/src/lib/components/filestates/file-state-icon-properties.tsx
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/libs/remix-ui/workspace/src/lib/components/filestates/file-state-warning.tsx b/libs/remix-ui/workspace/src/lib/components/filestates/file-state-warning.tsx
new file mode 100644
index 0000000000..81912cfbd2
--- /dev/null
+++ b/libs/remix-ui/workspace/src/lib/components/filestates/file-state-warning.tsx
@@ -0,0 +1,11 @@
+// eslint-disable-next-line no-use-before-define
+import React from 'react'
+import { fileState } from '../../types'
+
+const FileStateWarning = (props: {
+ fileState: fileState
+}) => {
+ return <>⬤>
+}
+
+export default FileStateWarning
\ No newline at end of file
diff --git a/libs/remix-ui/workspace/src/lib/reducers/workspace.ts b/libs/remix-ui/workspace/src/lib/reducers/workspace.ts
index 8d33cb226d..a6951c50cc 100644
--- a/libs/remix-ui/workspace/src/lib/reducers/workspace.ts
+++ b/libs/remix-ui/workspace/src/lib/reducers/workspace.ts
@@ -1,5 +1,5 @@
import { extractNameFromKey } from '@remix-ui/helper'
-import { action, FileType } from '../types'
+import { action, fileState, FileType } from '../types'
import * as _ from 'lodash'
interface Action {
type: string
@@ -20,7 +20,8 @@ export interface BrowserState {
registeredMenuItems: action[],
removedMenuItems: action[],
error: string
- }
+ },
+ fileState: fileState[]
},
localhost: {
sharedFolder: string,
@@ -35,7 +36,8 @@ export interface BrowserState {
registeredMenuItems: action[],
removedMenuItems: action[],
error: string
- }
+ },
+ fileState: []
},
mode: 'browser' | 'localhost',
notification: {
@@ -68,7 +70,8 @@ export const browserInitialState: BrowserState = {
registeredMenuItems: [],
removedMenuItems: [],
error: null
- }
+ },
+ fileState: []
},
localhost: {
sharedFolder: '',
@@ -83,7 +86,8 @@ export const browserInitialState: BrowserState = {
registeredMenuItems: [],
removedMenuItems: [],
error: null
- }
+ },
+ fileState: []
},
mode: 'browser',
notification: {
@@ -599,6 +603,34 @@ export const browserReducer = (state = browserInitialState, action: Action) => {
}
}
+ case 'SET_FILE_STATE_SUCCESS': {
+ const payload = action.payload as fileState[]
+ console.log('SET_FILE_STATE_SUCCESS', payload)
+ const a = state.browser.fileState
+ const b = payload
+ const merge = _.merge({}, _.keyBy(a, 'path'), _.keyBy(b, 'path'))
+ const vals = _.values(merge)
+ console.log(a)
+ console.log(vals)
+ vals.map(function (x) {
+ const c = a.find(function (el) {
+ return el.path === x.path
+ })
+ if (c && c.fileStateType) {
+ x.fileStateType = _.uniq([...c.fileStateType, ...x.fileStateType])
+ }
+ return x
+ })
+ console.log(vals)
+ return {
+ ...state,
+ browser: {
+ ...state.browser,
+ fileState: vals
+ }
+ }
+ }
+
default:
throw new Error()
}
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 98a80306bd..24538c4d9d 100644
--- a/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
+++ b/libs/remix-ui/workspace/src/lib/remix-ui-workspace.tsx
@@ -238,6 +238,7 @@ export function Workspace () {
contextMenuItems={global.fs.browser.contextMenu.registeredMenuItems}
removedContextMenuItems={global.fs.browser.contextMenu.removedMenuItems}
files={global.fs.browser.files}
+ fileState={global.fs.browser.fileState}
expandPath={global.fs.browser.expandPath}
focusEdit={global.fs.focusEdit}
focusElement={global.fs.focusElement}
@@ -273,6 +274,7 @@ export function Workspace () {
contextMenuItems={global.fs.localhost.contextMenu.registeredMenuItems}
removedContextMenuItems={global.fs.localhost.contextMenu.removedMenuItems}
files={global.fs.localhost.files}
+ fileState={[]}
expandPath={global.fs.localhost.expandPath}
focusEdit={global.fs.focusEdit}
focusElement={global.fs.focusElement}
diff --git a/libs/remix-ui/workspace/src/lib/types/index.ts b/libs/remix-ui/workspace/src/lib/types/index.ts
index fb169db5e8..9605894846 100644
--- a/libs/remix-ui/workspace/src/lib/types/index.ts
+++ b/libs/remix-ui/workspace/src/lib/types/index.ts
@@ -66,6 +66,35 @@ export interface FileType {
child?: File[]
}
+export enum fileStateType {
+ Error = 'ERROR',
+ Warning = 'WARNING',
+ Success = 'SUCCESS',
+ Loading = 'LOADING',
+ Unsaved = 'UNSAVED',
+ Untracked = 'UNTRACKED',
+ Modified = 'MODIFIED',
+ Staged = 'STAGED',
+ Committed = 'COMMITTED',
+ Deleted = 'DELETED',
+ Added = 'ADDED',
+ New = 'NEW',
+ Compiled = 'COMPILED',
+ Custom = 'CUSTOM',
+}
+
+export type fileState = {
+ path: string,
+ isDirectory: boolean,
+ fileStateType: fileStateType[],
+ fileStateLabelClass: string,
+ fileStateIconClass: string,
+ fileStateIcon: string | HTMLDivElement | JSX.Element,
+ bubble: boolean,
+ comment: string,
+ owner: string,
+}
+
/* eslint-disable-next-line */
export interface FileExplorerProps {
name: string,
@@ -73,6 +102,7 @@ export interface FileExplorerProps {
contextMenuItems: MenuItems,
removedContextMenuItems: MenuItems,
files: { [x: string]: Record },
+ fileState: fileState[],
expandPath: string[],
focusEdit: string,
focusElement: { key: string, type: 'file' | 'folder' | 'gist' }[],