rdesktop2
filip mertens 1 year ago
parent 297c476b21
commit 731aecd556
  1. 5
      apps/remix-ide/src/app/panels/terminal.js
  2. 4
      apps/remix-ide/src/app/plugins/electron/isoGitPlugin.ts
  3. 1
      apps/remixdesktop/src/plugins/fsPlugin.ts
  4. 12
      apps/remixdesktop/src/plugins/xtermPlugin.ts
  5. 1
      libs/remix-ui/app/src/lib/remix-app/remix-app.tsx
  6. 7
      libs/remix-ui/panel/src/lib/dragbar/dragbar.tsx
  7. 11
      libs/remix-ui/xterm/src/lib/components/remix-ui-xterm.tsx
  8. 130
      libs/remix-ui/xterm/src/lib/components/remix-ui-xterminals.tsx
  9. 46
      libs/remix-ui/xterm/src/lib/css/index.css

@ -9,6 +9,7 @@ import vm from 'vm'
const EventManager = require('../../lib/events') const EventManager = require('../../lib/events')
import { CompilerImports } from '@remix-project/core-plugin' // eslint-disable-line import { CompilerImports } from '@remix-project/core-plugin' // eslint-disable-line
import { RemixUiXterminals } from '@remix-ui/xterm'
const KONSOLES = [] const KONSOLES = []
@ -113,7 +114,9 @@ class Terminal extends Plugin {
} }
updateComponent(state) { updateComponent(state) {
return <RemixUiTerminal return isElectron() ? <RemixUiXterminals onReady={state.onReady} plugin={state.plugin}>
</RemixUiXterminals>
: <RemixUiTerminal
plugin={state.plugin} plugin={state.plugin}
onReady={state.onReady} onReady={state.onReady}
/> />

@ -16,9 +16,9 @@ export class isoGitPlugin extends ElectronPlugin {
setTimeout(async () => { setTimeout(async () => {
const version = await this.call('isogit', 'version') const version = await this.call('isogit', 'version')
if(version){ if(version){
this.call('terminal', 'log', version) //this.call('terminal', 'log', version)
}else{ }else{
this.call('terminal', 'log', 'Git is not installed on the system. Using builtin git instead. Performance will be affected. It is better to install git on the system and configure the credentials to connect to GitHub etc.') //this.call('terminal', 'log', 'Git is not installed on the system. Using builtin git instead. Performance will be affected. It is better to install git on the system and configure the credentials to connect to GitHub etc.')
} }

@ -138,7 +138,6 @@ class FSPluginClient extends ElectronBasePluginClient {
withFileTypes: true, withFileTypes: true,
...options ...options
}) })
console.log('glob', files)
const result: any[] = [] const result: any[] = []
for (const file of files) { for (const file of files) {

@ -55,7 +55,7 @@ const clientProfile: Profile = {
name: 'xterm', name: 'xterm',
displayName: 'xterm', displayName: 'xterm',
description: 'xterm plugin', description: 'xterm plugin',
methods: ['createTerminal', 'close', 'keystroke'] methods: ['createTerminal', 'close', 'keystroke', 'getShells']
} }
class XtermPluginClient extends ElectronBasePluginClient { class XtermPluginClient extends ElectronBasePluginClient {
@ -65,13 +65,23 @@ class XtermPluginClient extends ElectronBasePluginClient {
super(webContentsId, profile) super(webContentsId, profile)
this.onload(() => { this.onload(() => {
console.log('XtermPluginClient onload') console.log('XtermPluginClient onload')
this.emit('loaded')
}) })
} }
async onActivation(): Promise<void> {
console.log('XtermPluginClient onActivation')
}
async keystroke(key: string, pid: number): Promise<void> { async keystroke(key: string, pid: number): Promise<void> {
this.terminals[pid].write(key) this.terminals[pid].write(key)
} }
async getShells(): Promise<string[]> {
return [defaultShell]
}
async createTerminal(path?: string): Promise<number> { async createTerminal(path?: string): Promise<number> {
const shell = defaultShell; const shell = defaultShell;

@ -91,7 +91,6 @@ 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"

@ -16,15 +16,18 @@ const DragBar = (props: IRemixDragBarUi) => {
const nodeRef = React.useRef(null) // fix for strictmode const nodeRef = React.useRef(null) // fix for strictmode
function stopDrag (e: MouseEvent, data: any) { function stopDrag (e: MouseEvent, data: any) {
console.log('stopDrag', data)
const h = window.innerHeight - data.y const h = window.innerHeight - data.y
props.refObject.current.setAttribute('style', `height: ${h}px;`) props.refObject.current.setAttribute('style', `height: ${h}px;`)
setDragBarPosY(window.innerHeight - props.refObject.current.offsetHeight) console.log('stopDrag', `height: ${h}px;`)
setDragBarPosY(props.refObject.current.offsetTop)
setDragState(false) setDragState(false)
props.setHideStatus(false) props.setHideStatus(false)
} }
const handleResize = () => { const handleResize = () => {
console.log('handleResize', props.refObject.current)
if (!props.refObject.current) return if (!props.refObject.current) return
setDragBarPosY(window.innerHeight - props.refObject.current.offsetHeight) setDragBarPosY(props.refObject.current.offsetTop)
} }
useEffect(() => { useEffect(() => {

@ -9,6 +9,10 @@ export interface RemixUiXtermProps {
send: (data: string, pid: number) => void send: (data: string, pid: number) => void
timeStamp: number timeStamp: number
setTerminalRef: (pid: number, ref: any) => void setTerminalRef: (pid: number, ref: any) => void
theme: {
backgroundColor: string
textColor: string
}
} }
const RemixUiXterm = (props: RemixUiXtermProps) => { const RemixUiXterm = (props: RemixUiXtermProps) => {
@ -38,8 +42,11 @@ const RemixUiXterm = (props: RemixUiXtermProps) => {
return ( return (
<> <>
<button className='btn' onClick={closeTerminal}>close</button> <button className='btn d-none' onClick={closeTerminal}>close</button>
<XTerm ref={xtermRef} onData={onData} onKey={onKey}></XTerm> <XTerm
options={{theme: {background: props.theme.backgroundColor , foreground: props.theme.textColor}}}
ref={xtermRef} onData={onData}
onKey={onKey}></XTerm>
</> </>
) )

@ -2,9 +2,12 @@ import React, { useState, useEffect } from 'react' // eslint-disable-line
import { ElectronPlugin } from '@remixproject/engine-electron' import { ElectronPlugin } from '@remixproject/engine-electron'
import RemixUiXterm from './remix-ui-xterm' import RemixUiXterm from './remix-ui-xterm'
import '../css/index.css' import '../css/index.css'
import { Tab, Tabs } from 'react-bootstrap' import { Button, ButtonGroup, Dropdown, Tab, Tabs } from 'react-bootstrap'
import { CustomIconsToggle } from '@remix-ui/helper'
import { RemixUiTerminal } from '@remix-ui/terminal'
export interface RemixUiXterminalsProps { export interface RemixUiXterminalsProps {
plugin: ElectronPlugin plugin: ElectronPlugin
onReady: (api: any) => void
} }
export interface xtermState { export interface xtermState {
@ -18,12 +21,18 @@ export interface xtermState {
export const RemixUiXterminals = (props: RemixUiXterminalsProps) => { export const RemixUiXterminals = (props: RemixUiXterminalsProps) => {
const [terminals, setTerminals] = useState<xtermState[]>([]) const [terminals, setTerminals] = useState<xtermState[]>([])
const [workingDir, setWorkingDir] = useState<string>('') const [workingDir, setWorkingDir] = useState<string>('')
const [showOutput, setShowOutput] = useState<boolean>(true)
const [theme, setTheme] = useState<any>(themeCollection[0])
const [terminalsEnabled, setTerminalsEnabled] = useState<boolean>(false)
const [shells, setShells] = useState<string[]>([])
const { plugin } = props const { plugin } = props
useEffect(() => { useEffect(() => {
setTimeout(async () => { setTimeout(async () => {
plugin.on('xterm', 'loaded', async () => { plugin.on('xterm', 'loaded', async () => {
console.log('xterm loaded')
}) })
plugin.on('xterm', 'data', async (data: string, pid: number) => { plugin.on('xterm', 'data', async (data: string, pid: number) => {
writeToTerminal(data, pid) writeToTerminal(data, pid)
}) })
@ -31,17 +40,46 @@ export const RemixUiXterminals = (props: RemixUiXterminalsProps) => {
plugin.on('xterm', 'close', async (pid: number) => { plugin.on('xterm', 'close', async (pid: number) => {
setTerminals(prevState => { setTerminals(prevState => {
const removed = prevState.filter(xtermState => xtermState.pid !== pid) const removed = prevState.filter(xtermState => xtermState.pid !== pid)
if (removed.length > 0)
removed[removed.length - 1].hidden = false removed[removed.length - 1].hidden = false
if(removed.length === 0)
setShowOutput(true)
return [...removed] return [...removed]
}) })
}) })
plugin.on('fs', 'workingDirChanged', (path: string) => { plugin.on('fs', 'workingDirChanged', (path: string) => {
setWorkingDir(path) setWorkingDir(path)
setTerminalsEnabled(true)
})
plugin.on('theme', 'themeChanged', async (theme) => {
console.log('themeChanged', theme)
handleThemeChange(theme)
}) })
}, 5000)
const theme = await plugin.call('theme', 'currentTheme')
console.log('theme', theme)
handleThemeChange(theme)
const shells = await plugin.call('xterm', 'getShells')
console.log('shells', shells)
setShells(shells)
}, 2000)
}, []) }, [])
const handleThemeChange = (theme: any) => {
themeCollection.forEach((themeItem) => {
if (themeItem.themeName === theme.name) {
setTheme(themeItem)
console.log('setTheme', themeItem)
}
})
}
const writeToTerminal = (data: string, pid: number) => { const writeToTerminal = (data: string, pid: number) => {
setTerminals(prevState => { setTerminals(prevState => {
const terminal = prevState.find(xtermState => xtermState.pid === pid) const terminal = prevState.find(xtermState => xtermState.pid === pid)
@ -67,7 +105,7 @@ export const RemixUiXterminals = (props: RemixUiXterminalsProps) => {
const createTerminal = async () => { const createTerminal = async () => {
const pid = await plugin.call('xterm', 'createTerminal', workingDir) const pid = await plugin.call('xterm', 'createTerminal', workingDir)
setShowOutput(false)
setTerminals(prevState => { setTerminals(prevState => {
// set all to hidden // set all to hidden
prevState.forEach(xtermState => { prevState.forEach(xtermState => {
@ -108,28 +146,70 @@ export const RemixUiXterminals = (props: RemixUiXterminalsProps) => {
}) })
} }
const closeTerminal = () => {
const pid = terminals.find(xtermState => xtermState.hidden === false).pid
if (pid)
plugin.call('xterm', 'close', pid)
}
const selectOutput = () => {
setShowOutput(true)
}
const showTerminal = () => {
setShowOutput(false)
if (terminals.length === 0) createTerminal()
}
return (<> return (<>
<div className='xterm-panel'> <div className='xterm-panel'>
<button className='btn btn-sm btn-secondary' onClick={() => { <div className='xterm-panel-header bg-light'>
createTerminal() <div className='xterm-panel-header-left p-1'>
}}>open new terminal</button> <button className={`btn btn-sm btn-secondary mr-2 ${!showOutput ? 'xterm-btn-none' : 'xterm-btn-active'}`} onClick={selectOutput}>ouput</button>
<button className={`btn btn-sm btn-secondary ${terminalsEnabled ? '' : 'd-none'} ${showOutput ? 'xterm-btn-none' : 'xterm-btn-active'}`} onClick={showTerminal}><span className="far fa-terminal border-0 ml-1"></span></button>
</div>
<div className={`xterm-panel-header-right ${showOutput ? 'd-none' : ''}`}>
<Dropdown as={ButtonGroup}>
<button className="btn btn-sm btn-secondary" onClick={createTerminal}><span className="far fa-plus border-0 p-0 m-0"></span></button>
<div className='remix-ui-xterminals-container'>
<>
{terminals.map((xtermState, index) => {
return (<button onClick={async () => selectTerminal(xtermState)} className={`btn btn-sm btn-secondary ${xtermState.hidden ? 'xterm-btn-none' : 'xterm-btn-active'}`}>Terminal {index + 1}</button>) <Dropdown.Toggle split variant="secondary" id="dropdown-split-basic" />
<Dropdown.Menu className='custom-dropdown-items remixui_menuwidth'>
{shells.map((shell, index) => {
return (<Dropdown.Item index={index} onClick={createTerminal}>{shell}</Dropdown.Item>)
})} })}
</Dropdown.Menu>
</Dropdown>
<button className="btn ml-2 btn-sm btn-secondary" onClick={closeTerminal}><span className="far fa-trash border-0 ml-1"></span></button>
</div>
</div>
<div className='remix-ui-xterminals-container'>
<>
<div className={`${!showOutput ? 'd-none' : 'd-block w-100'} `}>
<RemixUiTerminal
plugin={props.plugin}
onReady={props.onReady} />
</div>
<div className={`remix-ui-xterminals-section ${showOutput ? 'd-none' : 'd-flex'} `}>
{terminals.map((xtermState) => { {terminals.map((xtermState) => {
return ( return (
<div className={xtermState.hidden ? 'hide-xterm' : 'show-xterm'} key={xtermState.pid} data-id={`remixUIXT${xtermState.pid}`}> <div className={`xterm-terminal ${xtermState.hidden ? 'hide-xterm' : 'show-xterm'}`} key={xtermState.pid} data-id={`remixUIXT${xtermState.pid}`}>
<RemixUiXterm setTerminalRef={setTerminalRef} timeStamp={xtermState.timeStamp} send={send} pid={xtermState.pid} plugin={plugin}></RemixUiXterm> <RemixUiXterm theme={theme} setTerminalRef={setTerminalRef} timeStamp={xtermState.timeStamp} send={send} pid={xtermState.pid} plugin={plugin}></RemixUiXterm>
</div> </div>
) )
})} })}
<div className='remix-ui-xterminals-buttons border-left'>
{terminals.map((xtermState, index) => {
return (<button onClick={async () => selectTerminal(xtermState)} className={`btn btn-sm mt-2 btn-secondary ${xtermState.hidden ? 'xterm-btn-none' : 'xterm-btn-active'}`}><span className="fa fa-terminal border-0 p-0 m-0"></span></button>)
})}
</div>
</div>
</> </>
</div> </div>
</div> </div>
@ -138,3 +218,29 @@ export const RemixUiXterminals = (props: RemixUiXterminalsProps) => {
</>) </>)
} }
const themeCollection = [
{ themeName: 'HackerOwl', backgroundColor: '#011628', textColor: '#babbcc',
shapeColor: '#8694a1',fillColor: '#011C32'},
{ themeName: 'Cerulean', backgroundColor: '#ffffff', textColor: '#343a40',
shapeColor: '#343a40',fillColor: '#f8f9fa'},
{ themeName: 'Cyborg', backgroundColor: '#060606', textColor: '#adafae',
shapeColor: '#adafae', fillColor: '#222222'},
{ themeName: 'Dark', backgroundColor: '#222336', textColor: '#babbcc',
shapeColor: '#babbcc',fillColor: '#2a2c3f'},
{ themeName: 'Flatly', backgroundColor: '#ffffff', textColor: '#343a40',
shapeColor: '#7b8a8b',fillColor: '#ffffff'},
{ themeName: 'Black', backgroundColor: '#1a1a1a', textColor: '#babbcc',
shapeColor: '#b5b4bc',fillColor: '#1f2020'},
{ themeName: 'Light', backgroundColor: '#eef1f6', textColor: '#3b445e',
shapeColor: '#343a40',fillColor: '#ffffff'},
{ themeName: 'Midcentury', backgroundColor: '#DBE2E0', textColor: '#11556c',
shapeColor: '#343a40',fillColor: '#eeede9'},
{ themeName: 'Spacelab', backgroundColor: '#ffffff', textColor: '#343a40',
shapeColor: '#333333', fillColor: '#eeeeee'},
{ themeName: 'Candy', backgroundColor: '#d5efff', textColor: '#11556c',
shapeColor: '#343a40',fillColor: '#fbe7f8' },
{ themeName: 'Violet', backgroundColor: '#f1eef6', textColor: '#3b445e',
shapeColor: '#343a40',fillColor: '#f8fafe' },
{ themeName: 'Pride', backgroundColor: '#f1eef6', textColor: '#343a40',
shapeColor: '#343a40',fillColor: '#f8fafe' },
]

@ -1,7 +1,12 @@
.remix-ui-xterminals-container { .remix-ui-xterminals-container {
overflow: scroll; display: flex;
flex-direction: row;
} }
.xterm-panel { .xterm-panel {
}
.remix-ui-xterminals-buttons {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
@ -20,3 +25,42 @@
.xterm-btn-none { .xterm-btn-none {
background-color: var(--secondary); background-color: var(--secondary);
} }
.xterm-terminal {
flex-grow: 1;
height: 100%;
width: 100%;
}
.xterm-panel-header-right {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-self: flex-end;
}
.xterm-panel-header {
display: flex;
flex-direction: row;
}
.xterm-panel-header-left {
display: flex;
flex-direction: row;
flex-grow: 1;
}
.remix-ui-xterminals-section {
display: flex;
flex-direction: row;
width: 100%;
z-index: 3;
}
.hide-terminals {
width: 0;
}
.show-terminals {
width: 100%;
}

Loading…
Cancel
Save