@electerm/electerm-react 1.38.65 → 1.38.80
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 +6 -3
- package/client/common/create-title.jsx +9 -1
- package/client/common/sftp.js +3 -0
- package/client/components/batch-op/batch-op.jsx +1 -6
- package/client/components/bookmark-form/bookmark-form.styl +3 -1
- package/client/components/bookmark-form/index.jsx +12 -8
- package/client/components/bookmark-form/render-ssh-tunnel.jsx +210 -88
- package/client/components/bookmark-form/ssh-form-ui.jsx +1 -1
- package/client/components/bookmark-form/web-form-ui.jsx +96 -0
- package/client/components/bookmark-form/web-form.jsx +16 -0
- package/client/components/main/main.jsx +14 -0
- package/client/components/quick-commands/qm.styl +1 -1
- package/client/components/session/session.styl +4 -1
- package/client/components/session/sessions.jsx +16 -2
- package/client/components/session/web-session.jsx +20 -0
- package/client/components/sftp/{confirm-modal.jsx → confirm-modal-store.jsx} +81 -50
- package/client/components/sftp/file-item.jsx +2 -0
- package/client/components/sftp/sftp-entry.jsx +27 -37
- package/client/components/sftp/transfer-conflict-store.jsx +291 -0
- package/client/components/sftp/transport-action-store.jsx +430 -0
- package/client/components/sftp/transports-action-store.jsx +102 -0
- package/client/components/sftp/transports-ui-store.jsx +30 -0
- package/client/components/sidebar/transfer-list-control.jsx +5 -14
- package/client/components/sidebar/transport-ui.jsx +2 -12
- package/client/components/tabs/tab.jsx +43 -2
- package/client/components/tabs/tabs.styl +1 -1
- package/client/components/terminal/index.jsx +14 -1
- package/client/components/terminal/terminal-interactive.jsx +15 -0
- package/client/components/terminal-info/disk.jsx +9 -0
- package/client/entry/worker.js +5 -1
- package/client/store/index.js +16 -1
- package/client/store/init-state.js +2 -3
- package/client/store/sync.js +5 -2
- package/client/store/tab.js +1 -1
- package/client/store/transfer-list.js +55 -2
- package/client/store/watch.js +0 -8
- package/package.json +1 -1
- package/client/components/sftp/transfer-conflict.jsx +0 -323
- package/client/components/sftp/transport-action.jsx +0 -412
- package/client/components/sftp/transport-entry.jsx +0 -108
- package/client/components/sftp/transport-types.js +0 -8
- package/client/components/sftp/transports-action.jsx +0 -111
- package/client/components/sftp/transports-ui.jsx +0 -93
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Component } from '../common/react-subx'
|
|
2
2
|
import Session from './session'
|
|
3
|
+
import WebSession from './web-session'
|
|
3
4
|
import { findIndex, pick } from 'lodash-es'
|
|
4
5
|
import classNames from 'classnames'
|
|
5
6
|
import generate from '../../common/uid'
|
|
@@ -11,7 +12,8 @@ import {
|
|
|
11
12
|
tabActions,
|
|
12
13
|
termInitId,
|
|
13
14
|
paneMap,
|
|
14
|
-
statusMap
|
|
15
|
+
statusMap,
|
|
16
|
+
terminalWebType
|
|
15
17
|
} from '../../common/constants'
|
|
16
18
|
import newTerm, { updateCount } from '../../common/new-terminal'
|
|
17
19
|
import postMsg from '../../common/post-msg'
|
|
@@ -336,7 +338,7 @@ class Sessions extends Component {
|
|
|
336
338
|
return this.renderNoSession()
|
|
337
339
|
}
|
|
338
340
|
return tabs.map((tab) => {
|
|
339
|
-
const { id } = tab
|
|
341
|
+
const { id, type } = tab
|
|
340
342
|
const cls = classNames(
|
|
341
343
|
`session-wrap session-${id}`,
|
|
342
344
|
{
|
|
@@ -372,6 +374,18 @@ class Sessions extends Component {
|
|
|
372
374
|
'editTab'
|
|
373
375
|
])
|
|
374
376
|
}
|
|
377
|
+
if (type === terminalWebType) {
|
|
378
|
+
const webProps = {
|
|
379
|
+
tab
|
|
380
|
+
}
|
|
381
|
+
return (
|
|
382
|
+
<div className={cls} key={id}>
|
|
383
|
+
<WebSession
|
|
384
|
+
{...webProps}
|
|
385
|
+
/>
|
|
386
|
+
</div>
|
|
387
|
+
)
|
|
388
|
+
}
|
|
375
389
|
return (
|
|
376
390
|
<div className={cls} key={id}>
|
|
377
391
|
<Session
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useEffect } from 'react'
|
|
2
|
+
import Link from '../common/external-link'
|
|
3
|
+
|
|
4
|
+
export default function WebSession (props) {
|
|
5
|
+
const {
|
|
6
|
+
tab
|
|
7
|
+
} = props
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
tab.url && window.openLink(tab.url)
|
|
10
|
+
}, [])
|
|
11
|
+
return (
|
|
12
|
+
<div className='web-session-wrap'>
|
|
13
|
+
<div className='pd3 aligncenter'>
|
|
14
|
+
<h1>{tab.title}</h1>
|
|
15
|
+
<p>{tab.description}</p>
|
|
16
|
+
<Link to={tab.url}>{tab.url}</Link>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { Component } from '../common/react-subx'
|
|
6
7
|
import { Modal, Button } from 'antd'
|
|
7
8
|
import { isString } from 'lodash-es'
|
|
8
9
|
import AnimateText from '../common/animate-text'
|
|
@@ -23,42 +24,51 @@ function formatTimeAuto (strOrDigit) {
|
|
|
23
24
|
return formatTime(strOrDigit * 1000)
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
export default
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
modifyTime: modifyTimeTo,
|
|
43
|
-
size: sizeTo,
|
|
44
|
-
type: typeTo
|
|
45
|
-
},
|
|
46
|
-
id,
|
|
47
|
-
transferGroupId
|
|
48
|
-
} = props.transferToConfirm
|
|
49
|
-
function act (action) {
|
|
50
|
-
props.modifier({
|
|
51
|
-
transferToConfirm: null
|
|
52
|
-
})
|
|
27
|
+
export default class ConfirmModalStore extends Component {
|
|
28
|
+
act (action) {
|
|
29
|
+
const { store } = this.props
|
|
30
|
+
const {
|
|
31
|
+
transferToConfirm
|
|
32
|
+
} = store
|
|
33
|
+
store.setState(
|
|
34
|
+
'transferToConfirm', {}
|
|
35
|
+
)
|
|
36
|
+
const {
|
|
37
|
+
fromFile: {
|
|
38
|
+
id: fileId
|
|
39
|
+
},
|
|
40
|
+
id,
|
|
41
|
+
transferGroupId
|
|
42
|
+
} = transferToConfirm
|
|
53
43
|
postMessage({
|
|
54
44
|
transferGroupId,
|
|
55
45
|
fileId,
|
|
56
46
|
id,
|
|
57
|
-
transfer:
|
|
47
|
+
transfer: transferToConfirm,
|
|
58
48
|
action
|
|
59
49
|
})
|
|
60
50
|
}
|
|
61
|
-
|
|
51
|
+
|
|
52
|
+
renderContent () {
|
|
53
|
+
const {
|
|
54
|
+
transferToConfirm
|
|
55
|
+
} = this.props.store
|
|
56
|
+
const {
|
|
57
|
+
fromPath,
|
|
58
|
+
toPath,
|
|
59
|
+
fromFile: {
|
|
60
|
+
isDirectory,
|
|
61
|
+
name,
|
|
62
|
+
modifyTime: modifyTimeFrom,
|
|
63
|
+
size: sizeFrom,
|
|
64
|
+
type: typeFrom
|
|
65
|
+
},
|
|
66
|
+
toFile: {
|
|
67
|
+
modifyTime: modifyTimeTo,
|
|
68
|
+
size: sizeTo,
|
|
69
|
+
type: typeTo
|
|
70
|
+
}
|
|
71
|
+
} = transferToConfirm
|
|
62
72
|
const action = isDirectory ? e('merge') : e('replace')
|
|
63
73
|
const typeTxt = isDirectory ? e('folder') : e('file')
|
|
64
74
|
const Icon = isDirectory ? FolderOutlined : FileOutlined
|
|
@@ -95,27 +105,39 @@ export default (props) => {
|
|
|
95
105
|
</div>
|
|
96
106
|
)
|
|
97
107
|
}
|
|
98
|
-
|
|
108
|
+
|
|
109
|
+
renderFooter () {
|
|
110
|
+
const {
|
|
111
|
+
transferToConfirm
|
|
112
|
+
} = this.props.store
|
|
113
|
+
if (!transferToConfirm) {
|
|
114
|
+
return null
|
|
115
|
+
}
|
|
116
|
+
const {
|
|
117
|
+
fromFile: {
|
|
118
|
+
isDirectory
|
|
119
|
+
}
|
|
120
|
+
} = transferToConfirm
|
|
99
121
|
return (
|
|
100
122
|
<div className='mgq1t pd1y alignright'>
|
|
101
123
|
<Button
|
|
102
124
|
type='dashed'
|
|
103
125
|
className='mg1l'
|
|
104
|
-
onClick={() => act(fileActions.cancel)}
|
|
126
|
+
onClick={() => this.act(fileActions.cancel)}
|
|
105
127
|
>
|
|
106
128
|
{e('cancel')}
|
|
107
129
|
</Button>
|
|
108
130
|
<Button
|
|
109
131
|
type='dashed'
|
|
110
132
|
className='mg1l'
|
|
111
|
-
onClick={() => act(fileActions.skip)}
|
|
133
|
+
onClick={() => this.act(fileActions.skip)}
|
|
112
134
|
>
|
|
113
135
|
{e('skip')}
|
|
114
136
|
</Button>
|
|
115
137
|
<Button
|
|
116
138
|
type='dashed'
|
|
117
139
|
className='mg1l'
|
|
118
|
-
onClick={() => act(fileActions.skipAll)}
|
|
140
|
+
onClick={() => this.act(fileActions.skipAll)}
|
|
119
141
|
>
|
|
120
142
|
{e('skipAll')}
|
|
121
143
|
</Button>
|
|
@@ -123,7 +145,7 @@ export default (props) => {
|
|
|
123
145
|
danger
|
|
124
146
|
className='mg1l'
|
|
125
147
|
onClick={
|
|
126
|
-
() => act(fileActions.mergeOrOverwrite)
|
|
148
|
+
() => this.act(fileActions.mergeOrOverwrite)
|
|
127
149
|
}
|
|
128
150
|
>
|
|
129
151
|
{isDirectory ? e('merge') : e('overwrite')}
|
|
@@ -132,7 +154,7 @@ export default (props) => {
|
|
|
132
154
|
type='primary'
|
|
133
155
|
className='mg1l'
|
|
134
156
|
onClick={
|
|
135
|
-
() => act(fileActions.rename)
|
|
157
|
+
() => this.act(fileActions.rename)
|
|
136
158
|
}
|
|
137
159
|
>
|
|
138
160
|
{e('rename')}
|
|
@@ -148,7 +170,7 @@ export default (props) => {
|
|
|
148
170
|
: e('overwriteDesc')
|
|
149
171
|
}
|
|
150
172
|
onClick={
|
|
151
|
-
() => act(fileActions.mergeOrOverwriteAll)
|
|
173
|
+
() => this.act(fileActions.mergeOrOverwriteAll)
|
|
152
174
|
}
|
|
153
175
|
>
|
|
154
176
|
{isDirectory ? e('mergeAll') : e('overwriteAll')}
|
|
@@ -158,7 +180,7 @@ export default (props) => {
|
|
|
158
180
|
className='mg1l'
|
|
159
181
|
title={e('renameDesc')}
|
|
160
182
|
onClick={
|
|
161
|
-
() => act(fileActions.renameAll)
|
|
183
|
+
() => this.act(fileActions.renameAll)
|
|
162
184
|
}
|
|
163
185
|
>
|
|
164
186
|
{e('renameAll')}
|
|
@@ -167,18 +189,27 @@ export default (props) => {
|
|
|
167
189
|
</div>
|
|
168
190
|
)
|
|
169
191
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
192
|
+
|
|
193
|
+
render () {
|
|
194
|
+
const {
|
|
195
|
+
transferToConfirm
|
|
196
|
+
} = this.props.store
|
|
197
|
+
if (!transferToConfirm.id) {
|
|
198
|
+
return null
|
|
199
|
+
}
|
|
200
|
+
const modalProps = {
|
|
201
|
+
open: true,
|
|
202
|
+
width: 500,
|
|
203
|
+
title: e('fileConflict'),
|
|
204
|
+
footer: this.renderFooter(),
|
|
205
|
+
onCancel: () => this.act(fileActions.cancel)
|
|
206
|
+
}
|
|
207
|
+
return (
|
|
208
|
+
<Modal
|
|
209
|
+
{...modalProps}
|
|
210
|
+
>
|
|
211
|
+
{this.renderContent()}
|
|
212
|
+
</Modal>
|
|
213
|
+
)
|
|
176
214
|
}
|
|
177
|
-
return (
|
|
178
|
-
<Modal
|
|
179
|
-
{...modalProps}
|
|
180
|
-
>
|
|
181
|
-
{renderContent()}
|
|
182
|
-
</Modal>
|
|
183
|
-
)
|
|
184
215
|
}
|
|
@@ -168,6 +168,7 @@ export default class FileSection extends React.Component {
|
|
|
168
168
|
fromPath,
|
|
169
169
|
toPath,
|
|
170
170
|
id: generate(),
|
|
171
|
+
host: this.props.tab?.host,
|
|
171
172
|
...createTransferProps(this.props),
|
|
172
173
|
operation
|
|
173
174
|
})
|
|
@@ -804,6 +805,7 @@ export default class FileSection extends React.Component {
|
|
|
804
805
|
}
|
|
805
806
|
toPath = resolve(toPath, name)
|
|
806
807
|
const obj = {
|
|
808
|
+
host: this.props.tab?.host,
|
|
807
809
|
typeFrom: type,
|
|
808
810
|
typeTo,
|
|
809
811
|
fromPath: resolve(path, name),
|
|
@@ -14,8 +14,10 @@ import {
|
|
|
14
14
|
typeMap, maxSftpHistory, paneMap,
|
|
15
15
|
eventTypes,
|
|
16
16
|
fileTypeMap,
|
|
17
|
-
terminalSshConfigType,
|
|
18
|
-
|
|
17
|
+
terminalSshConfigType,
|
|
18
|
+
terminalSerialType,
|
|
19
|
+
unexpectedPacketErrorDesc,
|
|
20
|
+
sftpRetryInterval,
|
|
19
21
|
commonActions
|
|
20
22
|
} from '../../common/constants'
|
|
21
23
|
import { hasFileInClipboardText } from '../../common/clipboard'
|
|
@@ -27,7 +29,6 @@ import ListTable from './list-table-ui'
|
|
|
27
29
|
import deepCopy from 'json-deep-copy'
|
|
28
30
|
import isValidPath from '../../common/is-valid-path'
|
|
29
31
|
import memoizeOne from 'memoize-one'
|
|
30
|
-
import TransportEntry from './transport-entry'
|
|
31
32
|
import postMessage from '../../common/post-msg'
|
|
32
33
|
import { runCmd } from '../terminal/terminal-apis'
|
|
33
34
|
import * as owner from './owner-list'
|
|
@@ -58,9 +59,6 @@ export default class Sftp extends Component {
|
|
|
58
59
|
onEditFile: false,
|
|
59
60
|
...this.defaultState(),
|
|
60
61
|
loadingSftp: false,
|
|
61
|
-
transferToConfirm: null,
|
|
62
|
-
transferList: [],
|
|
63
|
-
pauseAll: false,
|
|
64
62
|
inited: false
|
|
65
63
|
}
|
|
66
64
|
this.retryCount = 0
|
|
@@ -190,11 +188,27 @@ export default class Sftp extends Component {
|
|
|
190
188
|
}, isEqual)
|
|
191
189
|
|
|
192
190
|
initEvent () {
|
|
191
|
+
window.addEventListener('message', this.handleMsg)
|
|
193
192
|
window.addEventListener('keydown', this.handleEvent)
|
|
194
193
|
}
|
|
195
194
|
|
|
196
195
|
destroyEvent () {
|
|
197
196
|
window.removeEventListener('keydown', this.handleEvent)
|
|
197
|
+
window.removeEventListener('message', this.handleMsg)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
handleMsg = event => {
|
|
201
|
+
const {
|
|
202
|
+
action,
|
|
203
|
+
sessionId,
|
|
204
|
+
type
|
|
205
|
+
} = event?.data || {}
|
|
206
|
+
if (
|
|
207
|
+
action === commonActions.sftpList &&
|
|
208
|
+
sessionId === this.props.sessionId
|
|
209
|
+
) {
|
|
210
|
+
this[type + 'List']()
|
|
211
|
+
}
|
|
198
212
|
}
|
|
199
213
|
|
|
200
214
|
isActive () {
|
|
@@ -437,32 +451,28 @@ export default class Sftp extends Component {
|
|
|
437
451
|
}
|
|
438
452
|
const { type } = lastClickedFile
|
|
439
453
|
const { inputFocus, onDelete } = this
|
|
454
|
+
e.stopPropagation()
|
|
440
455
|
if (keyControlPressed(e) && keyPressed(e, 'keyA') && !inputFocus) {
|
|
441
|
-
e.stopPropagation()
|
|
442
456
|
this.selectAll(type, e)
|
|
443
457
|
} else if (keyPressed(e, 'arrowdown') && !inputFocus) {
|
|
444
|
-
e.stopPropagation()
|
|
445
458
|
this.selectNext(type)
|
|
446
459
|
} else if (keyPressed(e, 'arrowup') && !inputFocus) {
|
|
447
|
-
e.stopPropagation()
|
|
448
460
|
this.selectPrev(type)
|
|
449
|
-
} else if (
|
|
450
|
-
e
|
|
461
|
+
} else if (
|
|
462
|
+
keyPressed(e, 'delete') &&
|
|
463
|
+
!inputFocus &&
|
|
464
|
+
!this.state.onEditFile
|
|
465
|
+
) {
|
|
451
466
|
this.onDel(type)
|
|
452
467
|
} else if (keyPressed(e, 'enter') && !inputFocus && !onDelete) {
|
|
453
|
-
e.stopPropagation()
|
|
454
468
|
this.enter(type, e)
|
|
455
469
|
} else if (keyControlPressed(e) && keyPressed(e, 'keyC') && !inputFocus) {
|
|
456
|
-
e.stopPropagation()
|
|
457
470
|
this.doCopy(type, e)
|
|
458
471
|
} else if (keyControlPressed(e) && keyPressed(e, 'keyX') && !inputFocus) {
|
|
459
|
-
e.stopPropagation()
|
|
460
472
|
this.doCut(type, e)
|
|
461
473
|
} else if (keyControlPressed(e) && keyPressed(e, 'keyV') && !inputFocus) {
|
|
462
|
-
e.stopPropagation()
|
|
463
474
|
this.doPaste(type, e)
|
|
464
475
|
} else if (keyPressed(e, 'f5')) {
|
|
465
|
-
e.stopPropagation()
|
|
466
476
|
this.onGoto(type)
|
|
467
477
|
}
|
|
468
478
|
}
|
|
@@ -496,11 +506,7 @@ export default class Sftp extends Component {
|
|
|
496
506
|
}
|
|
497
507
|
|
|
498
508
|
addTransferList = list => {
|
|
499
|
-
|
|
500
|
-
list,
|
|
501
|
-
action: commonActions.addTransfer,
|
|
502
|
-
sessionId: this.props.sessionId
|
|
503
|
-
})
|
|
509
|
+
window.store.addTransferList(list)
|
|
504
510
|
}
|
|
505
511
|
|
|
506
512
|
computeListHeight = () => {
|
|
@@ -906,11 +912,8 @@ export default class Sftp extends Component {
|
|
|
906
912
|
typeMap.remote,
|
|
907
913
|
'lastClickedFile',
|
|
908
914
|
'lastMataKey',
|
|
909
|
-
'transferToConfirm',
|
|
910
|
-
'transferList',
|
|
911
915
|
'targetTransferType',
|
|
912
916
|
'selectedFiles',
|
|
913
|
-
'pauseAll',
|
|
914
917
|
'localGidTree',
|
|
915
918
|
'remoteUidTree',
|
|
916
919
|
'localUidTree',
|
|
@@ -1108,18 +1111,6 @@ export default class Sftp extends Component {
|
|
|
1108
1111
|
const {
|
|
1109
1112
|
id
|
|
1110
1113
|
} = this.state
|
|
1111
|
-
const prps = {
|
|
1112
|
-
localList: this.localList,
|
|
1113
|
-
remoteList: this.remoteList,
|
|
1114
|
-
sftp: this.sftp,
|
|
1115
|
-
sessionId: this.props.sessionId,
|
|
1116
|
-
host: this.props.tab.host,
|
|
1117
|
-
localListDebounce: this.localListDebounce,
|
|
1118
|
-
remoteListDebounce: this.remoteListDebounce,
|
|
1119
|
-
config: this.props.config,
|
|
1120
|
-
tab: this.props.tab,
|
|
1121
|
-
pid: this.props.pid
|
|
1122
|
-
}
|
|
1123
1114
|
const all = {
|
|
1124
1115
|
className: 'sftp-wrap overhide relative',
|
|
1125
1116
|
id: `id-${id}`,
|
|
@@ -1132,7 +1123,6 @@ export default class Sftp extends Component {
|
|
|
1132
1123
|
{
|
|
1133
1124
|
this.renderSections()
|
|
1134
1125
|
}
|
|
1135
|
-
<TransportEntry {...prps} />
|
|
1136
1126
|
</div>
|
|
1137
1127
|
)
|
|
1138
1128
|
}
|