@electerm/electerm-react 1.40.20 → 1.50.21
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 +57 -7
- package/client/common/new-terminal.js +2 -2
- package/client/components/auth/login.jsx +34 -57
- package/client/components/batch-op/batch-op.jsx +12 -11
- package/client/components/bookmark-form/index.jsx +2 -2
- package/client/components/bookmark-form/ssh-form.jsx +4 -1
- package/client/components/bookmark-form/tree-delete.jsx +5 -5
- package/client/components/context-menu/boomarks.jsx +8 -12
- package/client/components/context-menu/context-menu.jsx +10 -10
- package/client/components/context-menu/history.jsx +21 -24
- package/client/components/context-menu/menu-btn.jsx +11 -11
- package/client/components/context-menu/tabs.jsx +15 -19
- package/client/components/context-menu/zoom.jsx +25 -29
- package/client/components/footer/footer-entry.jsx +56 -56
- package/client/components/icons/split-icons.jsx +77 -0
- package/client/components/layout/layout-alg.js +260 -0
- package/client/components/layout/layout-item.jsx +26 -0
- package/client/components/layout/layout.jsx +167 -0
- package/client/components/layout/layout.styl +5 -0
- package/client/components/layout/layouts.jsx +71 -0
- package/client/components/layout/session-size-alg.js +31 -0
- package/client/components/main/main.jsx +183 -109
- package/client/components/main/wrapper.styl +2 -4
- package/client/components/profile/profile-list.jsx +1 -3
- package/client/components/profile/profile-transport-mod.jsx +1 -1
- package/client/components/profile/profile-transport.jsx +6 -9
- package/client/components/quick-commands/quick-command-transport.jsx +6 -9
- package/client/components/quick-commands/quick-commands-box.jsx +144 -153
- package/client/components/quick-commands/quick-commands-select.jsx +10 -3
- package/client/components/rdp/rdp-session.jsx +3 -23
- package/client/components/rdp/resolution-edit.jsx +40 -42
- package/client/components/session/session.jsx +62 -317
- package/client/components/session/session.styl +1 -5
- package/client/components/session/sessions.jsx +99 -105
- package/client/components/setting-panel/bookmark-tree-list.jsx +1 -1
- package/client/components/setting-panel/setting-common.jsx +6 -4
- package/client/components/setting-panel/setting-modal.jsx +31 -31
- package/client/components/setting-panel/start-session-select.jsx +4 -4
- package/client/components/setting-panel/tab-settings.jsx +27 -5
- package/client/components/setting-sync/data-import.jsx +36 -39
- package/client/components/setting-sync/setting-sync-form.jsx +9 -9
- package/client/components/setting-sync/setting-sync.jsx +50 -52
- package/client/components/sftp/address-bookmark.jsx +57 -58
- package/client/components/sftp/confirm-modal-store.jsx +34 -40
- package/client/components/sftp/file-item.jsx +14 -3
- package/client/components/sftp/file-mode-modal.jsx +3 -0
- package/client/components/sftp/list-table-ui.jsx +4 -4
- package/client/components/sftp/sftp-entry.jsx +2 -2
- package/client/components/sftp/transfer-conflict-store.jsx +13 -17
- package/client/components/sftp/transport-action-store.jsx +38 -31
- package/client/components/sftp/transports-action-store.jsx +3 -3
- package/client/components/sftp/transports-ui-store.jsx +18 -23
- package/client/components/shortcuts/shortcut-handler.js +1 -0
- package/client/components/shortcuts/shortcuts.jsx +9 -12
- package/client/components/side-panel-r/right-side-panel.styl +40 -0
- package/client/components/side-panel-r/side-panel-r.jsx +102 -0
- package/client/components/sidebar/bookmark-select.jsx +40 -40
- package/client/components/sidebar/bookmark.jsx +63 -65
- package/client/components/sidebar/history.jsx +53 -50
- package/client/components/sidebar/index.jsx +195 -184
- package/client/components/sidebar/info-modal.jsx +202 -202
- package/client/components/sidebar/sidebar.styl +8 -2
- package/client/components/sidebar/transfer-history-modal.jsx +95 -100
- package/client/components/sidebar/transfer-list-control.jsx +2 -2
- package/client/components/sidebar/transfer-list.jsx +45 -42
- package/client/components/sidebar/transfer-modal.jsx +49 -52
- package/client/components/sidebar/transport-ui.jsx +1 -1
- package/client/components/tabs/index.jsx +261 -49
- package/client/components/tabs/tab.jsx +60 -65
- package/client/components/tabs/tabs.styl +6 -1
- package/client/components/tabs/window-control.jsx +46 -48
- package/client/components/terminal/index.jsx +101 -104
- package/client/components/terminal/term-search.jsx +26 -24
- package/client/components/terminal-info/run-cmd.jsx +0 -25
- package/client/components/terminal-info/terminal-info.jsx +60 -0
- package/client/components/terminal-info/terminal-info.styl +1 -1
- package/client/components/tree-list/bookmark-transport.jsx +8 -9
- package/client/components/tree-list/tree-list.jsx +36 -26
- package/client/components/vnc/vnc-session.jsx +1 -6
- package/client/store/common.js +1 -1
- package/client/store/event.js +2 -2
- package/client/store/index.js +21 -32
- package/client/store/init-state.js +15 -3
- package/client/store/load-data.js +1 -1
- package/client/store/quick-command.js +4 -4
- package/client/store/session.js +1 -1
- package/client/store/setting.js +9 -5
- package/client/store/system-menu.js +1 -10
- package/client/store/tab.js +66 -1
- package/client/store/transfer-list.js +5 -6
- package/client/store/watch.js +11 -6
- package/package.json +1 -1
- package/client/components/common/react-subx.jsx +0 -1
- package/client/components/common/resize-wrap.jsx +0 -222
- package/client/components/common/resize-wrap.styl +0 -9
- package/client/components/terminal-info/content.jsx +0 -152
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* session tabs component
|
|
3
|
-
* @param {array} props.tabs {id, title}
|
|
4
3
|
*/
|
|
5
4
|
|
|
6
5
|
import React from 'react'
|
|
7
|
-
import
|
|
6
|
+
import runIdle from '../../common/run-idle'
|
|
7
|
+
import { findIndex, debounce } from 'lodash-es'
|
|
8
8
|
import TabTitle from './tab-title'
|
|
9
9
|
import {
|
|
10
10
|
CodeFilled,
|
|
@@ -14,8 +14,17 @@ import {
|
|
|
14
14
|
RightOutlined,
|
|
15
15
|
RightSquareFilled
|
|
16
16
|
} from '@ant-design/icons'
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
import {
|
|
18
|
+
SingleIcon,
|
|
19
|
+
TwoColumnsIcon,
|
|
20
|
+
ThreeColumnsIcon,
|
|
21
|
+
TwoRowsIcon,
|
|
22
|
+
ThreeRowsIcon,
|
|
23
|
+
Grid2x2Icon,
|
|
24
|
+
TwoRowsRightIcon,
|
|
25
|
+
TwoColumnsBottomIcon
|
|
26
|
+
} from '../icons/split-icons'
|
|
27
|
+
import { Dropdown, Popover } from 'antd'
|
|
19
28
|
import Tab from './tab'
|
|
20
29
|
import './tabs.styl'
|
|
21
30
|
import {
|
|
@@ -23,7 +32,9 @@ import {
|
|
|
23
32
|
tabMargin,
|
|
24
33
|
extraTabWidth,
|
|
25
34
|
windowControlWidth,
|
|
26
|
-
isMacJs
|
|
35
|
+
isMacJs,
|
|
36
|
+
splitMapDesc,
|
|
37
|
+
commonActions
|
|
27
38
|
} from '../../common/constants'
|
|
28
39
|
import findParentBySel from '../../common/find-parent'
|
|
29
40
|
import WindowControl from './window-control'
|
|
@@ -32,22 +43,28 @@ import AppDrag from './app-drag'
|
|
|
32
43
|
import classNames from 'classnames'
|
|
33
44
|
|
|
34
45
|
const e = window.translate
|
|
35
|
-
const MenuItem = Menu.Item
|
|
36
46
|
|
|
37
47
|
export default class Tabs extends React.Component {
|
|
38
48
|
constructor (props) {
|
|
39
49
|
super(props)
|
|
40
50
|
this.tabsRef = React.createRef()
|
|
41
51
|
this.state = {
|
|
42
|
-
overflow: false
|
|
52
|
+
overflow: false,
|
|
53
|
+
receiveDataTabId: '',
|
|
54
|
+
onContextMenuTabId: '',
|
|
55
|
+
contextFuncTabId: '',
|
|
56
|
+
contextFunc: '',
|
|
57
|
+
contextArgs: []
|
|
43
58
|
}
|
|
44
59
|
}
|
|
45
60
|
|
|
46
61
|
componentDidMount () {
|
|
47
|
-
|
|
62
|
+
const { batch } = this.props
|
|
63
|
+
this.dom = document.querySelector(`.v${batch + 1} .tabs-inner`)
|
|
48
64
|
const {
|
|
49
65
|
tabsRef
|
|
50
66
|
} = this
|
|
67
|
+
window.addEventListener('message', this.onEvent)
|
|
51
68
|
tabsRef.current.addEventListener('mousedown', this.handleClickEvent)
|
|
52
69
|
tabsRef.current.addEventListener('mousewheel', this.handleWheelEvent)
|
|
53
70
|
}
|
|
@@ -56,15 +73,102 @@ export default class Tabs extends React.Component {
|
|
|
56
73
|
if (
|
|
57
74
|
prevProps.currentTabId !== this.props.currentTabId ||
|
|
58
75
|
prevProps.width !== this.props.width ||
|
|
59
|
-
prevProps.tabs.length !== this.props.tabs.length
|
|
76
|
+
(prevProps.tabs || []).length !== (this.props.tabs || []).length
|
|
60
77
|
) {
|
|
61
78
|
this.adjustScroll()
|
|
62
79
|
}
|
|
63
80
|
}
|
|
64
81
|
|
|
82
|
+
componentWillUnmount () {
|
|
83
|
+
window.removeEventListener('message', this.onEvent)
|
|
84
|
+
this.offTimer()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
modifier = (...args) => {
|
|
88
|
+
runIdle(() => this.setState(...args))
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
onEvent = (e) => {
|
|
92
|
+
const {
|
|
93
|
+
action,
|
|
94
|
+
tabId
|
|
95
|
+
} = e.data || {}
|
|
96
|
+
if (
|
|
97
|
+
action === commonActions.closeContextMenuAfter
|
|
98
|
+
) {
|
|
99
|
+
this.offContextMenu()
|
|
100
|
+
} else if (
|
|
101
|
+
action === 'terminal-receive-data' &&
|
|
102
|
+
tabId
|
|
103
|
+
) {
|
|
104
|
+
this.modifier({
|
|
105
|
+
receiveDataTabId: tabId
|
|
106
|
+
})
|
|
107
|
+
this.timer = setTimeout(this.clearReceiveData, 4000)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
clearReceiveData = () => {
|
|
112
|
+
this.modifier({
|
|
113
|
+
receiveDataTabId: ''
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
offTimer = () => {
|
|
118
|
+
clearTimeout(this.timer)
|
|
119
|
+
this.timer = null
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
offContextMenu = () => {
|
|
123
|
+
window.removeEventListener('message', this.onContextAction)
|
|
124
|
+
this.setState({
|
|
125
|
+
onContextMenuTabId: ''
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
handleContextMenu = e => {
|
|
130
|
+
e.preventDefault()
|
|
131
|
+
const { target } = e
|
|
132
|
+
const tabElem = findParentBySel(target, '.tab')
|
|
133
|
+
if (!tabElem) {
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
this.setState({
|
|
137
|
+
contextFuncTabId: '',
|
|
138
|
+
onContextMenuTabId: tabElem.dataset.id
|
|
139
|
+
})
|
|
140
|
+
window.addEventListener('message', this.onContextAction)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
onContextAction = e => {
|
|
144
|
+
const {
|
|
145
|
+
action,
|
|
146
|
+
id,
|
|
147
|
+
args = [],
|
|
148
|
+
func
|
|
149
|
+
} = e.data || {}
|
|
150
|
+
if (
|
|
151
|
+
action !== commonActions.clickContextMenu ||
|
|
152
|
+
id !== this.state.onContextMenuTabId
|
|
153
|
+
) {
|
|
154
|
+
return false
|
|
155
|
+
}
|
|
156
|
+
this.offContextMenu()
|
|
157
|
+
this.setContextFunc(id, func, args)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
setContextFunc = (id, func, args) => {
|
|
161
|
+
this.setState({
|
|
162
|
+
contextFuncTabId: id,
|
|
163
|
+
contextFunc: func,
|
|
164
|
+
contextArgs: args
|
|
165
|
+
})
|
|
166
|
+
}
|
|
167
|
+
|
|
65
168
|
tabsWidth = () => {
|
|
169
|
+
const { batch } = this.props
|
|
66
170
|
return Array.from(
|
|
67
|
-
document.querySelectorAll(
|
|
171
|
+
document.querySelectorAll(`.v${batch + 1} .tab`)
|
|
68
172
|
).reduce((prev, c) => {
|
|
69
173
|
return prev + c.clientWidth
|
|
70
174
|
}, 0)
|
|
@@ -80,7 +184,9 @@ export default class Tabs extends React.Component {
|
|
|
80
184
|
}
|
|
81
185
|
|
|
82
186
|
getInnerWidth = () => {
|
|
83
|
-
const
|
|
187
|
+
const { batch } = this.props
|
|
188
|
+
const cls = `.v${batch + 1} .tabs-inner`
|
|
189
|
+
const inner = document.querySelector(cls)
|
|
84
190
|
return inner ? inner.clientWidth : 0
|
|
85
191
|
}
|
|
86
192
|
|
|
@@ -101,11 +207,15 @@ export default class Tabs extends React.Component {
|
|
|
101
207
|
this.props.addTab()
|
|
102
208
|
}
|
|
103
209
|
|
|
210
|
+
handleTabAdd = () => {
|
|
211
|
+
this.props.addTab()
|
|
212
|
+
}
|
|
213
|
+
|
|
104
214
|
adjustScroll = () => {
|
|
105
|
-
const { tabs, currentTabId } = this.props
|
|
215
|
+
const { tabs, currentTabId, batch } = this.props
|
|
106
216
|
const index = findIndex(tabs, t => t.id === currentTabId)
|
|
107
217
|
const tabsDomWith = Array.from(
|
|
108
|
-
document.querySelectorAll(
|
|
218
|
+
document.querySelectorAll(`.v${batch + 1} .tab`)
|
|
109
219
|
).slice(0, index + 2).reduce((prev, c) => {
|
|
110
220
|
return prev + c.clientWidth
|
|
111
221
|
}, 0)
|
|
@@ -138,7 +248,7 @@ export default class Tabs extends React.Component {
|
|
|
138
248
|
this.dom.scrollLeft = scrollLeft
|
|
139
249
|
}
|
|
140
250
|
|
|
141
|
-
handleWheelEvent = (e) => {
|
|
251
|
+
handleWheelEvent = debounce((e) => {
|
|
142
252
|
if (this.isOverflow()) {
|
|
143
253
|
if (e.deltaY < 0) {
|
|
144
254
|
this.handleScrollLeft()
|
|
@@ -146,34 +256,24 @@ export default class Tabs extends React.Component {
|
|
|
146
256
|
this.handleScrollRight()
|
|
147
257
|
}
|
|
148
258
|
}
|
|
149
|
-
}
|
|
259
|
+
}, 100)
|
|
150
260
|
|
|
151
261
|
handleClickMenu = ({ key }) => {
|
|
152
262
|
const id = key.split('##')[1]
|
|
153
263
|
this.props.onChangeTabId(id)
|
|
154
264
|
}
|
|
155
265
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
key={i + '##' + t.id}
|
|
165
|
-
>
|
|
166
|
-
<TabTitle tab={t} />
|
|
167
|
-
</MenuItem>
|
|
168
|
-
)
|
|
169
|
-
})
|
|
170
|
-
}
|
|
171
|
-
</Menu>
|
|
172
|
-
)
|
|
266
|
+
handleChangeLayout = ({ key }) => {
|
|
267
|
+
window.store.setLayout(key)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
handleOpenChange = (open) => {
|
|
271
|
+
if (open) {
|
|
272
|
+
window.openTabBatch = this.props.batch
|
|
273
|
+
}
|
|
173
274
|
}
|
|
174
275
|
|
|
175
276
|
renderMenus () {
|
|
176
|
-
const { addTab } = this.props
|
|
177
277
|
const { onNewSsh } = window.store
|
|
178
278
|
const cls = 'pd2x pd1y context-item pointer'
|
|
179
279
|
return (
|
|
@@ -190,7 +290,7 @@ export default class Tabs extends React.Component {
|
|
|
190
290
|
</div>
|
|
191
291
|
<div
|
|
192
292
|
className={cls}
|
|
193
|
-
onClick={
|
|
293
|
+
onClick={this.handleTabAdd}
|
|
194
294
|
>
|
|
195
295
|
<RightSquareFilled /> {e('newTab')}
|
|
196
296
|
</div>
|
|
@@ -205,23 +305,48 @@ export default class Tabs extends React.Component {
|
|
|
205
305
|
const cls = classNames(
|
|
206
306
|
'pointer tabs-add-btn font16',
|
|
207
307
|
{
|
|
208
|
-
empty: !this.props.tabs
|
|
308
|
+
empty: !this.props.tabs?.length
|
|
209
309
|
}
|
|
210
310
|
)
|
|
211
311
|
return (
|
|
212
312
|
<Popover
|
|
213
313
|
content={this.renderMenus()}
|
|
314
|
+
onOpenChange={this.handleOpenChange}
|
|
214
315
|
>
|
|
215
316
|
<PlusOutlined
|
|
216
317
|
title={e('openNewTerm')}
|
|
217
318
|
className={cls}
|
|
218
|
-
onClick={
|
|
319
|
+
onClick={this.handleTabAdd}
|
|
219
320
|
/>
|
|
220
321
|
</Popover>
|
|
221
322
|
)
|
|
222
323
|
}
|
|
223
324
|
|
|
325
|
+
renderNoExtra () {
|
|
326
|
+
return (
|
|
327
|
+
<div className='tabs-extra pd1x'>
|
|
328
|
+
{this.renderLayoutMenu()}
|
|
329
|
+
</div>
|
|
330
|
+
)
|
|
331
|
+
}
|
|
332
|
+
|
|
224
333
|
renderExtra () {
|
|
334
|
+
const items = this.props.tabs.map((t, i) => {
|
|
335
|
+
return {
|
|
336
|
+
key: i + '##' + t.id,
|
|
337
|
+
label: (
|
|
338
|
+
<span><TabTitle tab={t} /></span>
|
|
339
|
+
),
|
|
340
|
+
onClick: () => this.handleClickMenu({ key: i + '##' + t.id })
|
|
341
|
+
}
|
|
342
|
+
})
|
|
343
|
+
const dropProps = {
|
|
344
|
+
className: 'tabs-add-btn font16',
|
|
345
|
+
menu: {
|
|
346
|
+
items
|
|
347
|
+
},
|
|
348
|
+
placement: 'bottomRight'
|
|
349
|
+
}
|
|
225
350
|
return (
|
|
226
351
|
<div className='tabs-extra pd1x'>
|
|
227
352
|
{this.renderAddBtn()}
|
|
@@ -234,12 +359,13 @@ export default class Tabs extends React.Component {
|
|
|
234
359
|
onClick={this.handleScrollRight}
|
|
235
360
|
/>
|
|
236
361
|
<Dropdown
|
|
237
|
-
|
|
238
|
-
placement='bottomRight'
|
|
239
|
-
overlay={this.renderList()}
|
|
362
|
+
{...dropProps}
|
|
240
363
|
>
|
|
241
364
|
<DownOutlined className='tabs-dd-icon' />
|
|
242
365
|
</Dropdown>
|
|
366
|
+
{
|
|
367
|
+
this.renderLayoutMenu()
|
|
368
|
+
}
|
|
243
369
|
</div>
|
|
244
370
|
)
|
|
245
371
|
}
|
|
@@ -260,13 +386,13 @@ export default class Tabs extends React.Component {
|
|
|
260
386
|
const { tabs = [], width, config } = this.props
|
|
261
387
|
const len = tabs.length
|
|
262
388
|
const tabsWidthAll = tabMargin * len + 10 + this.tabsWidth()
|
|
263
|
-
const { overflow } = this.state
|
|
389
|
+
const { overflow, receiveDataTabId, onContextMenuTabId } = this.state
|
|
264
390
|
const left = overflow
|
|
265
391
|
? '100%'
|
|
266
392
|
: tabsWidthAll
|
|
267
393
|
const w1 = isMacJs && (config.useSystemTitleBar || window.et.isWebApp)
|
|
268
394
|
? 30
|
|
269
|
-
:
|
|
395
|
+
: this.getExtraTabWidth()
|
|
270
396
|
const style = {
|
|
271
397
|
width: width - w1 - 166
|
|
272
398
|
}
|
|
@@ -290,11 +416,20 @@ export default class Tabs extends React.Component {
|
|
|
290
416
|
{
|
|
291
417
|
tabs.map((tab, i) => {
|
|
292
418
|
const isLast = i === len - 1
|
|
419
|
+
const tabProps = {
|
|
420
|
+
...this.props,
|
|
421
|
+
tab,
|
|
422
|
+
isLast,
|
|
423
|
+
receiveData: receiveDataTabId === tab.id,
|
|
424
|
+
openContextMenu: onContextMenuTabId === tab.id
|
|
425
|
+
}
|
|
426
|
+
if (this.state.contextFuncTabId === tab.id) {
|
|
427
|
+
tabProps.contextFunc = this.state.contextFunc
|
|
428
|
+
tabProps.contextArgs = this.state.contextArgs
|
|
429
|
+
}
|
|
293
430
|
return (
|
|
294
431
|
<Tab
|
|
295
|
-
{...
|
|
296
|
-
tab={tab}
|
|
297
|
-
isLast={isLast}
|
|
432
|
+
{...tabProps}
|
|
298
433
|
key={tab.id}
|
|
299
434
|
/>
|
|
300
435
|
)
|
|
@@ -310,18 +445,95 @@ export default class Tabs extends React.Component {
|
|
|
310
445
|
)
|
|
311
446
|
}
|
|
312
447
|
|
|
313
|
-
|
|
314
|
-
const
|
|
448
|
+
getLayoutIcon = (layout) => {
|
|
449
|
+
const iconMaps = {
|
|
450
|
+
single: SingleIcon,
|
|
451
|
+
twoColumns: TwoColumnsIcon,
|
|
452
|
+
threeColumns: ThreeColumnsIcon,
|
|
453
|
+
twoRows: TwoRowsIcon,
|
|
454
|
+
threeRows: ThreeRowsIcon,
|
|
455
|
+
grid2x2: Grid2x2Icon,
|
|
456
|
+
twoRowsRight: TwoRowsRightIcon,
|
|
457
|
+
twoColumnsBottom: TwoColumnsBottomIcon
|
|
458
|
+
}
|
|
459
|
+
return iconMaps[layout]
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
renderLayoutMenu = () => {
|
|
463
|
+
if (!this.shouldRenderWindowControl()) {
|
|
464
|
+
return null
|
|
465
|
+
}
|
|
466
|
+
const items = Object.keys(splitMapDesc).map((t) => {
|
|
467
|
+
const v = splitMapDesc[t]
|
|
468
|
+
const Icon = this.getLayoutIcon(v)
|
|
469
|
+
return {
|
|
470
|
+
key: t,
|
|
471
|
+
label: (
|
|
472
|
+
<span>
|
|
473
|
+
<Icon /> {e(v)}
|
|
474
|
+
</span>
|
|
475
|
+
),
|
|
476
|
+
onClick: () => this.handleChangeLayout({ key: t })
|
|
477
|
+
}
|
|
478
|
+
})
|
|
479
|
+
const v = splitMapDesc[this.props.layout]
|
|
480
|
+
const Icon = this.getLayoutIcon(v)
|
|
315
481
|
return (
|
|
316
|
-
<
|
|
317
|
-
{
|
|
482
|
+
<Dropdown
|
|
483
|
+
menu={{ items }}
|
|
484
|
+
placement='bottomRight'
|
|
485
|
+
>
|
|
486
|
+
<span className='tabs-dd-icon mg1l'>
|
|
487
|
+
<Icon /> <DownOutlined />
|
|
488
|
+
</span>
|
|
489
|
+
</Dropdown>
|
|
490
|
+
)
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
shouldRenderWindowControl = () => {
|
|
494
|
+
const { layout, batch } = this.props
|
|
495
|
+
const batchToRender = {
|
|
496
|
+
c1: 0,
|
|
497
|
+
c2: 1,
|
|
498
|
+
c3: 2,
|
|
499
|
+
r2: 0,
|
|
500
|
+
r3: 0,
|
|
501
|
+
c2x2: 1,
|
|
502
|
+
c1r2: 1,
|
|
503
|
+
r1c2: 0
|
|
504
|
+
}
|
|
505
|
+
return batch === batchToRender[layout]
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
getExtraTabWidth = () => {
|
|
509
|
+
return this.shouldRenderWindowControl()
|
|
510
|
+
? windowControlWidth
|
|
511
|
+
: 0
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
renderWindowControl = () => {
|
|
515
|
+
if (this.shouldRenderWindowControl()) {
|
|
516
|
+
return (
|
|
318
517
|
<WindowControl
|
|
319
518
|
store={window.store}
|
|
320
519
|
/>
|
|
520
|
+
)
|
|
521
|
+
}
|
|
522
|
+
return null
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
render () {
|
|
526
|
+
const { overflow } = this.state
|
|
527
|
+
return (
|
|
528
|
+
<div className='tabs' ref={this.tabsRef} onContextMenu={this.handleContextMenu}>
|
|
529
|
+
{this.renderContent()}
|
|
530
|
+
{
|
|
531
|
+
this.renderWindowControl()
|
|
532
|
+
}
|
|
321
533
|
{
|
|
322
534
|
overflow
|
|
323
535
|
? this.renderExtra()
|
|
324
|
-
:
|
|
536
|
+
: this.renderNoExtra()
|
|
325
537
|
}
|
|
326
538
|
</div>
|
|
327
539
|
)
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
Loading3QuartersOutlined,
|
|
10
10
|
BorderlessTableOutlined
|
|
11
11
|
} from '@ant-design/icons'
|
|
12
|
-
import generate from '../../common/
|
|
12
|
+
import generate from '../../common/id-with-stamp'
|
|
13
13
|
import { Tooltip, message } from 'antd'
|
|
14
14
|
import classnames from 'classnames'
|
|
15
15
|
import copy from 'json-deep-copy'
|
|
@@ -19,7 +19,9 @@ import createName from '../../common/create-title'
|
|
|
19
19
|
import { addClass, removeClass } from '../../common/class'
|
|
20
20
|
import {
|
|
21
21
|
terminalSshConfigType,
|
|
22
|
-
|
|
22
|
+
splitConfig,
|
|
23
|
+
paneMap,
|
|
24
|
+
statusMap
|
|
23
25
|
} from '../../common/constants'
|
|
24
26
|
import { shortcutDescExtend } from '../shortcuts/shortcut-handler.js'
|
|
25
27
|
|
|
@@ -31,13 +33,12 @@ class Tab extends Component {
|
|
|
31
33
|
constructor (props) {
|
|
32
34
|
super(props)
|
|
33
35
|
this.state = {
|
|
34
|
-
terminalOnData: false,
|
|
35
36
|
tab: copy(props.tab)
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
componentDidMount () {
|
|
40
|
-
this.dom = document.getElementById('
|
|
41
|
+
this.dom = document.getElementById('tab-' + this.state.tab.id)
|
|
41
42
|
window.addEventListener('message', this.onEvent)
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -47,12 +48,16 @@ class Tab extends Component {
|
|
|
47
48
|
tab: copy(this.props.tab)
|
|
48
49
|
})
|
|
49
50
|
}
|
|
51
|
+
if (this.props.openContextMenu && !prevProps.openContextMenu) {
|
|
52
|
+
this.handleContextMenu()
|
|
53
|
+
}
|
|
54
|
+
if (this.props.contextFunc && !prevProps.contextFunc) {
|
|
55
|
+
this[this.props.contextFunc](...this.props.contextArgs)
|
|
56
|
+
}
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
componentWillUnmount () {
|
|
53
|
-
|
|
54
|
-
window.removeEventListener('message', this.onContextAction)
|
|
55
|
-
clearTimeout(this.handler)
|
|
60
|
+
this.dom = null
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
shouldComponentUpdate (nextProps, nextState) {
|
|
@@ -70,10 +75,11 @@ class Tab extends Component {
|
|
|
70
75
|
'height',
|
|
71
76
|
'isLast',
|
|
72
77
|
'isMaximized',
|
|
73
|
-
'activeTerminalId',
|
|
74
78
|
'config',
|
|
75
79
|
'tab',
|
|
76
|
-
'width'
|
|
80
|
+
'width',
|
|
81
|
+
'openContextMenu',
|
|
82
|
+
'contextFunc'
|
|
77
83
|
]
|
|
78
84
|
|
|
79
85
|
// compare only the relevant props
|
|
@@ -84,28 +90,6 @@ class Tab extends Component {
|
|
|
84
90
|
runIdle(() => this.setState(...args))
|
|
85
91
|
}
|
|
86
92
|
|
|
87
|
-
onEvent = (e) => {
|
|
88
|
-
if (
|
|
89
|
-
e.data &&
|
|
90
|
-
e.data.action === 'terminal-receive-data' &&
|
|
91
|
-
e.data.tabId === this.state.tab.id
|
|
92
|
-
) {
|
|
93
|
-
this.modifier({
|
|
94
|
-
terminalOnData: true
|
|
95
|
-
})
|
|
96
|
-
if (this.handler) {
|
|
97
|
-
clearTimeout(this.handler)
|
|
98
|
-
}
|
|
99
|
-
this.handler = setTimeout(this.offTerminalOnData, 4000)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
offTerminalOnData = () => {
|
|
104
|
-
this.modifier({
|
|
105
|
-
terminalOnData: false
|
|
106
|
-
})
|
|
107
|
-
}
|
|
108
|
-
|
|
109
93
|
clearCls = () => {
|
|
110
94
|
document.querySelectorAll('.' + onDragOverCls).forEach((d) => {
|
|
111
95
|
removeClass(d, onDragOverCls)
|
|
@@ -173,12 +157,24 @@ class Tab extends Component {
|
|
|
173
157
|
}
|
|
174
158
|
const { id } = fromTab
|
|
175
159
|
const tabs = copy(this.props.tabs)
|
|
176
|
-
const indexFrom = findIndex(tabs, t => t.id === id)
|
|
177
160
|
let indexDrop = findIndex(tabs, t => t.id === dropId)
|
|
178
|
-
|
|
179
|
-
|
|
161
|
+
const dropTab = tabs[indexDrop]
|
|
162
|
+
const indexFrom = findIndex(tabs, t => t.id === id)
|
|
163
|
+
if (indexFrom === -1) {
|
|
164
|
+
const fromBatch = fromTab.batch
|
|
165
|
+
setTimeout(() => {
|
|
166
|
+
const closeBtn = document.querySelector(`.v${fromBatch + 1} .tab-${id} .tab-close .anticon`)
|
|
167
|
+
if (closeBtn) {
|
|
168
|
+
closeBtn.click()
|
|
169
|
+
}
|
|
170
|
+
}, 10)
|
|
171
|
+
fromTab.batch = dropTab.batch
|
|
172
|
+
} else {
|
|
173
|
+
if (indexDrop > indexFrom) {
|
|
174
|
+
indexDrop = indexDrop - 1
|
|
175
|
+
}
|
|
176
|
+
tabs.splice(indexFrom, 1)
|
|
180
177
|
}
|
|
181
|
-
tabs.splice(indexFrom, 1)
|
|
182
178
|
tabs.splice(indexDrop, 0, fromTab)
|
|
183
179
|
this.props.setTabs(
|
|
184
180
|
tabs
|
|
@@ -206,6 +202,21 @@ class Tab extends Component {
|
|
|
206
202
|
)
|
|
207
203
|
}
|
|
208
204
|
|
|
205
|
+
cloneToNextLayout = () => {
|
|
206
|
+
const defaultStatus = statusMap.processing
|
|
207
|
+
const { batch, layout } = this.props
|
|
208
|
+
const ntb = copy(this.state.tab)
|
|
209
|
+
Object.assign(ntb, {
|
|
210
|
+
id: generate(),
|
|
211
|
+
status: defaultStatus,
|
|
212
|
+
isTransporting: undefined,
|
|
213
|
+
pane: paneMap.terminal
|
|
214
|
+
})
|
|
215
|
+
const maxBatch = splitConfig[layout].children
|
|
216
|
+
ntb.batch = (batch + 1) % maxBatch
|
|
217
|
+
window.store.addTab(ntb)
|
|
218
|
+
}
|
|
219
|
+
|
|
209
220
|
newTab = () => {
|
|
210
221
|
this.props.addTab()
|
|
211
222
|
}
|
|
@@ -269,7 +280,7 @@ class Tab extends Component {
|
|
|
269
280
|
}
|
|
270
281
|
|
|
271
282
|
renderContext = () => {
|
|
272
|
-
const { tabs, tab } = this.props
|
|
283
|
+
const { tabs, tab, layout } = this.props
|
|
273
284
|
const len = tabs.length
|
|
274
285
|
const index = findIndex(tabs, t => t.id === tab.id)
|
|
275
286
|
const noRight = index >= len - 1
|
|
@@ -303,6 +314,13 @@ class Tab extends Component {
|
|
|
303
314
|
icon: 'CopyOutlined',
|
|
304
315
|
text: e('duplicate')
|
|
305
316
|
})
|
|
317
|
+
if (layout !== 'c1') {
|
|
318
|
+
res.push({
|
|
319
|
+
func: 'cloneToNextLayout',
|
|
320
|
+
icon: 'CopyOutlined',
|
|
321
|
+
text: e('cloneToNextLayout')
|
|
322
|
+
})
|
|
323
|
+
}
|
|
306
324
|
res.push({
|
|
307
325
|
disabled: isSshConfig,
|
|
308
326
|
func: 'doRename',
|
|
@@ -318,39 +336,17 @@ class Tab extends Component {
|
|
|
318
336
|
return res
|
|
319
337
|
}
|
|
320
338
|
|
|
321
|
-
|
|
322
|
-
const
|
|
323
|
-
action,
|
|
324
|
-
id,
|
|
325
|
-
args = [],
|
|
326
|
-
func
|
|
327
|
-
} = e.data || {}
|
|
328
|
-
if (
|
|
329
|
-
action !== commonActions.clickContextMenu ||
|
|
330
|
-
id !== this.uid ||
|
|
331
|
-
!this[func]
|
|
332
|
-
) {
|
|
333
|
-
return false
|
|
334
|
-
}
|
|
335
|
-
window.removeEventListener('message', this.onContextAction)
|
|
336
|
-
this[func](...args)
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
handleContextMenu = e => {
|
|
340
|
-
e.preventDefault()
|
|
341
|
-
const { target } = e
|
|
342
|
-
const rect = target.getBoundingClientRect()
|
|
339
|
+
handleContextMenu = () => {
|
|
340
|
+
const rect = this.dom.getBoundingClientRect()
|
|
343
341
|
const items = this.renderContext()
|
|
344
|
-
this.uid = generate()
|
|
345
342
|
window.store.openContextMenu({
|
|
346
343
|
items,
|
|
347
344
|
pos: {
|
|
348
345
|
left: rect.left,
|
|
349
346
|
top: rect.top + 20
|
|
350
347
|
},
|
|
351
|
-
id: this.
|
|
348
|
+
id: this.state.tab.id
|
|
352
349
|
})
|
|
353
|
-
window.addEventListener('message', this.onContextAction)
|
|
354
350
|
}
|
|
355
351
|
|
|
356
352
|
renderEditting (tab, cls) {
|
|
@@ -416,8 +412,8 @@ class Tab extends Component {
|
|
|
416
412
|
const {
|
|
417
413
|
currentTabId
|
|
418
414
|
} = this.props
|
|
419
|
-
const { isLast } = this.props
|
|
420
|
-
const { tab
|
|
415
|
+
const { isLast, terminalOnData } = this.props
|
|
416
|
+
const { tab } = this.state
|
|
421
417
|
const {
|
|
422
418
|
id,
|
|
423
419
|
isEditting,
|
|
@@ -461,7 +457,7 @@ class Tab extends Component {
|
|
|
461
457
|
<div
|
|
462
458
|
className={cls}
|
|
463
459
|
draggable
|
|
464
|
-
id={'
|
|
460
|
+
id={'tab-' + id}
|
|
465
461
|
data-id={id}
|
|
466
462
|
{...pick(this, [
|
|
467
463
|
'onDrag',
|
|
@@ -479,7 +475,6 @@ class Tab extends Component {
|
|
|
479
475
|
onClick={this.handleClick}
|
|
480
476
|
onDoubleClick={this.handleDup}
|
|
481
477
|
style={styleTag}
|
|
482
|
-
onContextMenu={this.handleContextMenu}
|
|
483
478
|
>
|
|
484
479
|
<Loading3QuartersOutlined
|
|
485
480
|
className='pointer tab-reload mg1r'
|