xterm build

rdesktop2
bunsenstraat 1 year ago
parent cb32ecbd31
commit f4e3dfc01d
  1. 5
      apps/remix-ide/src/app.js
  2. 15
      apps/remix-ide/src/app/plugins/electron/xtermPlugin.ts
  3. 3
      apps/remixdesktop/package.json
  4. 2
      apps/remixdesktop/src/plugins/fsPlugin.ts
  5. 32
      apps/remixdesktop/src/plugins/xtermPlugin.ts
  6. 2
      libs/remix-ui/app/src/lib/remix-app/remix-app.tsx
  7. 3
      libs/remix-ui/xterm/src/index.ts
  8. 39
      libs/remix-ui/xterm/src/lib/components/remix-ui-filedialog.tsx
  9. 44
      libs/remix-ui/xterm/src/lib/components/remix-ui-xterm.tsx
  10. 103
      libs/remix-ui/xterm/src/lib/components/remix-ui-xterminals.tsx
  11. 3
      package.json
  12. 4
      tsconfig.paths.json
  13. 13
      yarn.lock

@ -50,6 +50,7 @@ import { fsPlugin } from './app/plugins/electron/fsPlugin'
import { isoGitPlugin } from './app/plugins/electron/isoGitPlugin' import { isoGitPlugin } from './app/plugins/electron/isoGitPlugin'
import { electronConfig } from './app/plugins/electron/electronConfigPlugin' import { electronConfig } from './app/plugins/electron/electronConfigPlugin'
import { electronTemplates } from './app/plugins/electron/templatesPlugin' import { electronTemplates } from './app/plugins/electron/templatesPlugin'
import { xtermPlugin } from './app/plugins/electron/xtermPlugin'
@ -340,6 +341,8 @@ class AppComponent {
this.engine.register([electronConfigPlugin]) this.engine.register([electronConfigPlugin])
const templatesPlugin = new electronTemplates() const templatesPlugin = new electronTemplates()
this.engine.register([templatesPlugin]) this.engine.register([templatesPlugin])
const xterm = new xtermPlugin()
this.engine.register([xterm])
} }
// LAYOUT & SYSTEM VIEWS // LAYOUT & SYSTEM VIEWS
@ -458,7 +461,7 @@ class AppComponent {
await this.appManager.activatePlugin(['solidity-script', 'remix-templates']) await this.appManager.activatePlugin(['solidity-script', 'remix-templates'])
if(isElectron()){ if(isElectron()){
await this.appManager.activatePlugin(['fs', 'isogit', 'electronconfig', 'electronTemplates']) await this.appManager.activatePlugin(['fs', 'isogit', 'electronconfig', 'electronTemplates', 'xterm'])
} }
this.appManager.on( this.appManager.on(

@ -0,0 +1,15 @@
import { ElectronPlugin } from '@remixproject/engine-electron';
export class xtermPlugin extends ElectronPlugin {
constructor(){
super({
displayName: 'xterm',
name: 'xterm',
description: 'xterm',
})
}
onActivation(){
console.log('xtermPlugin Activated')
}
}

@ -26,7 +26,8 @@
"start:production": "tsc && cross-env NODE_ENV=production electron .", "start:production": "tsc && cross-env NODE_ENV=production electron .",
"pack": "tsc && electron-builder", "pack": "tsc && electron-builder",
"dist": "tsc && electron-builder", "dist": "tsc && electron-builder",
"postinstall": "electron-builder install-app-deps" "postinstall": "electron-builder install-app-deps",
"rebuild-node-pty": "electron-rebuild -f -o node-pty"
}, },
"devDependencies": { "devDependencies": {
"@electron/rebuild": "^3.2.13", "@electron/rebuild": "^3.2.13",

@ -55,7 +55,7 @@ export class FSPlugin extends ElectronBasePlugin {
} }
}else{ }else{
console.log('no opened folders') console.log('no opened folders')
//createWindow() createWindow()
} }
} }

