From c4ce144be2dc62ab9fac323904ea02c66d6c0b64 Mon Sep 17 00:00:00 2001 From: Pig Fang Date: Sun, 1 Mar 2020 22:07:45 +0800 Subject: [PATCH] make terminal window be draggable --- package.json | 1 + resources/assets/src/scripts/cli.ts | 60 ------------------ resources/assets/src/scripts/cli.tsx | 75 +++++++++++++++++++++++ resources/assets/src/styles/terminal.scss | 7 ++- yarn.lock | 15 ++++- 5 files changed, 96 insertions(+), 62 deletions(-) delete mode 100644 resources/assets/src/scripts/cli.ts create mode 100644 resources/assets/src/scripts/cli.tsx diff --git a/package.json b/package.json index 572ae1b2..a6b2a4a9 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/resources/assets/src/scripts/cli.ts b/resources/assets/src/scripts/cli.ts deleted file mode 100644 index 224925df..00000000 --- a/resources/assets/src/scripts/cli.ts +++ /dev/null @@ -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) -} diff --git a/resources/assets/src/scripts/cli.tsx b/resources/assets/src/scripts/cli.tsx new file mode 100644 index 00000000..3104c881 --- /dev/null +++ b/resources/assets/src/scripts/cli.tsx @@ -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(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 ( + +
+
+
+

Blessing Skin Shell

+ +
+
+
+
+
+ ) +} + +export function launch() { + if (launched) { + return + } + + const container = document.createElement('div') + document.body.appendChild(container) + + const handleClose = () => { + ReactDOM.unmountComponentAtNode(container) + container.remove() + } + + ReactDOM.render(, container) +} diff --git a/resources/assets/src/styles/terminal.scss b/resources/assets/src/styles/terminal.scss index cf74bc90..a615699e 100644 --- a/resources/assets/src/styles/terminal.scss +++ b/resources/assets/src/styles/terminal.scss @@ -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; +} diff --git a/yarn.lock b/yarn.lock index 6aa5372f..30fa465d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"