@electerm/electerm-react 1.38.65 → 1.38.70

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.
Files changed (35) hide show
  1. package/client/common/constants.js +3 -2
  2. package/client/common/create-title.jsx +9 -1
  3. package/client/common/sftp.js +3 -0
  4. package/client/components/batch-op/batch-op.jsx +1 -6
  5. package/client/components/bookmark-form/bookmark-form.styl +3 -1
  6. package/client/components/bookmark-form/render-ssh-tunnel.jsx +210 -88
  7. package/client/components/bookmark-form/ssh-form-ui.jsx +1 -1
  8. package/client/components/main/main.jsx +14 -0
  9. package/client/components/sftp/{confirm-modal.jsx → confirm-modal-store.jsx} +81 -50
  10. package/client/components/sftp/file-item.jsx +2 -0
  11. package/client/components/sftp/sftp-entry.jsx +27 -37
  12. package/client/components/sftp/transfer-conflict-store.jsx +291 -0
  13. package/client/components/sftp/transport-action-store.jsx +430 -0
  14. package/client/components/sftp/transports-action-store.jsx +102 -0
  15. package/client/components/sftp/transports-ui-store.jsx +30 -0
  16. package/client/components/sidebar/transfer-list-control.jsx +5 -14
  17. package/client/components/sidebar/transport-ui.jsx +2 -12
  18. package/client/components/tabs/tab.jsx +43 -2
  19. package/client/components/tabs/tabs.styl +1 -1
  20. package/client/components/terminal/index.jsx +1 -0
  21. package/client/components/terminal/terminal-interactive.jsx +15 -0
  22. package/client/components/terminal-info/disk.jsx +9 -0
  23. package/client/store/index.js +4 -0
  24. package/client/store/init-state.js +2 -3
  25. package/client/store/sync.js +5 -2
  26. package/client/store/tab.js +1 -1
  27. package/client/store/transfer-list.js +55 -2
  28. package/client/store/watch.js +0 -8
  29. package/package.json +1 -1
  30. package/client/components/sftp/transfer-conflict.jsx +0 -323
  31. package/client/components/sftp/transport-action.jsx +0 -412
  32. package/client/components/sftp/transport-entry.jsx +0 -108
  33. package/client/components/sftp/transport-types.js +0 -8
  34. package/client/components/sftp/transports-action.jsx +0 -111
  35. package/client/components/sftp/transports-ui.jsx +0 -93
