@electerm/electerm-react 1.34.68 → 1.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/common/constants.js +3 -1
- package/client/common/key-pressed.js +1 -1
- package/client/common/rand-hex-color.js +28 -0
- package/client/common/shortcuts-defaults.js +51 -0
- package/client/components/batch-op/batch-op.jsx +6 -2
- package/client/components/bookmark-form/color-picker-item.jsx +14 -0
- package/client/components/bookmark-form/color-picker.jsx +90 -0
- package/client/components/bookmark-form/color-picker.styl +20 -0
- package/client/components/bookmark-form/form-ssh-common.jsx +4 -0
- package/client/components/bookmark-form/hex-input.jsx +39 -0
- package/client/components/bookmark-form/local-form-ui.jsx +1 -0
- package/client/components/bookmark-form/serial-form-ui.jsx +12 -8
- package/client/components/bookmark-form/ssh-form-ui.jsx +3 -0
- package/client/components/bookmark-form/telnet-form-ui.jsx +1 -0
- package/client/components/bookmark-form/use-ui.jsx +11 -1
- package/client/components/context-menu/context-menu.styl +1 -1
- package/client/components/context-menu/menu-btn.jsx +6 -3
- package/client/components/main/custom-css.jsx +28 -0
- package/client/components/main/main.jsx +5 -2
- package/client/components/session/session.jsx +11 -35
- package/client/components/session/sessions.jsx +15 -15
- package/client/components/setting-panel/setting.jsx +20 -32
- package/client/components/setting-panel/tab-settings.jsx +13 -10
- package/client/components/sftp/transfer-tag.jsx +2 -2
- package/client/components/sftp/transport-action.jsx +1 -0
- package/client/components/shortcuts/get-key-char.js +45 -0
- package/client/components/shortcuts/shortcut-control.jsx +63 -0
- package/client/components/shortcuts/shortcut-editor.jsx +194 -0
- package/client/components/shortcuts/shortcut-handler.js +76 -0
- package/client/components/shortcuts/shortcut.styl +0 -0
- package/client/components/shortcuts/shortcuts-defaults.js +87 -0
- package/client/components/shortcuts/shortcuts.jsx +166 -0
- package/client/components/sidebar/index.jsx +1 -1
- package/client/components/sidebar/transfer-history-modal.jsx +14 -2
- package/client/components/tabs/index.jsx +0 -25
- package/client/components/tabs/tab.jsx +6 -5
- package/client/components/terminal/index.jsx +93 -110
- package/client/components/terminal/term-search.jsx +9 -21
- package/client/components/terminal-theme/index.jsx +4 -3
- package/client/store/index.js +17 -2
- package/client/store/init-state.js +1 -8
- package/client/store/item.js +3 -0
- package/client/store/session.js +0 -22
- package/client/store/watch.js +3 -1
- package/client/views/index.pug +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
export default () => {
|
|
2
|
+
return [
|
|
3
|
+
{
|
|
4
|
+
name: 'app_closeCurrentTab',
|
|
5
|
+
shortcut: 'ctrl+w',
|
|
6
|
+
shortcutMac: 'ctrl+w'
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
name: 'app_newBookmark',
|
|
10
|
+
shortcut: 'ctrl+b',
|
|
11
|
+
shortcutMac: 'meta+b'
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: 'app_togglefullscreen',
|
|
15
|
+
shortcut: 'alt+f',
|
|
16
|
+
shortcutMac: 'alt+f'
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'app_zoomin',
|
|
20
|
+
shortcut: 'ctrl+=',
|
|
21
|
+
shortcutMac: 'meta+='
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'app_zoomout',
|
|
25
|
+
shortcut: 'ctrl+-',
|
|
26
|
+
shortcutMac: 'meta+-'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'app_prevTab',
|
|
30
|
+
shortcut: 'ctrl+shift+tab',
|
|
31
|
+
shortcutMac: 'ctrl+shift+tab'
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'app_nextTab',
|
|
35
|
+
shortcut: 'ctrl+tab',
|
|
36
|
+
shortcutMac: 'ctrl+tab'
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'terminal_clear',
|
|
40
|
+
shortcut: 'ctrl+l,ctrl+shift+l',
|
|
41
|
+
shortcutMac: 'meta+l'
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'terminal_selectAll',
|
|
45
|
+
shortcut: 'ctrl+a,ctrl+shift+a',
|
|
46
|
+
shortcutMac: 'meta+a',
|
|
47
|
+
readonly: true
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'terminal_copy',
|
|
51
|
+
shortcut: 'ctrl+c,ctrl+shift+c',
|
|
52
|
+
shortcutMac: 'meta+c',
|
|
53
|
+
readonly: true
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'terminal_paste',
|
|
57
|
+
shortcut: 'ctrl+v,ctrl+shift+v',
|
|
58
|
+
shortcutMac: 'meta+v',
|
|
59
|
+
readonly: true
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'terminal_search',
|
|
63
|
+
shortcut: 'ctrl+f',
|
|
64
|
+
shortcutMac: 'meta+f'
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
name: 'terminal_pasteSelected',
|
|
68
|
+
shortcut: 'alt+insert',
|
|
69
|
+
shortcutMac: 'alt+insert'
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: 'terminal_showNormalBuffer',
|
|
73
|
+
shortcut: 'ctrl+ArrowUp',
|
|
74
|
+
shortcutMac: 'meta+↑'
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'terminal_zoominTerminal',
|
|
78
|
+
shortcut: 'ctrl+▲',
|
|
79
|
+
shortcutMac: 'meta+▲'
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'terminal_zoomoutTerminal',
|
|
83
|
+
shortcut: 'ctrl+▼',
|
|
84
|
+
shortcutMac: 'meta+▼'
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { Component } from '../common/react-subx'
|
|
2
|
+
import shortcutsDefaultsGen from './shortcuts-defaults'
|
|
3
|
+
import ShortcutEdit from './shortcut-editor'
|
|
4
|
+
import deepCopy from 'json-deep-copy'
|
|
5
|
+
import {
|
|
6
|
+
Table,
|
|
7
|
+
Button
|
|
8
|
+
} from 'antd'
|
|
9
|
+
import {
|
|
10
|
+
isMacJs as isMac
|
|
11
|
+
} from '../../common/constants.js'
|
|
12
|
+
|
|
13
|
+
const { prefix } = window
|
|
14
|
+
const e = prefix('form')
|
|
15
|
+
const c = prefix('control')
|
|
16
|
+
const m = prefix('menu')
|
|
17
|
+
const ss = prefix('ssh')
|
|
18
|
+
const s = prefix('setting')
|
|
19
|
+
const shortcutsDefaults = shortcutsDefaultsGen()
|
|
20
|
+
|
|
21
|
+
export default class Shortcuts extends Component {
|
|
22
|
+
handleResetAll = () => {
|
|
23
|
+
this.props.store.updateConfig({
|
|
24
|
+
shortcuts: {}
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
updateConfig = (name, value) => {
|
|
29
|
+
const { store } = this.props
|
|
30
|
+
const shortcuts = deepCopy(store.config.shortcuts || {})
|
|
31
|
+
shortcuts[name] = value
|
|
32
|
+
this.props.store.updateConfig({
|
|
33
|
+
shortcuts
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
getData () {
|
|
38
|
+
const { shortcuts = {} } = this.props.store.config
|
|
39
|
+
return shortcutsDefaults.map((c, i) => {
|
|
40
|
+
const propName = isMac ? 'shortcutMac' : 'shortcut'
|
|
41
|
+
const name = c.name + '_' + propName
|
|
42
|
+
return {
|
|
43
|
+
index: i + 1,
|
|
44
|
+
name,
|
|
45
|
+
readonly: c.readonly,
|
|
46
|
+
shortcut: c.readonly ? c[propName] : (shortcuts[name] || c[propName])
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
getKeysTakenData = () => {
|
|
52
|
+
const { shortcuts = {} } = this.props.store.config
|
|
53
|
+
return shortcutsDefaults
|
|
54
|
+
.reduce((p, k) => {
|
|
55
|
+
const propName = isMac ? 'shortcutMac' : 'shortcut'
|
|
56
|
+
const name = k.name + '_' + propName
|
|
57
|
+
const vv = k.readonly ? k[propName] : (shortcuts[name] || k[propName])
|
|
58
|
+
const v = vv
|
|
59
|
+
.split(',')
|
|
60
|
+
.map(f => f.trim())
|
|
61
|
+
.reduce((p, k, i) => {
|
|
62
|
+
return {
|
|
63
|
+
...p,
|
|
64
|
+
[k]: true
|
|
65
|
+
}
|
|
66
|
+
}, {})
|
|
67
|
+
return {
|
|
68
|
+
...p,
|
|
69
|
+
...v
|
|
70
|
+
}
|
|
71
|
+
}, {})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
render () {
|
|
75
|
+
const { store } = this.props
|
|
76
|
+
const columns = [
|
|
77
|
+
{
|
|
78
|
+
title: 'NO.',
|
|
79
|
+
dataIndex: 'index',
|
|
80
|
+
key: 'index',
|
|
81
|
+
render: (index) => {
|
|
82
|
+
return index
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
title: e('description'),
|
|
87
|
+
dataIndex: 'name',
|
|
88
|
+
key: 'name',
|
|
89
|
+
render: (name) => {
|
|
90
|
+
const [a, b] = name.split('_')
|
|
91
|
+
const pre = a === 'terminal' ? `[${ss('terminal')}] ` : ''
|
|
92
|
+
if (
|
|
93
|
+
[
|
|
94
|
+
'clear', 'selectAll', 'search'
|
|
95
|
+
].includes(b)
|
|
96
|
+
) {
|
|
97
|
+
return pre + ss(b)
|
|
98
|
+
} else if (b === 'copy') {
|
|
99
|
+
return pre + m(b)
|
|
100
|
+
} else if (b === 'newBookmark') {
|
|
101
|
+
return pre + c(b)
|
|
102
|
+
} else if (b.includes('zoomin')) {
|
|
103
|
+
return pre + m('zoomin')
|
|
104
|
+
} else if (b.includes('zoomout')) {
|
|
105
|
+
return pre + m('zoomout')
|
|
106
|
+
} else if (['togglefullscreen'].includes(b)) {
|
|
107
|
+
return pre + m(b)
|
|
108
|
+
} else {
|
|
109
|
+
return pre + s(b)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
title: s('shortcut'),
|
|
115
|
+
dataIndex: 'shortcut',
|
|
116
|
+
key: 'shortcut',
|
|
117
|
+
render: (shortcut, inst) => {
|
|
118
|
+
const { readonly } = inst
|
|
119
|
+
if (readonly) {
|
|
120
|
+
return (
|
|
121
|
+
<span className='readonly'>
|
|
122
|
+
{
|
|
123
|
+
shortcut.split(',').map(s => {
|
|
124
|
+
return (
|
|
125
|
+
<span className='shortcut-unit' key={s}>{s}</span>
|
|
126
|
+
)
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
</span>
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
return (
|
|
133
|
+
<ShortcutEdit
|
|
134
|
+
data={inst}
|
|
135
|
+
keysTaken={this.getKeysTakenData()}
|
|
136
|
+
store={store}
|
|
137
|
+
updateConfig={this.updateConfig}
|
|
138
|
+
/>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
const props = {
|
|
144
|
+
dataSource: this.getData(),
|
|
145
|
+
columns,
|
|
146
|
+
bordered: true,
|
|
147
|
+
pagination: false,
|
|
148
|
+
size: 'small',
|
|
149
|
+
rowKey: 'id'
|
|
150
|
+
}
|
|
151
|
+
return (
|
|
152
|
+
<div>
|
|
153
|
+
<Table
|
|
154
|
+
{...props}
|
|
155
|
+
/>
|
|
156
|
+
<div className='pd1y'>
|
|
157
|
+
<Button
|
|
158
|
+
onClick={this.handleResetAll}
|
|
159
|
+
>
|
|
160
|
+
{s('resetAllToDefault')}
|
|
161
|
+
</Button>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -116,7 +116,7 @@ export default class Sidebar extends Component {
|
|
|
116
116
|
>
|
|
117
117
|
<div className='sidebar-bar btns'>
|
|
118
118
|
<div className='control-icon-wrap'>
|
|
119
|
-
<MenuBtn store={store} />
|
|
119
|
+
<MenuBtn store={store} config={store.config} />
|
|
120
120
|
</div>
|
|
121
121
|
<SideIcon
|
|
122
122
|
title={e('newBookmark')}
|
|
@@ -22,12 +22,20 @@ const sorterFactory = prop => {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
export default class TransferHistoryModal extends Component {
|
|
25
|
+
state = {
|
|
26
|
+
pageSize: 5
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
handlePageSizeChange = (page, pageSize) => {
|
|
30
|
+
this.setState({ pageSize })
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
render () {
|
|
26
34
|
const {
|
|
27
35
|
getTransferHistory,
|
|
28
36
|
clearTransferHistory
|
|
29
37
|
} = this.props.store
|
|
30
|
-
const transferHistory = getTransferHistory()
|
|
38
|
+
const transferHistory = getTransferHistory().filter(d => !d.unzip)
|
|
31
39
|
const columns = [{
|
|
32
40
|
title: e('startTime'),
|
|
33
41
|
dataIndex: 'startTime',
|
|
@@ -88,7 +96,11 @@ export default class TransferHistoryModal extends Component {
|
|
|
88
96
|
columns,
|
|
89
97
|
bordered: true,
|
|
90
98
|
pagination: {
|
|
91
|
-
pageSize:
|
|
99
|
+
pageSize: this.state.pageSize,
|
|
100
|
+
showSizeChanger: true,
|
|
101
|
+
pageSizeOptions: [5, 10, 20, 50, 100],
|
|
102
|
+
onChange: this.handlePageSizeChange,
|
|
103
|
+
position: ['topRight']
|
|
92
104
|
},
|
|
93
105
|
size: 'small',
|
|
94
106
|
rowKey: 'id'
|
|
@@ -42,7 +42,6 @@ export default class Tabs extends React.Component {
|
|
|
42
42
|
const {
|
|
43
43
|
tabsRef
|
|
44
44
|
} = this
|
|
45
|
-
window.addEventListener('keypress', this.handleTabHotkey)
|
|
46
45
|
tabsRef.current.addEventListener('dblclick', this.handleDblClickEvent)
|
|
47
46
|
tabsRef.current.addEventListener('mousedown', this.handleClickEvent)
|
|
48
47
|
}
|
|
@@ -58,14 +57,6 @@ export default class Tabs extends React.Component {
|
|
|
58
57
|
}
|
|
59
58
|
}
|
|
60
59
|
|
|
61
|
-
// componentWillUnmount () {
|
|
62
|
-
// const {
|
|
63
|
-
// tabsRef
|
|
64
|
-
// } = this
|
|
65
|
-
// window.removeEventListener('keydown', this.handleTabHotkey)
|
|
66
|
-
// tabsRef.current.removeEventListener('mousedown', this.handleClickEvent)
|
|
67
|
-
// }
|
|
68
|
-
|
|
69
60
|
tabsWidth = () => {
|
|
70
61
|
return Array.from(
|
|
71
62
|
document.querySelectorAll('.tab')
|
|
@@ -83,22 +74,6 @@ export default class Tabs extends React.Component {
|
|
|
83
74
|
return width < (tabsWidthAll + addBtnWidth)
|
|
84
75
|
}
|
|
85
76
|
|
|
86
|
-
handleTabHotkey = e => {
|
|
87
|
-
if (
|
|
88
|
-
e.ctrlKey &&
|
|
89
|
-
e.code === 'Tab' &&
|
|
90
|
-
!e.shiftKey
|
|
91
|
-
) {
|
|
92
|
-
window.store.clickNextTab()
|
|
93
|
-
} else if (
|
|
94
|
-
e.ctrlKey &&
|
|
95
|
-
e.code === 'Tab' &&
|
|
96
|
-
e.shiftKey
|
|
97
|
-
) {
|
|
98
|
-
window.store.clickPrevTab()
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
77
|
handleClickEvent = (e) => {
|
|
103
78
|
if (e.button === 1) {
|
|
104
79
|
const p = findParentBySel(e.target, '.tab')
|
|
@@ -19,7 +19,6 @@ import createName from '../../common/create-title'
|
|
|
19
19
|
import { addClass, removeClass } from '../../common/class'
|
|
20
20
|
import {
|
|
21
21
|
terminalSshConfigType,
|
|
22
|
-
ctrlOrCmd,
|
|
23
22
|
commonActions
|
|
24
23
|
} from '../../common/constants'
|
|
25
24
|
|
|
@@ -255,8 +254,7 @@ export default class Tab extends React.Component {
|
|
|
255
254
|
res.push({
|
|
256
255
|
func: 'handleClose',
|
|
257
256
|
icon: 'CloseOutlined',
|
|
258
|
-
text: e('close')
|
|
259
|
-
subText: `${ctrlOrCmd} + W`
|
|
257
|
+
text: e('close')
|
|
260
258
|
})
|
|
261
259
|
res.push({
|
|
262
260
|
func: 'closeOther',
|
|
@@ -359,7 +357,7 @@ export default class Tab extends React.Component {
|
|
|
359
357
|
} = this.props
|
|
360
358
|
const { isLast } = this.props
|
|
361
359
|
const { tab, terminalOnData } = this.state
|
|
362
|
-
const { id, isEditting, status, isTransporting, tabCount } = tab
|
|
360
|
+
const { id, isEditting, status, isTransporting, tabCount, color } = tab
|
|
363
361
|
const active = id === currentTabId
|
|
364
362
|
const cls = classnames(
|
|
365
363
|
`tab-${id}`,
|
|
@@ -380,6 +378,9 @@ export default class Tab extends React.Component {
|
|
|
380
378
|
if (isEditting) {
|
|
381
379
|
return this.renderEditting(tab, cls)
|
|
382
380
|
}
|
|
381
|
+
const styleTag = color
|
|
382
|
+
? { color }
|
|
383
|
+
: {}
|
|
383
384
|
return (
|
|
384
385
|
<Tooltip
|
|
385
386
|
title={title}
|
|
@@ -412,7 +413,7 @@ export default class Tab extends React.Component {
|
|
|
412
413
|
onClick={this.handleReloadTab}
|
|
413
414
|
title={m('reload')}
|
|
414
415
|
/>
|
|
415
|
-
{tabCount}. {title}
|
|
416
|
+
<span style={styleTag}>♦</span> {tabCount}. {title}
|
|
416
417
|
</div>
|
|
417
418
|
<div className={'tab-status ' + status} />
|
|
418
419
|
<div className='tab-traffic' />
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
CheckCircleOutlined,
|
|
11
11
|
ReloadOutlined
|
|
12
12
|
} from '@ant-design/icons'
|
|
13
|
-
|
|
14
13
|
import {
|
|
15
14
|
notification,
|
|
16
15
|
Spin,
|
|
@@ -26,7 +25,6 @@ import {
|
|
|
26
25
|
paneMap,
|
|
27
26
|
typeMap,
|
|
28
27
|
isWin,
|
|
29
|
-
isMac,
|
|
30
28
|
terminalSshConfigType,
|
|
31
29
|
transferTypeMap,
|
|
32
30
|
terminalActions,
|
|
@@ -47,13 +45,12 @@ import getProxy from '../../common/get-proxy'
|
|
|
47
45
|
import { Zmodem, AddonZmodem } from './xterm-zmodem'
|
|
48
46
|
import { Unicode11Addon } from 'xterm-addon-unicode11'
|
|
49
47
|
import keyControlPressed from '../../common/key-control-pressed'
|
|
50
|
-
import keyShiftPressed from '../../common/key-shift-pressed'
|
|
51
|
-
import keyPressed from '../../common/key-pressed'
|
|
52
48
|
import { Terminal } from 'xterm'
|
|
53
49
|
import * as ls from '../../common/safe-local-storage'
|
|
54
50
|
import NormalBuffer from './normal-buffer'
|
|
55
51
|
import { createTerm, resizeTerm } from './terminal-apis'
|
|
56
52
|
import createLsId from './build-ls-term-id'
|
|
53
|
+
import { shortcutExtend, shortcutDescExtend } from '../shortcuts/shortcut-handler.js'
|
|
57
54
|
|
|
58
55
|
const { prefix } = window
|
|
59
56
|
const e = prefix('ssh')
|
|
@@ -70,7 +67,7 @@ const computePos = (e) => {
|
|
|
70
67
|
}
|
|
71
68
|
}
|
|
72
69
|
|
|
73
|
-
|
|
70
|
+
class Term extends Component {
|
|
74
71
|
constructor (props) {
|
|
75
72
|
super(props)
|
|
76
73
|
this.state = {
|
|
@@ -223,13 +220,58 @@ export default class Term extends Component {
|
|
|
223
220
|
this.props.pane === paneMap.terminal
|
|
224
221
|
}
|
|
225
222
|
|
|
223
|
+
clearShortcut = (e) => {
|
|
224
|
+
e.stopPropagation()
|
|
225
|
+
this.onClear()
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
selectAllShortcut = (e) => {
|
|
229
|
+
e.stopPropagation()
|
|
230
|
+
this.term.selectAll()
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
copyShortcut = (e) => {
|
|
234
|
+
const sel = this.term.getSelection()
|
|
235
|
+
if (sel) {
|
|
236
|
+
e.stopPropagation()
|
|
237
|
+
e.preventDefault()
|
|
238
|
+
this.copySelectionToClipboard()
|
|
239
|
+
return false
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
searchShortcut = (e) => {
|
|
244
|
+
e.stopPropagation()
|
|
245
|
+
this.toggleSearch()
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
pasteSelectedShortcut = (e) => {
|
|
249
|
+
e.stopPropagation()
|
|
250
|
+
this.tryInsertSelected()
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
showNormalBufferShortcut = (e) => {
|
|
254
|
+
e.stopPropagation()
|
|
255
|
+
this.openNormalBuffer()
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
prevTabShortcut = debounce((e) => {
|
|
259
|
+
e.stopPropagation()
|
|
260
|
+
window.store.clickPrevTab()
|
|
261
|
+
}, 300)
|
|
262
|
+
|
|
263
|
+
nextTabShortcut = debounce((e) => {
|
|
264
|
+
e.stopPropagation()
|
|
265
|
+
window.store.clickNextTab()
|
|
266
|
+
}, 300)
|
|
267
|
+
|
|
226
268
|
handleEvent = (e) => {
|
|
227
269
|
const {
|
|
228
270
|
keyword,
|
|
229
271
|
options,
|
|
230
272
|
action,
|
|
231
273
|
encode,
|
|
232
|
-
id,
|
|
274
|
+
// id,
|
|
233
275
|
type,
|
|
234
276
|
cmd,
|
|
235
277
|
activeSplitId,
|
|
@@ -312,67 +354,6 @@ export default class Term extends Component {
|
|
|
312
354
|
e.stopPropagation()
|
|
313
355
|
return this.term && this.term.blur()
|
|
314
356
|
}
|
|
315
|
-
if (
|
|
316
|
-
keyControlPressed(e) &&
|
|
317
|
-
!keyShiftPressed(e) &&
|
|
318
|
-
keyPressed(e, 'c')
|
|
319
|
-
) {
|
|
320
|
-
const sel = this.term.getSelection()
|
|
321
|
-
if (sel) {
|
|
322
|
-
e.stopPropagation()
|
|
323
|
-
e.preventDefault()
|
|
324
|
-
this.copySelectionToClipboard()
|
|
325
|
-
return false
|
|
326
|
-
}
|
|
327
|
-
} else if (
|
|
328
|
-
keyControlPressed(e) &&
|
|
329
|
-
keyShiftPressed(e) &&
|
|
330
|
-
keyPressed(e, 'c')
|
|
331
|
-
) {
|
|
332
|
-
e.stopPropagation()
|
|
333
|
-
this.copySelectionToClipboard()
|
|
334
|
-
} else if (id === this.props.id) {
|
|
335
|
-
e.stopPropagation()
|
|
336
|
-
this.term.selectAll()
|
|
337
|
-
} else if (
|
|
338
|
-
keyPressed(e, 'f') && keyControlPressed(e) &&
|
|
339
|
-
(
|
|
340
|
-
isMac ||
|
|
341
|
-
(!isMac && keyShiftPressed(e))
|
|
342
|
-
)
|
|
343
|
-
) {
|
|
344
|
-
e.stopPropagation()
|
|
345
|
-
this.toggleSearch()
|
|
346
|
-
} else if (
|
|
347
|
-
keyPressed(e, 'tab')
|
|
348
|
-
) {
|
|
349
|
-
e.stopPropagation()
|
|
350
|
-
e.preventDefault()
|
|
351
|
-
if (e.ctrlKey && e.type === 'keydown') {
|
|
352
|
-
if (e.shiftKey) {
|
|
353
|
-
window.store.clickPrevTab()
|
|
354
|
-
} else {
|
|
355
|
-
window.store.clickNextTab()
|
|
356
|
-
}
|
|
357
|
-
return false
|
|
358
|
-
}
|
|
359
|
-
} else if (
|
|
360
|
-
keyControlPressed(e) &&
|
|
361
|
-
keyPressed(e, 'ArrowUp') && this.bufferMode === 'alternate'
|
|
362
|
-
) {
|
|
363
|
-
e.stopPropagation()
|
|
364
|
-
this.openNormalBuffer()
|
|
365
|
-
} else if (
|
|
366
|
-
e.ctrlKey &&
|
|
367
|
-
keyPressed(e, 'tab')
|
|
368
|
-
) {
|
|
369
|
-
this.onClear()
|
|
370
|
-
} else if (
|
|
371
|
-
e.altKey &&
|
|
372
|
-
keyPressed(e, 'insert')
|
|
373
|
-
) {
|
|
374
|
-
this.tryInsertSelected()
|
|
375
|
-
}
|
|
376
357
|
}
|
|
377
358
|
|
|
378
359
|
onDrop = e => {
|
|
@@ -692,12 +673,11 @@ export default class Term extends Component {
|
|
|
692
673
|
renderContext = () => {
|
|
693
674
|
const hasSlected = this.term.hasSelection()
|
|
694
675
|
const copyed = readClipboard()
|
|
695
|
-
const copyShortcut =
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
const
|
|
699
|
-
|
|
700
|
-
: 'Ctrl+Shift+V'
|
|
676
|
+
const copyShortcut = this.getShortcut('terminal_copy')
|
|
677
|
+
const pasteShortcut = this.getShortcut('terminal_paste')
|
|
678
|
+
const clearShortcut = this.getShortcut('terminal_clear')
|
|
679
|
+
const selectAllShortcut = this.getShortcut('terminal_selectAll')
|
|
680
|
+
const searchShortcut = this.getShortcut('terminal_search')
|
|
701
681
|
return [
|
|
702
682
|
{
|
|
703
683
|
func: 'onCopy',
|
|
@@ -717,17 +697,19 @@ export default class Term extends Component {
|
|
|
717
697
|
func: 'onClear',
|
|
718
698
|
icon: 'ReloadOutlined',
|
|
719
699
|
text: e('clear'),
|
|
720
|
-
subText:
|
|
700
|
+
subText: clearShortcut
|
|
721
701
|
},
|
|
722
702
|
{
|
|
723
703
|
func: 'onSelectAll',
|
|
724
704
|
icon: 'SelectOutlined',
|
|
725
|
-
text: e('selectAll')
|
|
705
|
+
text: e('selectAll'),
|
|
706
|
+
subText: selectAllShortcut
|
|
726
707
|
},
|
|
727
708
|
{
|
|
728
709
|
func: 'toggleSearch',
|
|
729
710
|
icon: 'SearchOutlined',
|
|
730
|
-
text: e('search')
|
|
711
|
+
text: e('search'),
|
|
712
|
+
subText: searchShortcut
|
|
731
713
|
},
|
|
732
714
|
{
|
|
733
715
|
func: 'split',
|
|
@@ -837,7 +819,7 @@ export default class Term extends Component {
|
|
|
837
819
|
// term.on('keydown', this.handleEvent)
|
|
838
820
|
term.onData(this.onData)
|
|
839
821
|
this.term = term
|
|
840
|
-
term.attachCustomKeyEventHandler(this.
|
|
822
|
+
term.attachCustomKeyEventHandler(this.handleKeyboardEvent.bind(this))
|
|
841
823
|
term.onKey(this.onKey)
|
|
842
824
|
// if (host && !password && !privateKey) {
|
|
843
825
|
// return this.promote()
|
|
@@ -895,16 +877,6 @@ export default class Term extends Component {
|
|
|
895
877
|
})
|
|
896
878
|
}
|
|
897
879
|
|
|
898
|
-
watchNormalBufferTrigger = e => {
|
|
899
|
-
if (
|
|
900
|
-
keyControlPressed(e) &&
|
|
901
|
-
keyPressed(e, 'ArrowUp')
|
|
902
|
-
) {
|
|
903
|
-
e.stopPropagation()
|
|
904
|
-
this.copySelectionToClipboard()
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
|
|
908
880
|
openNormalBuffer = () => {
|
|
909
881
|
const normal = this.term.buffer._normal
|
|
910
882
|
const len = normal.length
|
|
@@ -940,7 +912,8 @@ export default class Term extends Component {
|
|
|
940
912
|
srcId, from = 'bookmarks',
|
|
941
913
|
type,
|
|
942
914
|
encode,
|
|
943
|
-
term: terminalType
|
|
915
|
+
term: terminalType,
|
|
916
|
+
displayRaw
|
|
944
917
|
} = tab
|
|
945
918
|
const { savePassword } = this.state
|
|
946
919
|
const isSshConfig = type === terminalSshConfigType
|
|
@@ -1054,32 +1027,40 @@ export default class Term extends Component {
|
|
|
1054
1027
|
}
|
|
1055
1028
|
|
|
1056
1029
|
// this.decoder = new TextDecoder(encode)
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1030
|
+
if (displayRaw) {
|
|
1031
|
+
const oldWrite = term.write
|
|
1032
|
+
const th = this
|
|
1033
|
+
term.write = function (data) {
|
|
1034
|
+
// let str = ''
|
|
1035
|
+
// if (typeof data === 'object') {
|
|
1036
|
+
// if (data instanceof ArrayBuffer) {
|
|
1037
|
+
// str = th.decoder.decode(data)
|
|
1038
|
+
// oldWrite.call(term, th.escape(str))
|
|
1039
|
+
// } else {
|
|
1040
|
+
// const fileReader = new FileReader()
|
|
1041
|
+
// fileReader.addEventListener('load', () => {
|
|
1042
|
+
// str = th.decoder.decode(fileReader.result)
|
|
1043
|
+
// oldWrite.call(term, th.escape(str))
|
|
1044
|
+
// })
|
|
1045
|
+
// fileReader.readAsArrayBuffer(new window.Blob([data]))
|
|
1046
|
+
// }
|
|
1047
|
+
// } else if (typeof data === 'string') {
|
|
1048
|
+
// oldWrite.call(term, th.escape(data))
|
|
1049
|
+
// } else {
|
|
1050
|
+
// throw Error(`Cannot handle ${typeof data} websocket message.`)
|
|
1051
|
+
// }
|
|
1052
|
+
oldWrite.call(term, th.escape(data))
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1079
1055
|
this.term = term
|
|
1080
1056
|
window.store.triggerResize()
|
|
1081
1057
|
}
|
|
1082
1058
|
|
|
1059
|
+
escape = str => {
|
|
1060
|
+
return str.replace(/\\x1B/g, '\\x1B')
|
|
1061
|
+
.replace(/\033/g, '\\033')
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1083
1064
|
onKey = (key, e) => {
|
|
1084
1065
|
// log.log('onKey', key, e)
|
|
1085
1066
|
}
|
|
@@ -1382,3 +1363,5 @@ export default class Term extends Component {
|
|
|
1382
1363
|
)
|
|
1383
1364
|
}
|
|
1384
1365
|
}
|
|
1366
|
+
|
|
1367
|
+
export default shortcutDescExtend(shortcutExtend(Term))
|