make terminal window be draggable

This commit is contained in:
Pig Fang 2020-03-01 22:07:45 +08:00
parent 60373e6290
commit c4ce144be2
5 changed files with 96 additions and 62 deletions

View File

@ -28,6 +28,7 @@
"nanoid": "^2.1.11",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-draggable": "^4.2.0",
"react-hot-loader": "^4.12.18",
"rxjs": "^6.5.3",
"skinview3d": "^1.2.1",

View File

@ -1,60 +0,0 @@
import { Terminal } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'
import { Shell } from 'blessing-skin-shell'
import 'xterm/css/xterm.css'
import styles from '@/styles/terminal.scss'
let launched = false
export function launch() {
if (launched) {
return
}
const card = document.createElement('div')
card.className = `card ${styles.terminal}`
const header = document.createElement('div')
header.className = 'card-header'
const headerStuff = document.createElement('div')
headerStuff.className = 'd-flex justify-content-between'
const title = document.createElement('h4')
title.className = 'card-title mt-1'
title.textContent = 'Blessing Skin Shell'
headerStuff.appendChild(title)
const btnClose = document.createElement('button')
btnClose.innerHTML = '×'
btnClose.className = 'btn btn-default'
headerStuff.appendChild(btnClose)
header.appendChild(headerStuff)
card.appendChild(header)
const body = document.createElement('div')
body.className = 'card-body p-2'
body.style.backgroundColor = '#000'
const container = document.createElement('div')
body.appendChild(container)
card.appendChild(body)
document.body.appendChild(card)
const terminal = new Terminal()
const fitAddon = new FitAddon()
terminal.loadAddon(fitAddon)
terminal.setOption('fontFamily', 'Monaco, Consolas, "Roboto Mono", "Noto Sans", "Droid Sans Mono"')
terminal.open(container)
fitAddon.fit()
const shell = new Shell(terminal)
const unbind = terminal.onData(e => shell.input(e))
launched = true
const handleClose = () => {
unbind.dispose()
shell.free()
fitAddon.dispose()
terminal.dispose()
btnClose.removeEventListener('click', handleClose)
card.remove()
launched = false
}
btnClose.addEventListener('click', handleClose)
}

View File

@ -0,0 +1,75 @@
import React, { useEffect, useRef } from 'react'
import ReactDOM from 'react-dom'
import { Terminal } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'
import { Shell } from 'blessing-skin-shell'
import 'xterm/css/xterm.css'
import Draggable from 'react-draggable'
import styles from '@/styles/terminal.scss'
let launched = false
const TerminalWindow: React.FC<{ onClose(): void }> = props => {
const mount = useRef<HTMLDivElement>(null)
useEffect(() => {
const el = mount.current
if (!el) {
return
}
const terminal = new Terminal()
const fitAddon = new FitAddon()
terminal.loadAddon(fitAddon)
terminal.setOption(
'fontFamily',
'Monaco, Consolas, "Roboto Mono", "Noto Sans", "Droid Sans Mono"',
)
terminal.open(el)
fitAddon.fit()
const shell = new Shell(terminal)
const unbind = terminal.onData(e => shell.input(e))
launched = true
return () => {
unbind.dispose()
shell.free()
fitAddon.dispose()
terminal.dispose()
launched = false
}
}, [])
return (
<Draggable handle=".card-header">
<div className={`card ${styles.terminal}`}>
<div className="card-header">
<div className="d-flex justify-content-between">
<h4 className="card-title mt-1">Blessing Skin Shell</h4>
<button className="btn btn-default" onClick={props.onClose}>
&times;
</button>
</div>
</div>
<div className={`card-body p-2 ${styles.body}`} ref={mount}></div>
</div>
</Draggable>
)
}
export function launch() {
if (launched) {
return
}
const container = document.createElement('div')
document.body.appendChild(container)
const handleClose = () => {
ReactDOM.unmountComponentAtNode(container)
container.remove()
}
ReactDOM.render(<TerminalWindow onClose={handleClose} />, container)
}

View File

@ -3,7 +3,8 @@
.terminal {
z-index: 1060;
position: fixed;
bottom: 0;
bottom: 7vh;
user-select: none;
@include breakpoints.greater-than('xl') {
left: 25vw;
@ -23,3 +24,7 @@
height: 35vh;
}
}
.body {
background-color: #000;
}

View File

@ -2791,6 +2791,11 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
classnames@^2.2.5:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
cli-cursor@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
@ -8229,7 +8234,7 @@ prompts@^2.0.1:
kleur "^3.0.2"
sisteransi "^1.0.0"
prop-types@^15.6.1, prop-types@^15.6.2:
prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@ -8417,6 +8422,14 @@ react-dom@^16.12.0:
prop-types "^15.6.2"
scheduler "^0.18.0"
react-draggable@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.2.0.tgz#40cc5209082ca7d613104bf6daf31372cc0e1114"
integrity sha512-5wFq//gEoeTYprnd4ze8GrFc+Rbnx+9RkOMR3vk4EbWxj02U6L6T3yrlKeiw4X5CtjD2ma2+b3WujghcXNRzkw==
dependencies:
classnames "^2.2.5"
prop-types "^15.6.0"
react-hot-loader@^4.12.18:
version "4.12.18"
resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.12.18.tgz#a9029e34af2690d76208f9a35189d73c2dfea6a7"