@electerm/electerm-react 1.50.21 → 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/components/layout/layout-item.jsx +69 -1
- package/client/components/layout/layout.jsx +1 -1
- package/client/components/layout/layout.styl +4 -1
- package/client/components/layout/layouts.jsx +2 -1
- package/client/components/main/custom-css.jsx +1 -1
- package/client/components/main/main.jsx +3 -3
- package/client/components/main/ui-theme.jsx +1 -1
- package/client/components/session/session.jsx +3 -13
- package/client/components/session/sessions.jsx +54 -19
- package/client/components/setting-sync/setting-sync-form.jsx +1 -1
- package/client/components/shortcuts/shortcuts-defaults.js +5 -5
- package/client/components/tabs/tab.jsx +13 -26
- package/client/components/terminal/attach-addon-custom.js +1 -1
- package/client/components/terminal/index.jsx +10 -9
- 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/db-upgrade.js +1 -1
- package/client/store/quick-command.js +1 -1
- package/client/store/setting.js +1 -1
- package/client/store/tab.js +27 -2
- package/package.json +1 -1
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
tabActions
|
|
3
|
+
} from '../../common/constants'
|
|
4
|
+
import postMsg from '../../common/post-msg'
|
|
5
|
+
|
|
1
6
|
export default function LayoutItem (props) {
|
|
2
7
|
const {
|
|
3
8
|
children,
|
|
4
9
|
i,
|
|
10
|
+
batch,
|
|
5
11
|
...itemProps
|
|
6
12
|
} = props
|
|
7
13
|
function handleClick (e) {
|
|
@@ -12,13 +18,75 @@ export default function LayoutItem (props) {
|
|
|
12
18
|
}
|
|
13
19
|
currentElement = currentElement.parentElement
|
|
14
20
|
}
|
|
21
|
+
window.store.currentLayoutBatch = i
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getDom () {
|
|
25
|
+
return document.querySelector(`.layout-item.v${batch + 1}`)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function onDrop (e) {
|
|
29
|
+
e.preventDefault()
|
|
30
|
+
const { target } = e
|
|
31
|
+
if (!target) {
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
let currentElement = target
|
|
35
|
+
while (currentElement) {
|
|
36
|
+
if (currentElement.classList && currentElement.classList.contains('tab')) {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
currentElement = currentElement.parentElement
|
|
40
|
+
}
|
|
41
|
+
// debug('target drop', target)
|
|
42
|
+
const fromTab = JSON.parse(e.dataTransfer.getData('fromFile'))
|
|
43
|
+
const onDropElem = getDom
|
|
44
|
+
if (!onDropElem || !fromTab || fromTab.batch === batch) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
const { store } = window
|
|
48
|
+
const { tabs } = store
|
|
49
|
+
const t = tabs.find(t => t.id === fromTab.id)
|
|
50
|
+
if (!t) {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
t.batch = batch
|
|
54
|
+
postMsg({
|
|
55
|
+
action: tabActions.changeCurrentTabId,
|
|
56
|
+
currentTabId: store.currentTabId
|
|
57
|
+
})
|
|
58
|
+
store.setTabs(tabs)
|
|
59
|
+
clearCls()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function clearCls () {
|
|
63
|
+
getDom()?.classList.remove('drag-over')
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function addCls () {
|
|
67
|
+
getDom()?.classList.add('drag-over')
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function onDragEnter () {
|
|
71
|
+
addCls()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function onDragLeave (e) {
|
|
75
|
+
clearCls()
|
|
76
|
+
}
|
|
15
77
|
|
|
16
|
-
|
|
78
|
+
function onDragEnd (e) {
|
|
79
|
+
clearCls()
|
|
80
|
+
e && e.dataTransfer && e.dataTransfer.clearData()
|
|
17
81
|
}
|
|
18
82
|
return (
|
|
19
83
|
<div
|
|
20
84
|
{...itemProps}
|
|
21
85
|
onClick={handleClick}
|
|
86
|
+
onDragEnter={onDragEnter}
|
|
87
|
+
onDragLeave={onDragLeave}
|
|
88
|
+
onDragEnd={onDragEnd}
|
|
89
|
+
onDrop={onDrop}
|
|
22
90
|
>
|
|
23
91
|
{children}
|
|
24
92
|
</div>
|
|
@@ -64,7 +64,7 @@ export default auto(function Index (props) {
|
|
|
64
64
|
if (window.et.isWebApp) {
|
|
65
65
|
window.onbeforeunload = store.beforeExit
|
|
66
66
|
}
|
|
67
|
-
store.
|
|
67
|
+
store.isSecondInstance = window.pre.runSync('isSecondInstance')
|
|
68
68
|
store.initData()
|
|
69
69
|
store.checkForDbUpgrade()
|
|
70
70
|
window.pre.runGlobalAsync('registerDeepLink')
|
|
@@ -76,7 +76,7 @@ export default auto(function Index (props) {
|
|
|
76
76
|
config,
|
|
77
77
|
terminalFullScreen,
|
|
78
78
|
pinned,
|
|
79
|
-
|
|
79
|
+
isSecondInstance,
|
|
80
80
|
pinnedQuickCommandBar,
|
|
81
81
|
wsInited,
|
|
82
82
|
upgradeInfo,
|
|
@@ -98,7 +98,7 @@ export default auto(function Index (props) {
|
|
|
98
98
|
pinned,
|
|
99
99
|
'qm-pinned': pinnedQuickCommandBar,
|
|
100
100
|
'term-fullscreen': terminalFullScreen,
|
|
101
|
-
'is-main': !
|
|
101
|
+
'is-main': !isSecondInstance
|
|
102
102
|
})
|
|
103
103
|
const ext1 = {
|
|
104
104
|
className: cls
|
|
@@ -20,7 +20,6 @@ import generate from '../../common/uid'
|
|
|
20
20
|
import copy from 'json-deep-copy'
|
|
21
21
|
import classnames from 'classnames'
|
|
22
22
|
import {
|
|
23
|
-
termControlHeight,
|
|
24
23
|
paneMap,
|
|
25
24
|
terminalActions,
|
|
26
25
|
connectionMap,
|
|
@@ -89,15 +88,6 @@ export default class SessionWrapper extends Component {
|
|
|
89
88
|
})
|
|
90
89
|
}
|
|
91
90
|
|
|
92
|
-
computeHeight = () => {
|
|
93
|
-
const {
|
|
94
|
-
tabsHeight
|
|
95
|
-
} = this.props
|
|
96
|
-
return this.props.height -
|
|
97
|
-
tabsHeight -
|
|
98
|
-
termControlHeight
|
|
99
|
-
}
|
|
100
|
-
|
|
101
91
|
editTab = (up) => {
|
|
102
92
|
const {
|
|
103
93
|
tab,
|
|
@@ -131,7 +121,7 @@ export default class SessionWrapper extends Component {
|
|
|
131
121
|
|
|
132
122
|
computePosition = (index) => {
|
|
133
123
|
const windowWidth = this.getWidth()
|
|
134
|
-
const heightAll = this.computeHeight()
|
|
124
|
+
const heightAll = this.props.computeHeight()
|
|
135
125
|
return {
|
|
136
126
|
height: heightAll,
|
|
137
127
|
width: windowWidth,
|
|
@@ -196,7 +186,7 @@ export default class SessionWrapper extends Component {
|
|
|
196
186
|
const cls = pane === paneMap.terminal
|
|
197
187
|
? 'terms-box'
|
|
198
188
|
: 'terms-box hide'
|
|
199
|
-
const height = this.computeHeight()
|
|
189
|
+
const height = this.props.computeHeight()
|
|
200
190
|
const { tab } = this.props
|
|
201
191
|
const width = this.getWidth()
|
|
202
192
|
const themeConfig = copy(window.store.getThemeConfig())
|
|
@@ -246,7 +236,7 @@ export default class SessionWrapper extends Component {
|
|
|
246
236
|
if (type === terminalRdpType) {
|
|
247
237
|
return null
|
|
248
238
|
}
|
|
249
|
-
const height = this.computeHeight(pane)
|
|
239
|
+
const height = this.props.computeHeight(pane)
|
|
250
240
|
const cls = pane === paneMap.terminal
|
|
251
241
|
? 'hide'
|
|
252
242
|
: ''
|
|
@@ -8,15 +8,13 @@ import copy from 'json-deep-copy'
|
|
|
8
8
|
import wait from '../../common/wait.js'
|
|
9
9
|
import Tabs from '../tabs/index.jsx'
|
|
10
10
|
import {
|
|
11
|
-
commonActions,
|
|
12
11
|
tabActions,
|
|
13
12
|
paneMap,
|
|
14
13
|
statusMap,
|
|
15
|
-
terminalWebType
|
|
14
|
+
terminalWebType,
|
|
15
|
+
termControlHeight
|
|
16
16
|
} from '../../common/constants.js'
|
|
17
17
|
import newTerm, { updateCount } from '../../common/new-terminal.js'
|
|
18
|
-
import postMsg from '../../common/post-msg.js'
|
|
19
|
-
|
|
20
18
|
import LogoElem from '../common/logo-elem.jsx'
|
|
21
19
|
import { Button } from 'antd'
|
|
22
20
|
import toSimpleObj from '../../common/to-simple-obj.js'
|
|
@@ -45,9 +43,7 @@ class Sessions extends Component {
|
|
|
45
43
|
this.props.tabs &&
|
|
46
44
|
!deepEqual(prevProps.tabs, this.props.tabs)
|
|
47
45
|
) {
|
|
48
|
-
this.
|
|
49
|
-
tabs: copy(this.props.tabs)
|
|
50
|
-
})
|
|
46
|
+
this.updateTabs(this.props.tabs)
|
|
51
47
|
}
|
|
52
48
|
}
|
|
53
49
|
|
|
@@ -58,11 +54,29 @@ class Sessions extends Component {
|
|
|
58
54
|
this.timer = null
|
|
59
55
|
}
|
|
60
56
|
|
|
57
|
+
updateTabs = (propTabs) => {
|
|
58
|
+
const update = {
|
|
59
|
+
tabs: copy(propTabs)
|
|
60
|
+
}
|
|
61
|
+
const currentTab = propTabs.find(t => t.id === this.state.currentTabId)
|
|
62
|
+
if (!currentTab) {
|
|
63
|
+
update.currentTabId = propTabs[0]?.id
|
|
64
|
+
}
|
|
65
|
+
this.setState(update)
|
|
66
|
+
}
|
|
67
|
+
|
|
61
68
|
initShortcuts () {
|
|
62
69
|
window.addEventListener('keydown', this.bindHandleKeyboardEvent)
|
|
63
70
|
}
|
|
64
71
|
|
|
72
|
+
notCurrentTab = (tab) => {
|
|
73
|
+
return this.state.currentTabId !== window.store.currentTabId
|
|
74
|
+
}
|
|
75
|
+
|
|
65
76
|
closeCurrentTabShortcut = (e) => {
|
|
77
|
+
if (this.notCurrentTab()) {
|
|
78
|
+
return
|
|
79
|
+
}
|
|
66
80
|
e.stopPropagation()
|
|
67
81
|
this.delTab(
|
|
68
82
|
this.state.currentTabId
|
|
@@ -70,12 +84,23 @@ class Sessions extends Component {
|
|
|
70
84
|
}
|
|
71
85
|
|
|
72
86
|
reloadCurrentTabShortcut = (e) => {
|
|
87
|
+
if (this.notCurrentTab()) {
|
|
88
|
+
return
|
|
89
|
+
}
|
|
73
90
|
e.stopPropagation()
|
|
74
91
|
this.reloadTab(
|
|
75
92
|
this.getCurrentTab()
|
|
76
93
|
)
|
|
77
94
|
}
|
|
78
95
|
|
|
96
|
+
cloneToNextLayoutShortcut = (e) => {
|
|
97
|
+
if (this.notCurrentTab()) {
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
e.stopPropagation()
|
|
101
|
+
window.store.cloneToNextLayout()
|
|
102
|
+
}
|
|
103
|
+
|
|
79
104
|
watch = () => {
|
|
80
105
|
window.addEventListener('message', this.onEvent)
|
|
81
106
|
}
|
|
@@ -94,18 +119,8 @@ class Sessions extends Component {
|
|
|
94
119
|
currentTabId: id
|
|
95
120
|
})
|
|
96
121
|
} else {
|
|
97
|
-
|
|
122
|
+
document.querySelector('.tab.active').click()
|
|
98
123
|
}
|
|
99
|
-
postMsg({
|
|
100
|
-
action: commonActions.updateStore,
|
|
101
|
-
value: id,
|
|
102
|
-
prop: 'currentTabId'
|
|
103
|
-
})
|
|
104
|
-
postMsg({
|
|
105
|
-
action: commonActions.updateStore,
|
|
106
|
-
value: id,
|
|
107
|
-
prop: 'currentTabId' + this.props.batch
|
|
108
|
-
})
|
|
109
124
|
}
|
|
110
125
|
|
|
111
126
|
getCurrentTab = () => {
|
|
@@ -185,6 +200,10 @@ class Sessions extends Component {
|
|
|
185
200
|
this.addTab(tab)
|
|
186
201
|
}
|
|
187
202
|
|
|
203
|
+
handleClick = () => {
|
|
204
|
+
window.store.currentTabId = this.state.currentTabId
|
|
205
|
+
}
|
|
206
|
+
|
|
188
207
|
reloadTab = async (tabToReload) => {
|
|
189
208
|
this.setState(async oldState => {
|
|
190
209
|
const tab = copy(
|
|
@@ -347,6 +366,15 @@ class Sessions extends Component {
|
|
|
347
366
|
)
|
|
348
367
|
}
|
|
349
368
|
|
|
369
|
+
computeHeight = () => {
|
|
370
|
+
const {
|
|
371
|
+
tabsHeight
|
|
372
|
+
} = this.props
|
|
373
|
+
return this.props.height -
|
|
374
|
+
tabsHeight -
|
|
375
|
+
termControlHeight
|
|
376
|
+
}
|
|
377
|
+
|
|
350
378
|
renderSessions () {
|
|
351
379
|
const {
|
|
352
380
|
config, width, height
|
|
@@ -389,6 +417,7 @@ class Sessions extends Component {
|
|
|
389
417
|
'onChangeTabId',
|
|
390
418
|
'onDuplicateTab',
|
|
391
419
|
'reloadTab',
|
|
420
|
+
'computeHeight',
|
|
392
421
|
'delTab',
|
|
393
422
|
'addTab',
|
|
394
423
|
'editTab'
|
|
@@ -396,7 +425,12 @@ class Sessions extends Component {
|
|
|
396
425
|
}
|
|
397
426
|
if (type === terminalWebType) {
|
|
398
427
|
const webProps = {
|
|
399
|
-
tab
|
|
428
|
+
tab,
|
|
429
|
+
width,
|
|
430
|
+
height: this.computeHeight(),
|
|
431
|
+
...pick(this, [
|
|
432
|
+
'reloadTab'
|
|
433
|
+
])
|
|
400
434
|
}
|
|
401
435
|
return (
|
|
402
436
|
<div className={cls} key={id}>
|
|
@@ -461,6 +495,7 @@ class Sessions extends Component {
|
|
|
461
495
|
<div
|
|
462
496
|
className='sessions'
|
|
463
497
|
key='main-sess'
|
|
498
|
+
onClick={this.handleClick}
|
|
464
499
|
>
|
|
465
500
|
{this.renderSessions()}
|
|
466
501
|
</div>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* bookmark form
|
|
7
7
|
*/
|
|
8
|
-
import { useDelta, useConditionalEffect } from 'react-delta'
|
|
8
|
+
import { useDelta, useConditionalEffect } from 'react-delta-hooks'
|
|
9
9
|
import { ArrowDownOutlined, ArrowUpOutlined, SaveOutlined, ClearOutlined } from '@ant-design/icons'
|
|
10
10
|
import { Button, Input, notification, Form } from 'antd'
|
|
11
11
|
import Link from '../common/external-link'
|
|
@@ -10,6 +10,11 @@ export default () => {
|
|
|
10
10
|
shortcut: 'alt+r',
|
|
11
11
|
shortcutMac: 'alt+r'
|
|
12
12
|
},
|
|
13
|
+
{
|
|
14
|
+
name: 'app_cloneToNextLayout',
|
|
15
|
+
shortcut: 'ctrl+/',
|
|
16
|
+
shortcutMac: 'meta+/'
|
|
17
|
+
},
|
|
13
18
|
{
|
|
14
19
|
name: 'app_newBookmark',
|
|
15
20
|
shortcut: 'ctrl+n',
|
|
@@ -40,11 +45,6 @@ export default () => {
|
|
|
40
45
|
shortcut: 'ctrl+tab',
|
|
41
46
|
shortcutMac: 'ctrl+tab'
|
|
42
47
|
},
|
|
43
|
-
{
|
|
44
|
-
name: 'terminal_split',
|
|
45
|
-
shortcut: 'ctrl+/',
|
|
46
|
-
shortcutMac: 'meta+/'
|
|
47
|
-
},
|
|
48
48
|
{
|
|
49
49
|
name: 'terminal_clear',
|
|
50
50
|
shortcut: 'ctrl+l,ctrl+shift+l',
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
Loading3QuartersOutlined,
|
|
10
10
|
BorderlessTableOutlined
|
|
11
11
|
} from '@ant-design/icons'
|
|
12
|
-
import generate from '../../common/id-with-stamp'
|
|
13
12
|
import { Tooltip, message } from 'antd'
|
|
14
13
|
import classnames from 'classnames'
|
|
15
14
|
import copy from 'json-deep-copy'
|
|
@@ -18,10 +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
|
-
splitConfig,
|
|
23
|
-
paneMap,
|
|
24
|
-
statusMap
|
|
20
|
+
terminalSshConfigType
|
|
25
21
|
} from '../../common/constants'
|
|
26
22
|
import { shortcutDescExtend } from '../shortcuts/shortcut-handler.js'
|
|
27
23
|
|
|
@@ -203,18 +199,7 @@ class Tab extends Component {
|
|
|
203
199
|
}
|
|
204
200
|
|
|
205
201
|
cloneToNextLayout = () => {
|
|
206
|
-
|
|
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)
|
|
202
|
+
window.store.cloneToNextLayout()
|
|
218
203
|
}
|
|
219
204
|
|
|
220
205
|
newTab = () => {
|
|
@@ -280,17 +265,20 @@ class Tab extends Component {
|
|
|
280
265
|
}
|
|
281
266
|
|
|
282
267
|
renderContext = () => {
|
|
283
|
-
const { tabs, tab
|
|
268
|
+
const { tabs, tab } = this.props
|
|
284
269
|
const len = tabs.length
|
|
285
270
|
const index = findIndex(tabs, t => t.id === tab.id)
|
|
286
271
|
const noRight = index >= len - 1
|
|
287
272
|
const isSshConfig = tab.type === terminalSshConfigType
|
|
288
273
|
const res = []
|
|
289
274
|
const reloadShortcut = this.getShortcut('app_reloadCurrentTab')
|
|
275
|
+
const closeShortcut = this.getShortcut('app_closeCurrentTab')
|
|
276
|
+
const cloneToNextShortcut = this.getShortcut('app_cloneToNextLayout')
|
|
290
277
|
res.push({
|
|
291
278
|
func: 'handleClose',
|
|
292
279
|
icon: 'CloseOutlined',
|
|
293
|
-
text: e('close')
|
|
280
|
+
text: e('close'),
|
|
281
|
+
subText: closeShortcut
|
|
294
282
|
})
|
|
295
283
|
res.push({
|
|
296
284
|
func: 'closeOther',
|
|
@@ -314,13 +302,12 @@ class Tab extends Component {
|
|
|
314
302
|
icon: 'CopyOutlined',
|
|
315
303
|
text: e('duplicate')
|
|
316
304
|
})
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
}
|
|
305
|
+
res.push({
|
|
306
|
+
func: 'cloneToNextLayout',
|
|
307
|
+
icon: 'CopyOutlined',
|
|
308
|
+
text: e('cloneToNextLayout'),
|
|
309
|
+
subText: cloneToNextShortcut
|
|
310
|
+
})
|
|
324
311
|
res.push({
|
|
325
312
|
disabled: isSshConfig,
|
|
326
313
|
func: 'doRename',
|
|
@@ -31,24 +31,24 @@ import {
|
|
|
31
31
|
} from '../../common/constants'
|
|
32
32
|
import deepCopy from 'json-deep-copy'
|
|
33
33
|
import { readClipboardAsync, copy } from '../../common/clipboard'
|
|
34
|
-
import { FitAddon } from 'xterm
|
|
34
|
+
import { FitAddon } from '@xterm/addon-fit'
|
|
35
35
|
import AttachAddon from './attach-addon-custom'
|
|
36
|
-
import { SearchAddon } from 'xterm
|
|
37
|
-
import { WebLinksAddon } from 'xterm
|
|
38
|
-
import { CanvasAddon } from 'xterm
|
|
39
|
-
import { WebglAddon } from 'xterm
|
|
40
|
-
import { LigaturesAddon } from 'xterm
|
|
36
|
+
import { SearchAddon } from '@xterm/addon-search'
|
|
37
|
+
import { WebLinksAddon } from '@xterm/addon-web-links'
|
|
38
|
+
import { CanvasAddon } from '@xterm/addon-canvas'
|
|
39
|
+
import { WebglAddon } from '@xterm/addon-webgl'
|
|
40
|
+
import { LigaturesAddon } from '@xterm/addon-ligatures'
|
|
41
41
|
import getProxy from '../../common/get-proxy'
|
|
42
42
|
import { AddonZmodem } from './xterm-zmodem'
|
|
43
|
-
import { Unicode11Addon } from 'xterm
|
|
43
|
+
import { Unicode11Addon } from '@xterm/addon-unicode11'
|
|
44
44
|
import keyControlPressed from '../../common/key-control-pressed'
|
|
45
|
-
import { Terminal } from 'xterm'
|
|
45
|
+
import { Terminal } from '@xterm/xterm'
|
|
46
46
|
import NormalBuffer from './normal-buffer'
|
|
47
47
|
import { createTerm, resizeTerm } from './terminal-apis'
|
|
48
48
|
import { shortcutExtend, shortcutDescExtend } from '../shortcuts/shortcut-handler.js'
|
|
49
49
|
import { KeywordHighlighterAddon } from './highlight-addon.js'
|
|
50
50
|
import { getLocalFileInfo } from '../sftp/file-read.js'
|
|
51
|
-
import { SerializeAddon } from 'xterm
|
|
51
|
+
import { SerializeAddon } from '@xterm/addon-serialize'
|
|
52
52
|
import strip from '@electerm/strip-ansi'
|
|
53
53
|
import { formatBytes } from '../../common/byte-format.js'
|
|
54
54
|
import * as fs from './fs.js'
|
|
@@ -1237,6 +1237,7 @@ clear\r`
|
|
|
1237
1237
|
new KeywordHighlighterAddon(keywords)
|
|
1238
1238
|
)
|
|
1239
1239
|
window.store.triggerResize()
|
|
1240
|
+
window.store.focus()
|
|
1240
1241
|
}
|
|
1241
1242
|
|
|
1242
1243
|
onResize = throttle(() => {
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Input,
|
|
3
|
+
Tooltip
|
|
4
|
+
} from 'antd'
|
|
5
|
+
import { copy } from '../../common/clipboard'
|
|
6
|
+
import {
|
|
7
|
+
ReloadOutlined,
|
|
8
|
+
GlobalOutlined
|
|
9
|
+
} from '@ant-design/icons'
|
|
10
|
+
|
|
11
|
+
export default function AddressBar (props) {
|
|
12
|
+
const {
|
|
13
|
+
url,
|
|
14
|
+
onReload,
|
|
15
|
+
onOpen,
|
|
16
|
+
title,
|
|
17
|
+
description
|
|
18
|
+
} = props
|
|
19
|
+
const content = (
|
|
20
|
+
<div>
|
|
21
|
+
<h1>{title}</h1>
|
|
22
|
+
<p>{description}</p>
|
|
23
|
+
</div>
|
|
24
|
+
)
|
|
25
|
+
function handleClick () {
|
|
26
|
+
copy(url)
|
|
27
|
+
}
|
|
28
|
+
return (
|
|
29
|
+
<div className='web-address-bar pd1'>
|
|
30
|
+
<Tooltip
|
|
31
|
+
title={content}
|
|
32
|
+
>
|
|
33
|
+
<Input
|
|
34
|
+
value={url}
|
|
35
|
+
onClick={handleClick}
|
|
36
|
+
addonBefore={
|
|
37
|
+
<ReloadOutlined
|
|
38
|
+
onClick={onReload}
|
|
39
|
+
/>
|
|
40
|
+
}
|
|
41
|
+
addonAfter={
|
|
42
|
+
<GlobalOutlined
|
|
43
|
+
onClick={onOpen}
|
|
44
|
+
/>
|
|
45
|
+
}
|
|
46
|
+
/>
|
|
47
|
+
</Tooltip>
|
|
48
|
+
</div>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
@@ -1,19 +1,41 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Link from '../common/external-link'
|
|
1
|
+
import AddressBar from './address-bar'
|
|
3
2
|
|
|
4
3
|
export default function WebSession (props) {
|
|
5
4
|
const {
|
|
6
|
-
tab
|
|
5
|
+
tab,
|
|
6
|
+
width,
|
|
7
|
+
height,
|
|
8
|
+
reloadTab
|
|
7
9
|
} = props
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
const addrProps = {
|
|
11
|
+
url: tab.url,
|
|
12
|
+
title: tab.title,
|
|
13
|
+
description: tab.description,
|
|
14
|
+
onOpen: () => {
|
|
15
|
+
window.openLink(tab.url)
|
|
16
|
+
},
|
|
17
|
+
onReload: () => {
|
|
18
|
+
reloadTab(
|
|
19
|
+
tab
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const viewProps = {
|
|
24
|
+
src: tab.url,
|
|
25
|
+
style: {
|
|
26
|
+
width: (width - 10) + 'px',
|
|
27
|
+
height: (height - 12) + 'px'
|
|
28
|
+
},
|
|
29
|
+
disableblinkfeatures: 'true',
|
|
30
|
+
disablewebsecurity: 'true'
|
|
31
|
+
}
|
|
11
32
|
return (
|
|
12
33
|
<div className='web-session-wrap'>
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
<
|
|
16
|
-
|
|
34
|
+
<AddressBar {...addrProps} />
|
|
35
|
+
<div className='pd1'>
|
|
36
|
+
<webview
|
|
37
|
+
{...viewProps}
|
|
38
|
+
/>
|
|
17
39
|
</div>
|
|
18
40
|
</div>
|
|
19
41
|
)
|
package/client/entry/index.jsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRoot } from 'react-dom/client'
|
|
2
2
|
import 'antd/dist/reset.css'
|
|
3
|
-
import 'xterm/css/xterm.css'
|
|
3
|
+
import '@xterm/xterm/css/xterm.css'
|
|
4
4
|
import '../common/trzsz'
|
|
5
5
|
import 'firacode/distr/fira_code.css'
|
|
6
6
|
import Main from '../components/main/index.jsx'
|
|
@@ -9,8 +9,7 @@ notification.config({
|
|
|
9
9
|
placement: 'bottomRight'
|
|
10
10
|
})
|
|
11
11
|
|
|
12
|
-
const rootElement = document.getElementById('container')
|
|
13
|
-
render(
|
|
14
|
-
<Main
|
|
15
|
-
rootElement
|
|
12
|
+
const rootElement = createRoot(document.getElementById('container'))
|
|
13
|
+
rootElement.render(
|
|
14
|
+
<Main />
|
|
16
15
|
)
|
|
@@ -9,7 +9,7 @@ import initWatch from './watch'
|
|
|
9
9
|
export default (Store) => {
|
|
10
10
|
Store.prototype.checkForDbUpgrade = async function () {
|
|
11
11
|
const { store } = window
|
|
12
|
-
if (store.
|
|
12
|
+
if (store.isSecondInstance) {
|
|
13
13
|
return false
|
|
14
14
|
}
|
|
15
15
|
const shouldUpgrade = await window.pre.runGlobalAsync('checkDbUpgrade')
|
package/client/store/setting.js
CHANGED
package/client/store/tab.js
CHANGED
|
@@ -5,11 +5,14 @@
|
|
|
5
5
|
import { uniq, debounce, findIndex } from 'lodash-es'
|
|
6
6
|
import {
|
|
7
7
|
tabActions,
|
|
8
|
-
splitConfig
|
|
8
|
+
splitConfig,
|
|
9
|
+
statusMap,
|
|
10
|
+
paneMap
|
|
9
11
|
} from '../common/constants'
|
|
10
12
|
import postMsg from '../common/post-msg'
|
|
11
13
|
import * as ls from '../common/safe-local-storage'
|
|
12
14
|
import deepCopy from 'json-deep-copy'
|
|
15
|
+
import generate from '../common/id-with-stamp'
|
|
13
16
|
|
|
14
17
|
export default Store => {
|
|
15
18
|
Store.prototype.updateTabsStatus = function () {
|
|
@@ -63,7 +66,7 @@ export default Store => {
|
|
|
63
66
|
postMsg({
|
|
64
67
|
action: tabActions.addTab,
|
|
65
68
|
tab,
|
|
66
|
-
batch: window.openTabBatch ?? window.store.currentLayoutBatch,
|
|
69
|
+
batch: tab?.batch ?? window.openTabBatch ?? window.store.currentLayoutBatch,
|
|
67
70
|
index
|
|
68
71
|
})
|
|
69
72
|
}
|
|
@@ -96,6 +99,28 @@ export default Store => {
|
|
|
96
99
|
}
|
|
97
100
|
}
|
|
98
101
|
|
|
102
|
+
Store.prototype.cloneToNextLayout = function () {
|
|
103
|
+
const { store } = window
|
|
104
|
+
const defaultStatus = statusMap.processing
|
|
105
|
+
const { currentTab, layout, currentLayoutBatch } = store
|
|
106
|
+
const ntb = deepCopy(currentTab)
|
|
107
|
+
Object.assign(ntb, {
|
|
108
|
+
id: generate(),
|
|
109
|
+
status: defaultStatus,
|
|
110
|
+
isTransporting: undefined,
|
|
111
|
+
pane: paneMap.terminal
|
|
112
|
+
})
|
|
113
|
+
let maxBatch = splitConfig[layout].children
|
|
114
|
+
if (maxBatch < 2) {
|
|
115
|
+
maxBatch = 2
|
|
116
|
+
}
|
|
117
|
+
ntb.batch = (currentLayoutBatch + 1) % maxBatch
|
|
118
|
+
store.addTab(ntb)
|
|
119
|
+
if (layout === 'c1') {
|
|
120
|
+
store.setLayout('c2')
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
99
124
|
Store.prototype.setLayout = function (layout) {
|
|
100
125
|
const {
|
|
101
126
|
store
|