@ -5,6 +5,36 @@ import { ElectronBasePlugin, ElectronBasePluginClient } from "@remixproject/plug
import os from 'os'; import os from 'os';
import * as pty from "node-pty" import * as pty from "node-pty"
import process from 'node:process';
import {userInfo} from 'node:os';
export const detectDefaultShell = () => {
const {env} = process;
if (process.platform === 'win32') {
return env.COMSPEC || 'cmd.exe';
}
try {
const {shell} = userInfo();
if (shell) {
return shell;
}
} catch {}
if (process.platform === 'darwin') {
return env.SHELL || '/bin/zsh';
}
return env.SHELL || '/bin/sh';
};
// Stores default shell when imported.
const defaultShell = detectDefaultShell();
export default defaultShell;
const profile: Profile = { const profile: Profile = {
name: 'xterm', name: 'xterm',
displayName: 'xterm', displayName: 'xterm',
@ -41,7 +71,7 @@ class XtermPluginClient extends ElectronBasePluginClient {
} }
async createTerminal(path?: string): Promise<number> { async createTerminal(path?: string): Promise<number> {
const shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash'; const shell = defaultShell;
const ptyProcess = pty.spawn(shell, [], { const ptyProcess = pty.spawn(shell, [], {
name: 'xterm-color', name: 'xterm-color',

@ -10,6 +10,7 @@ import DialogViewPlugin from './components/modals/dialogViewPlugin'
import { AppContext } from './context/context' import { AppContext } from './context/context'
import { IntlProvider } from 'react-intl' import { IntlProvider } from 'react-intl'
import { CustomTooltip } from '@remix-ui/helper'; import { CustomTooltip } from '@remix-ui/helper';
import { RemixUiXterminals } from '@remix-ui/xterm'
interface IRemixAppUi { interface IRemixAppUi {
app: any app: any
@ -90,6 +91,7 @@ const RemixApp = (props: IRemixAppUi) => {
<DragBar resetTrigger={resetTrigger} maximiseTrigger={maximiseTrigger} minWidth={285} refObject={sidePanelRef} hidden={hideSidePanel} setHideStatus={setHideSidePanel}></DragBar> <DragBar resetTrigger={resetTrigger} maximiseTrigger={maximiseTrigger} minWidth={285} refObject={sidePanelRef} hidden={hideSidePanel} setHideStatus={setHideSidePanel}></DragBar>
<div id="main-panel" data-id="remixIdeMainPanel" className='mainpanel d-flex'> <div id="main-panel" data-id="remixIdeMainPanel" className='mainpanel d-flex'>
<RemixUIMainPanel Context={AppContext}></RemixUIMainPanel> <RemixUIMainPanel Context={AppContext}></RemixUIMainPanel>
<RemixUiXterminals plugin={props.app.appManager}></RemixUiXterminals>
<CustomTooltip <CustomTooltip
placement="bottom" placement="bottom"
tooltipId="overlay-tooltip-all-tabs" tooltipId="overlay-tooltip-all-tabs"

@ -0,0 +1,3 @@
export * from './lib/components/remix-ui-xterm'
export * from './lib/components/remix-ui-filedialog'
export * from './lib/components/remix-ui-xterminals'

@ -0,0 +1,39 @@
import { Plugin } from "@remixproject/engine"
import React, { useEffect, useState } from "react"
interface RemixUIFileDialogInterface {
plugin: Plugin
}
export const RemixUIFileDialog = (props: RemixUIFileDialogInterface) => {
const { plugin } = props
const [files, setFiles] = useState<string[]>([])
const [workingDir, setWorkingDir] = useState<string>('')
useEffect(() => {
plugin.on('fs', 'workingDirChanged', async (path: string) => {
console.log('workingDirChanged')
setWorkingDir(path)
await readdir()
})
}, [])
const readdir = async () => {
const files = await plugin.call('fs', 'readdir', '/')
console.log('files', files)
setFiles(files)
}
return (
<>
<h1>RemixUIFileDialog</h1>
<button onClick={() => plugin.call('fs', 'setWorkingDir')}>open</button>
<button onClick={async () => await readdir()}>read</button>
<hr></hr>
{workingDir}
<hr></hr>
{files.map(file => <div key={file}>{file}</div>)}
</>
)
}

@ -0,0 +1,44 @@
import React, { useState, useEffect, forwardRef } from 'react' // eslint-disable-line
import { ElectronPlugin } from '@remixproject/engine-electron'
import { XTerm } from 'xterm-for-react'
export interface RemixUiXtermProps {
plugin: ElectronPlugin
pid: number
send: (data: string, pid: number) => void
timeStamp: number
setTerminalRef: (pid: number, ref: any) => void
}
const RemixUiXterm = (props: RemixUiXtermProps) => {
const { plugin, pid, send, timeStamp } = props
const xtermRef = React.useRef(null)
useEffect(() => {
console.log('remix-ui-xterm ref', xtermRef.current)
props.setTerminalRef(pid, xtermRef.current)
}, [xtermRef.current])
const onKey = (event: { key: string; domEvent: KeyboardEvent }) => {
send(event.key, pid)
}
const onData = (data: string) => {
console.log('onData', data)
}
const closeTerminal = () => {
plugin.call('xterm', 'close', pid)
}
return (
<>
<XTerm ref={xtermRef} onData={onData} onKey={onKey}></XTerm>
<button onClick={closeTerminal}>close</button>
</>
)
}
export default RemixUiXterm

@ -0,0 +1,103 @@
import React, { useState, useEffect } from 'react' // eslint-disable-line
import { ElectronPlugin } from '@remixproject/engine-electron'
import RemixUiXterm from './remix-ui-xterm'
export interface RemixUiXterminalsProps {
plugin: ElectronPlugin
}
export interface xtermState {
pid: number
queue: string
timeStamp: number
ref: any
}
export const RemixUiXterminals = (props: RemixUiXterminalsProps) => {
const [terminals, setTerminals] = useState<xtermState[]>([])
const [workingDir, setWorkingDir] = useState<string>('')
const { plugin } = props
useEffect(() => {
setTimeout(async () => {
plugin.on('xterm', 'loaded', async () => {
})
plugin.on('xterm', 'data', async (data: string, pid: number) => {
writeToTerminal(data, pid)
})
plugin.on('xterm', 'close', async (pid: number) => {
setTerminals(prevState => {
return prevState.filter(xtermState => xtermState.pid !== pid)
})
})
plugin.on('fs', 'workingDirChanged', (path: string) => {
setWorkingDir(path)
})
}, 5000)
}, [])
const writeToTerminal = (data: string, pid: number) => {
setTerminals(prevState => {
const terminal = prevState.find(xtermState => xtermState.pid === pid)
if (terminal.ref && terminal.ref.terminal) {
terminal.ref.terminal.write(data)
}else {
terminal.queue += data
}
return [...prevState]
})
}
useEffect(() => {
console.log('terminals', terminals)
}, [terminals])
const send = (data: string, pid: number) => {
plugin.call('xterm', 'keystroke', data, pid)
}
const createTerminal = async () => {
const pid = await plugin.call('xterm', 'createTerminal', workingDir)
setTerminals(prevState => {
return [...prevState, {
pid: pid,
queue: '',
timeStamp: Date.now(),
ref: null
}]
})
}
const setTerminalRef = (pid: number, ref: any) => {
console.log('setTerminalRef', pid, ref)
setTerminals(prevState => {
const terminal = prevState.find(xtermState => xtermState.pid === pid)
terminal.ref = ref
if(terminal.queue) {
ref.terminal.write(terminal.queue)
terminal.queue = ''
}
return [...prevState]
})
}
return (<>
<button onClick={() => {
createTerminal()
}}>create terminal</button>
{terminals.map((xtermState) => {
return (
<div key={xtermState.pid} data-id={`remixUIXT${xtermState.pid}`}>{xtermState.pid}
<RemixUiXterm setTerminalRef={setTerminalRef} timeStamp={xtermState.timeStamp} send={send} pid={xtermState.pid} plugin={plugin}></RemixUiXterm>
</div>
)
})}
</>)
}

@ -219,7 +219,8 @@
"wagmi": "^0.12.7", "wagmi": "^0.12.7",
"web3": "^1.8.0", "web3": "^1.8.0",
"winston": "^3.3.3", "winston": "^3.3.3",
"ws": "^7.3.0" "ws": "^7.3.0",
"xterm-for-react": "^1.0.4"
}, },
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.19.3", "@babel/cli": "^7.19.3",

@ -154,6 +154,10 @@
"@remixproject/walletconnect-plugin": [ "@remixproject/walletconnect-plugin": [
"apps/walletconnect/src/index.ts" "apps/walletconnect/src/index.ts"
], ],
"@remix-ui/xterm": [
"libs/remix-ui/xterm/src/index.ts"
],
} }
} }
} }

@ -29342,6 +29342,19 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.0, xtend@~4.0.1:
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
xterm-for-react@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/xterm-for-react/-/xterm-for-react-1.0.4.tgz#6b35b9b037a0f9d979e7b57bb1d7c6ab7565b380"
integrity sha512-DCkLR9ZXeW907YyyaCTk/3Ol34VRHfCnf3MAPOkj3dUNA85sDqHvTXN8efw4g7bx7gWdJQRsEpGt2tJOXKG3EQ==
dependencies:
prop-types "^15.7.2"
xterm "^4.5.0"
xterm@^4.5.0:
version "4.19.0"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.19.0.tgz#c0f9d09cd61de1d658f43ca75f992197add9ef6d"
integrity sha512-c3Cp4eOVsYY5Q839dR5IejghRPpxciGmLWWaP9g+ppfMeBChMeLa1DCA+pmX/jyDZ+zxFOmlJL/82qVdayVoGQ==
y18n@^3.2.1: y18n@^3.2.1:
version "3.2.2" version "3.2.2"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696"

Loading…
Cancel
Save