@electerm/electerm-react 1.40.20 → 1.50.31
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 +94 -0
- package/client/components/layout/layout.jsx +167 -0
- package/client/components/layout/layout.styl +8 -0
- package/client/components/layout/layouts.jsx +72 -0
- package/client/components/layout/session-size-alg.js +31 -0
- package/client/components/main/custom-css.jsx +1 -1
- package/client/components/main/main.jsx +184 -110
- package/client/components/main/ui-theme.jsx +1 -1
- 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 +63 -328
- package/client/components/session/session.styl +1 -5
- package/client/components/session/sessions.jsx +140 -111
- 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 +10 -10
- 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-defaults.js +5 -5
- 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 +48 -66
- package/client/components/tabs/tabs.styl +6 -1
- package/client/components/tabs/window-control.jsx +46 -48
- package/client/components/terminal/attach-addon-custom.js +1 -1
- package/client/components/terminal/index.jsx +111 -113
- 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/components/web/address-bar.jsx +50 -0
- package/client/components/web/web-session.jsx +32 -10
- package/client/entry/index.jsx +5 -6
- package/client/store/common.js +1 -1
- package/client/store/db-upgrade.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 +10 -6
- package/client/store/system-menu.js +1 -10
- package/client/store/tab.js +91 -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,6 @@ import {
|
|
|
9
9
|
Loading3QuartersOutlined,
|
|
10
10
|
BorderlessTableOutlined
|
|
11
11
|
} from '@ant-design/icons'
|
|
12
|
-
import generate from '../../common/uid'
|
|
13
12
|
import { Tooltip, message } from 'antd'
|
|
14
13
|
import classnames from 'classnames'
|
|
15
14
|
import copy from 'json-deep-copy'
|
|
@@ -18,8 +17,7 @@ import Input from '../common/input-auto-focus'
|
|
|
18
17
|
import createName from '../../common/create-title'
|
|
19
18
|
import { addClass, removeClass } from '../../common/class'
|
|
20
19
|
import {
|
|
21
|
-
terminalSshConfigType
|
|
22
|
-
commonActions
|
|
20
|
+
terminalSshConfigType
|
|
23
21
|
} from '../../common/constants'
|
|
24
22
|
import { shortcutDescExtend } from '../shortcuts/shortcut-handler.js'
|
|
25
23
|
|
|
@@ -31,13 +29,12 @@ class Tab extends Component {
|
|
|
31
29
|
constructor (props) {
|
|
32
30
|
super(props)
|
|
33
31
|
this.state = {
|
|
34
|
-
terminalOnData: false,
|
|
35
32
|
tab: copy(props.tab)
|
|
36
33
|
}
|
|
37
34
|
}
|
|
38
35
|
|
|
39
36
|
componentDidMount () {
|
|
40
|
-
this.dom = document.getElementById('
|
|
37
|
+
this.dom = document.getElementById('tab-' + this.state.tab.id)
|
|
41
38
|
window.addEventListener('message', this.onEvent)
|
|
42
39
|
}
|
|
43
40
|
|
|
@@ -47,12 +44,16 @@ class Tab extends Component {
|
|
|
47
44
|
tab: copy(this.props.tab)
|
|
48
45
|
})
|
|
49
46
|
}
|
|
47
|
+
if (this.props.openContextMenu && !prevProps.openContextMenu) {
|
|
48
|
+
this.handleContextMenu()
|
|
49
|
+
}
|
|
50
|
+
if (this.props.contextFunc && !prevProps.contextFunc) {
|
|
51
|
+
this[this.props.contextFunc](...this.props.contextArgs)
|
|
52
|
+
}
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
componentWillUnmount () {
|
|
53
|
-
|
|
54
|
-
window.removeEventListener('message', this.onContextAction)
|
|
55
|
-
clearTimeout(this.handler)
|
|
56
|
+
this.dom = null
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
shouldComponentUpdate (nextProps, nextState) {
|
|
@@ -70,10 +71,11 @@ class Tab extends Component {
|
|
|
70
71
|
'height',
|
|
71
72
|
'isLast',
|
|
72
73
|
'isMaximized',
|
|
73
|
-
'activeTerminalId',
|
|
74
74
|
'config',
|
|
75
75
|
'tab',
|
|
76
|
-
'width'
|
|
76
|
+
'width',
|
|
77
|
+
'openContextMenu',
|
|
78
|
+
'contextFunc'
|
|
77
79
|
]
|
|
78
80
|
|
|
79
81
|
// compare only the relevant props
|
|
@@ -84,28 +86,6 @@ class Tab extends Component {
|
|
|
84
86
|
runIdle(() => this.setState(...args))
|
|
85
87
|
}
|
|
86
88
|
|
|
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
89
|
clearCls = () => {
|
|
110
90
|
document.querySelectorAll('.' + onDragOverCls).forEach((d) => {
|
|
111
91
|
removeClass(d, onDragOverCls)
|
|
@@ -173,12 +153,24 @@ class Tab extends Component {
|
|
|
173
153
|
}
|
|
174
154
|
const { id } = fromTab
|
|
175
155
|
const tabs = copy(this.props.tabs)
|
|
176
|
-
const indexFrom = findIndex(tabs, t => t.id === id)
|
|
177
156
|
let indexDrop = findIndex(tabs, t => t.id === dropId)
|
|
178
|
-
|
|
179
|
-
|
|
157
|
+
const dropTab = tabs[indexDrop]
|
|
158
|
+
const indexFrom = findIndex(tabs, t => t.id === id)
|
|
159
|
+
if (indexFrom === -1) {
|
|
160
|
+
const fromBatch = fromTab.batch
|
|
161
|
+
setTimeout(() => {
|
|
162
|
+
const closeBtn = document.querySelector(`.v${fromBatch + 1} .tab-${id} .tab-close .anticon`)
|
|
163
|
+
if (closeBtn) {
|
|
164
|
+
closeBtn.click()
|
|
165
|
+
}
|
|
166
|
+
}, 10)
|
|
167
|
+
fromTab.batch = dropTab.batch
|
|
168
|
+
} else {
|
|
169
|
+
if (indexDrop > indexFrom) {
|
|
170
|
+
indexDrop = indexDrop - 1
|
|
171
|
+
}
|
|
172
|
+
tabs.splice(indexFrom, 1)
|
|
180
173
|
}
|
|
181
|
-
tabs.splice(indexFrom, 1)
|
|
182
174
|
tabs.splice(indexDrop, 0, fromTab)
|
|
183
175
|
this.props.setTabs(
|
|
184
176
|
tabs
|
|
@@ -206,6 +198,10 @@ class Tab extends Component {
|
|
|
206
198
|
)
|
|
207
199
|
}
|
|
208
200
|
|
|
201
|
+
cloneToNextLayout = () => {
|
|
202
|
+
window.store.cloneToNextLayout()
|
|
203
|
+
}
|
|
204
|
+
|
|
209
205
|
newTab = () => {
|
|
210
206
|
this.props.addTab()
|
|
211
207
|
}
|
|
@@ -276,10 +272,13 @@ class Tab extends Component {
|
|
|
276
272
|
const isSshConfig = tab.type === terminalSshConfigType
|
|
277
273
|
const res = []
|
|
278
274
|
const reloadShortcut = this.getShortcut('app_reloadCurrentTab')
|
|
275
|
+
const closeShortcut = this.getShortcut('app_closeCurrentTab')
|
|
276
|
+
const cloneToNextShortcut = this.getShortcut('app_cloneToNextLayout')
|
|
279
277
|
res.push({
|
|
280
278
|
func: 'handleClose',
|
|
281
279
|
icon: 'CloseOutlined',
|
|
282
|
-
text: e('close')
|
|
280
|
+
text: e('close'),
|
|
281
|
+
subText: closeShortcut
|
|
283
282
|
})
|
|
284
283
|
res.push({
|
|
285
284
|
func: 'closeOther',
|
|
@@ -303,6 +302,12 @@ class Tab extends Component {
|
|
|
303
302
|
icon: 'CopyOutlined',
|
|
304
303
|
text: e('duplicate')
|
|
305
304
|
})
|
|
305
|
+
res.push({
|
|
306
|
+
func: 'cloneToNextLayout',
|
|
307
|
+
icon: 'CopyOutlined',
|
|
308
|
+
text: e('cloneToNextLayout'),
|
|
309
|
+
subText: cloneToNextShortcut
|
|
310
|
+
})
|
|
306
311
|
res.push({
|
|
307
312
|
disabled: isSshConfig,
|
|
308
313
|
func: 'doRename',
|
|
@@ -318,39 +323,17 @@ class Tab extends Component {
|
|
|
318
323
|
return res
|
|
319
324
|
}
|
|
320
325
|
|
|
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()
|
|
326
|
+
handleContextMenu = () => {
|
|
327
|
+
const rect = this.dom.getBoundingClientRect()
|
|
343
328
|
const items = this.renderContext()
|
|
344
|
-
this.uid = generate()
|
|
345
329
|
window.store.openContextMenu({
|
|
346
330
|
items,
|
|
347
331
|
pos: {
|
|
348
332
|
left: rect.left,
|
|
349
333
|
top: rect.top + 20
|
|
350
334
|
},
|
|
351
|
-
id: this.
|
|
335
|
+
id: this.state.tab.id
|
|
352
336
|
})
|
|
353
|
-
window.addEventListener('message', this.onContextAction)
|
|
354
337
|
}
|
|
355
338
|
|
|
356
339
|
renderEditting (tab, cls) {
|
|
@@ -416,8 +399,8 @@ class Tab extends Component {
|
|
|
416
399
|
const {
|
|
417
400
|
currentTabId
|
|
418
401
|
} = this.props
|
|
419
|
-
const { isLast } = this.props
|
|
420
|
-
const { tab
|
|
402
|
+
const { isLast, terminalOnData } = this.props
|
|
403
|
+
const { tab } = this.state
|
|
421
404
|
const {
|
|
422
405
|
id,
|
|
423
406
|
isEditting,
|
|
@@ -461,7 +444,7 @@ class Tab extends Component {
|
|
|
461
444
|
<div
|
|
462
445
|
className={cls}
|
|
463
446
|
draggable
|
|
464
|
-
id={'
|
|
447
|
+
id={'tab-' + id}
|
|
465
448
|
data-id={id}
|
|
466
449
|
{...pick(this, [
|
|
467
450
|
'onDrag',
|
|
@@ -479,7 +462,6 @@ class Tab extends Component {
|
|
|
479
462
|
onClick={this.handleClick}
|
|
480
463
|
onDoubleClick={this.handleDup}
|
|
481
464
|
style={styleTag}
|
|
482
|
-
onContextMenu={this.handleContextMenu}
|
|
483
465
|
>
|
|
484
466
|
<Loading3QuartersOutlined
|
|
485
467
|
className='pointer tab-reload mg1r'
|