@@ -14,8 +14,10 @@ import {
14
14
  typeMap, maxSftpHistory, paneMap,
15
15
  eventTypes,
16
16
  fileTypeMap,
17
- terminalSshConfigType, terminalSerialType,
18
- unexpectedPacketErrorDesc, sftpRetryInterval,
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 (keyPressed(e, 'delete') && !inputFocus) {
450
- e.stopPropagation()
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
- postMessage({
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
  }
@@ -0,0 +1,291 @@
1
+ /**
2
+ * pass transfer list from props
3
+ * when list changes, do transfer and other op
4
+ */
5
+
6
+ import { Component } from '../common/react-subx'
7
+ import { typeMap } from '../../common/constants'
8
+ import {
9
+ getLocalFileInfo,
10
+ getRemoteFileInfo,
11
+ getFolderFromFilePath,
12
+ getFileExt,
13
+ checkFolderSize
14
+ } from './file-read'
15
+ import { findIndex, find } from 'lodash-es'
16
+ import generate from '../../common/uid'
17
+ import resolve from '../../common/resolve'
18
+
19
+ export default class TransferConflictStore extends Component {
20
+ state = {
21
+ currentId: ''
22
+ }
23
+
24
+ componentDidMount () {
25
+ this.watchFile()
26
+ }
27
+
28
+ componentDidUpdate (prevProps) {
29
+ if (
30
+ prevProps._fileTransfers !== this.props._fileTransfers
31
+ ) {
32
+ this.watchFile()
33
+ }
34
+ }
35
+
36
+ localCheckExist = (path) => {
37
+ return getLocalFileInfo(path)
38
+ }
39
+
40
+ remoteCheckExist = (path, sessionId) => {
41
+ const sftp = window.sftps[sessionId]
42
+ return getRemoteFileInfo(sftp, path)
43
+ .then(r => r)
44
+ .catch(() => false)
45
+ }
46
+
47
+ checkExist = (type, path, sessionId) => {
48
+ return this[type + 'CheckExist'](path, sessionId)
49
+ }
50
+
51
+ rename = (tr, action, _renameId) => {
52
+ const isRemote = tr.typeTo === typeMap.remote
53
+ const { path, name } = getFolderFromFilePath(tr.toPath, isRemote)
54
+ const { base, ext } = getFileExt(name)
55
+ const renameId = _renameId || generate()
56
+ const newName = ext
57
+ ? `${base}(rename-${renameId}).${ext}`
58
+ : `${base}(rename-${renameId})`
59
+ const res = {
60
+ ...tr,
61
+ renameId,
62
+ newName,
63
+ oldName: base,
64
+ toPath: resolve(path, newName)
65
+ }
66
+ if (action) {
67
+ res.action = action
68
+ }
69
+ return res
70
+ }
71
+
72
+ updateTransferAction = (data) => {
73
+ const {
74
+ id,
75
+ action,
76
+ transfer
77
+ } = data
78
+ const {
79
+ fromFile
80
+ } = transfer
81
+ this.clear()
82
+ const { store } = this.props
83
+ let {
84
+ fileTransfers
85
+ } = store
86
+ const index = findIndex(fileTransfers, d => d.id === id)
87
+ if (index < 0) {
88
+ return store.setFileTransfers(fileTransfers)
89
+ }
90
+ fileTransfers[index].fromFile = fromFile
91
+ fileTransfers[index].action = action
92
+ if (action === 'skip') {
93
+ fileTransfers.splice(index, 1)
94
+ } else if (action === 'cancel') {
95
+ fileTransfers = fileTransfers.slice(0, index)
96
+ }
97
+ if (action.includes('All')) {
98
+ fileTransfers = fileTransfers.map((t, i) => {
99
+ if (i < index) {
100
+ return t
101
+ }
102
+ return {
103
+ ...t,
104
+ action: action.replace('All', '')
105
+ }
106
+ })
107
+ }
108
+ if (action.includes('rename')) {
109
+ fileTransfers[index] = this.rename(fileTransfers[index])
110
+ } else if (action === 'skipAll') {
111
+ fileTransfers.splice(index, 1)
112
+ }
113
+ store.setFileTransfers(fileTransfers)
114
+ }
115
+
116
+ tagTransferError = (id, errorMsg) => {
117
+ const { store } = this.props
118
+ const {
119
+ fileTransfers
120
+ } = store
121
+ const tr = find(fileTransfers, d => d.id === id)
122
+ if (!tr) {
123
+ return
124
+ }
125
+ window.store.addTransferHistory({
126
+ ...tr,
127
+ host: tr.host,
128
+ error: errorMsg,
129
+ finishTime: Date.now()
130
+ })
131
+ const index = findIndex(fileTransfers, d => d.id === id)
132
+ if (index >= 0) {
133
+ fileTransfers.splice(index, 1)
134
+ }
135
+ store.setFileTransfers(fileTransfers)
136
+ }
137
+
138
+ setConflict (tr) {
139
+ if (window.store.transferToConfirm.id) {
140
+ return
141
+ }
142
+ window.store.setState(
143
+ 'transferToConfirm', tr
144
+ )
145
+ }
146
+
147
+ onDecision = (event) => {
148
+ if (
149
+ event &&
150
+ event.data &&
151
+ event.data.id === this.currentId
152
+ ) {
153
+ this.currentId = ''
154
+ this.updateTransferAction(event.data)
155
+ this.onConfirm = false
156
+ window.removeEventListener('message', this.onDecision)
157
+ }
158
+ }
159
+
160
+ waitForSignal = () => {
161
+ window.addEventListener('message', this.onDecision)
162
+ }
163
+
164
+ setCanTransfer = (fromFile, tr) => {
165
+ this.clear()
166
+ const {
167
+ store
168
+ } = this.props
169
+ const {
170
+ fileTransfers
171
+ } = store
172
+ const index = findIndex(fileTransfers, t => {
173
+ return t.id === tr.id
174
+ })
175
+ if (index >= 0) {
176
+ const up = {
177
+ action: 'transfer',
178
+ fromFile
179
+ }
180
+ Object.assign(fileTransfers[index], up)
181
+ } else {
182
+ fileTransfers[0].r = Math.random()
183
+ }
184
+ store.setFileTransfers(fileTransfers)
185
+ }
186
+
187
+ clear = () => {
188
+ this.currentId = ''
189
+ }
190
+
191
+ watchFile = async () => {
192
+ const { store } = this.props
193
+ const {
194
+ fileTransfers
195
+ } = store
196
+ if (!fileTransfers.length && this.currentId) {
197
+ return this.clear()
198
+ }
199
+ const tr = fileTransfers
200
+ .filter(t => {
201
+ return (
202
+ !t.action ||
203
+ !t.fromFile ||
204
+ t.fromFile.isDirectory
205
+ )
206
+ })[0]
207
+ if (!tr) {
208
+ this.onConfirm = false
209
+ return this.clear()
210
+ }
211
+ if (this.currentId) {
212
+ // fileTransfers[0].r = Math.random()
213
+ return store.setFileTransfers(fileTransfers)
214
+ }
215
+ this.currentId = tr.id
216
+ const {
217
+ typeFrom,
218
+ typeTo,
219
+ fromPath,
220
+ toPath,
221
+ id,
222
+ action,
223
+ renameId,
224
+ parentId,
225
+ skipConfirm,
226
+ sessionId
227
+ } = tr
228
+ const fromFile = tr.fromFile
229
+ ? tr.fromFile
230
+ : await this.checkExist(typeFrom, fromPath, sessionId)
231
+ if (!fromFile) {
232
+ this.currentId = ''
233
+ return this.tagTransferError(id, 'file not exist')
234
+ }
235
+ let toFile = false
236
+ if (renameId || parentId) {
237
+ toFile = false
238
+ } else if (fromPath === toPath && typeFrom === typeTo) {
239
+ toFile = true
240
+ } else {
241
+ toFile = await this.checkExist(typeTo, toPath, sessionId)
242
+ }
243
+ if (fromFile.isDirectory) {
244
+ const props = {
245
+ sftp: window.sftps[sessionId]
246
+ }
247
+ const skip = await checkFolderSize(props, fromFile)
248
+ .then(d => d && typeFrom !== typeTo)
249
+ if (!skip) {
250
+ return this.tagTransferError(id, 'folder too big or too many files in folder')
251
+ }
252
+ tr.zip = true
253
+ tr.skipExpand = true
254
+ }
255
+ if (fromPath === toPath && typeFrom === typeTo) {
256
+ return this.updateTransferAction({
257
+ id,
258
+ action: 'rename',
259
+ transfer: {
260
+ ...tr,
261
+ operation: 'cp',
262
+ fromFile
263
+ }
264
+ })
265
+ } else if (toFile && !action && !skipConfirm) {
266
+ this.waitForSignal(id)
267
+ if (!this.onConfirm) {
268
+ this.onConfirm = true
269
+ return this.setConflict({
270
+ ...tr,
271
+ fromFile,
272
+ toFile
273
+ })
274
+ }
275
+ } else if (toFile && !tr.fromFile && action) {
276
+ return this.updateTransferAction({
277
+ id,
278
+ action,
279
+ transfer: {
280
+ ...tr,
281
+ fromFile
282
+ }
283
+ })
284
+ }
285
+ this.setCanTransfer(fromFile, tr)
286
+ }
287
+
288
+ render () {
289
+ return null
290
+ }
291
+ }