@electerm/electerm-react 1.38.60 → 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 (36) 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/quick-commands/quick-commands-box.jsx +5 -4
  10. package/client/components/sftp/{confirm-modal.jsx → confirm-modal-store.jsx} +81 -50
  11. package/client/components/sftp/file-item.jsx +2 -0
  12. package/client/components/sftp/sftp-entry.jsx +34 -40
  13. package/client/components/sftp/transfer-conflict-store.jsx +291 -0
  14. package/client/components/sftp/transport-action-store.jsx +430 -0
  15. package/client/components/sftp/transports-action-store.jsx +102 -0
  16. package/client/components/sftp/transports-ui-store.jsx +30 -0
  17. package/client/components/sidebar/transfer-list-control.jsx +5 -14
  18. package/client/components/sidebar/transport-ui.jsx +2 -12
  19. package/client/components/tabs/tab.jsx +43 -2
  20. package/client/components/tabs/tabs.styl +1 -1
  21. package/client/components/terminal/index.jsx +1 -0
  22. package/client/components/terminal/terminal-interactive.jsx +15 -0
  23. package/client/components/terminal-info/disk.jsx +9 -0
  24. package/client/store/index.js +4 -0
  25. package/client/store/init-state.js +2 -3
  26. package/client/store/sync.js +5 -2
  27. package/client/store/tab.js +1 -1
  28. package/client/store/transfer-list.js +55 -2
  29. package/client/store/watch.js +0 -8
  30. package/package.json +1 -1
  31. package/client/components/sftp/transfer-conflict.jsx +0 -323
  32. package/client/components/sftp/transport-action.jsx +0 -412
  33. package/client/components/sftp/transport-entry.jsx +0 -108
  34. package/client/components/sftp/transport-types.js +0 -8
  35. package/client/components/sftp/transports-action.jsx +0 -111
  36. package/client/components/sftp/transports-ui.jsx +0 -93
@@ -1,412 +0,0 @@
1
- import { useEffect, useRef } from 'react'
2
- import { useDelta, useConditionalEffect } from 'react-delta'
3
- import copy from 'json-deep-copy'
4
- import { findIndex, isFunction, noop } from 'lodash-es'
5
- import generate from '../../common/uid'
6
- import { typeMap, transferTypeMap } from '../../common/constants'
7
- import fs from '../../common/fs'
8
- import { transportTypes } from './transport-types'
9
- import format, { computeLeftTime, computePassedTime } from './transfer-speed-format'
10
- import { getFolderFromFilePath } from './file-read'
11
- import resolve from '../../common/resolve'
12
- import delay from '../../common/wait'
13
- import { zipCmd, unzipCmd, rmCmd, mvCmd, mkdirCmd } from './zip'
14
- import './transfer.styl'
15
-
16
- export default function transportAction (props) {
17
- const { transfer } = props
18
- const inst = useRef({})
19
- const unzipping = useRef(false)
20
- const initRef = useDelta(transfer.inited)
21
- const initRefExpand = useDelta(transfer.expaned)
22
- function update (up) {
23
- props.modifier((old) => {
24
- const transferList = copy(old.transferList)
25
- const index = findIndex(transferList, t => t.id === transfer.id)
26
- if (index < 0) {
27
- return {
28
- transferList
29
- }
30
- }
31
- window.store.editTransfer(
32
- transferList[index].id,
33
- up
34
- )
35
- Object.assign(transferList[index], up)
36
- return {
37
- transferList
38
- }
39
- })
40
- }
41
- function insert (insts) {
42
- props.modifier((old) => {
43
- const transferList = copy(old.transferList)
44
- const index = findIndex(transferList, t => t.id === transfer.id)
45
- transferList.splice(index, 1, ...insts)
46
- window.store.setTransfers(transferList, transfer.sessionId)
47
- return {
48
- transferList
49
- }
50
- })
51
- }
52
- function onEnd (update = {}) {
53
- if (inst.current.onCancel) {
54
- return
55
- }
56
- const {
57
- typeTo,
58
- next
59
- } = transfer
60
- const cb = props[typeTo + 'List']
61
- const finishTime = Date.now()
62
- if (!props.config.disableTransferHistory) {
63
- window.store.addTransferHistory(
64
- {
65
- ...transfer,
66
- ...update,
67
- finishTime,
68
- startTime: inst.current.startTime,
69
- size: transfer.fromFile.size,
70
- speed: format(transfer.fromFile.size, inst.current.startTime),
71
- host: props.tab.host
72
- }
73
- )
74
- }
75
- if (next) {
76
- insert([copy(next)])
77
- }
78
- cancel(cb)
79
- }
80
- function onData (transferred) {
81
- if (inst.current.onCancel) {
82
- return
83
- }
84
- const up = {}
85
- const total = transfer.fromFile.size
86
- let percent = total === 0
87
- ? 0
88
- : Math.floor(100 * transferred / total)
89
- percent = percent >= 100 ? 99 : percent
90
- up.percent = percent
91
- up.status = 'active'
92
- up.transferred = transferred
93
- up.startTime = inst.current.startTime
94
- up.speed = format(transferred, up.startTime)
95
- Object.assign(
96
- up,
97
- computeLeftTime(transferred, total, up.startTime)
98
- )
99
- up.passedTime = computePassedTime(up.startTime)
100
- update(up)
101
- }
102
- function cancel (callback) {
103
- if (inst.current.onCancel) {
104
- return
105
- }
106
- inst.current.onCancel = true
107
- const { id } = transfer
108
- inst.current.transport && inst.current.transport.destroy()
109
- props.modifier((old) => {
110
- const oldTrans = copy(old.transferList)
111
- const transferList = oldTrans.filter(t => {
112
- return t.id !== id
113
- })
114
- window.store.setTransfers(transferList, transfer.sessionId)
115
- return {
116
- transferList
117
- }
118
- }, isFunction(callback) ? callback : noop)
119
- }
120
-
121
- function pause () {
122
- inst.current.transport && inst.current.transport.pause()
123
- update({
124
- pausing: true
125
- })
126
- }
127
-
128
- function resume () {
129
- update({
130
- pausing: false
131
- })
132
- inst.current.transport && inst.current.transport.resume()
133
- }
134
-
135
- function handlePauseOrResume () {
136
- if (transfer.pausing) {
137
- resume()
138
- } else {
139
- pause()
140
- }
141
- }
142
-
143
- function onMessage (e) {
144
- const action = e?.data?.action
145
- const id = e?.data?.id
146
- const ids = e?.data?.ids
147
- if (id === transfer.id) {
148
- switch (action) {
149
- case transportTypes.cancelTransport:
150
- cancel()
151
- break
152
- case transportTypes.pauseOrResumeTransfer:
153
- handlePauseOrResume()
154
- break
155
- default:
156
- break
157
- }
158
- }
159
- if (
160
- (ids && ids.includes(transfer.id)) ||
161
- (ids && ids.length === 0)
162
- ) {
163
- if (
164
- action === transportTypes.pauseTransport
165
- ) {
166
- pause()
167
- } else if (action === transportTypes.resumeTransport) {
168
- resume()
169
- } else if (action === transportTypes.cancelTransport) {
170
- cancel()
171
- }
172
- }
173
- }
174
- function initEvent () {
175
- window.addEventListener('message', onMessage)
176
- }
177
- function onDestroy () {
178
- window.removeEventListener('message', onMessage)
179
- }
180
- function mvOrCp () {
181
- const {
182
- fromPath,
183
- toPath,
184
- typeFrom,
185
- operation // 'mv' or 'cp'
186
- } = transfer
187
- if (typeFrom === typeMap.local) {
188
- return fs[operation](fromPath, toPath)
189
- .then(onEnd)
190
- .catch(e => {
191
- onEnd()
192
- onError(e)
193
- })
194
- }
195
- return props.sftp[operation](fromPath, toPath)
196
- .then(onEnd)
197
- .catch(e => {
198
- onEnd()
199
- onError(e)
200
- })
201
- }
202
- async function zipTransfer () {
203
- const {
204
- fromPath,
205
- toPath,
206
- typeFrom
207
- } = transfer
208
- let p
209
- let isFromRemote
210
- if (typeFrom === typeMap.local) {
211
- isFromRemote = false
212
- p = await fs.zipFolder(fromPath)
213
- } else {
214
- isFromRemote = true
215
- p = await zipCmd(props.pid, props.sessionId, fromPath)
216
- }
217
- const { name } = getFolderFromFilePath(p, isFromRemote)
218
- const { path } = getFolderFromFilePath(toPath, !isFromRemote)
219
- const nTo = resolve(path, name)
220
- const newTrans1 = {
221
- ...copy(transfer),
222
- toPathReal: transfer.toPath,
223
- fromPathReal: transfer.fromPath,
224
- toPath: nTo,
225
- fromPath: p,
226
- originalId: transfer.id,
227
- id: generate()
228
- }
229
- delete newTrans1.fromFile
230
- delete newTrans1.inited
231
- delete newTrans1.zip
232
- const newTrans2 = copy(newTrans1)
233
- newTrans2.unzip = true
234
- newTrans2.id = generate()
235
- newTrans1.next = newTrans2
236
- insert([newTrans1])
237
- }
238
-
239
- function buildUnzipPath (transfer) {
240
- const {
241
- newName,
242
- toPath,
243
- typeTo,
244
- oldName
245
- } = transfer
246
- const isToRemote = typeTo === typeMap.remote
247
- const { path } = getFolderFromFilePath(toPath, isToRemote)
248
- const np = newName
249
- ? resolve(path, 'temp-' + newName)
250
- : path
251
- return {
252
- targetPath: path,
253
- path: np,
254
- name: oldName
255
- }
256
- }
257
-
258
- async function unzipFile () {
259
- if (unzipping.current) {
260
- return false
261
- }
262
- unzipping.current = true
263
- const {
264
- fromPath,
265
- toPath,
266
- typeTo,
267
- newName
268
- } = transfer
269
- const isToRemote = typeTo === typeMap.remote
270
- const {
271
- path,
272
- name,
273
- targetPath
274
- } = buildUnzipPath(transfer)
275
- if (isToRemote) {
276
- if (newName) {
277
- await mkdirCmd(props.pid, props.sessionId, path)
278
- await delay(1000)
279
- }
280
- await unzipCmd(props.pid, props.sessionId, toPath, path)
281
- if (newName) {
282
- const mvFrom = resolve(path, name)
283
- const mvTo = resolve(targetPath, newName)
284
- await mvCmd(props.pid, props.sessionId, mvFrom, mvTo)
285
- }
286
- } else {
287
- if (newName) {
288
- await fs.mkdir(path)
289
- }
290
- await fs.unzipFile(toPath, path)
291
- if (newName) {
292
- const mvFrom = resolve(path, name)
293
- const mvTo = resolve(targetPath, newName)
294
- await fs.mv(mvFrom, mvTo)
295
- }
296
- }
297
- await rmCmd(props.pid, props.sessionId, !isToRemote ? fromPath : toPath)
298
- await fs.rmrf(!isToRemote ? toPath : fromPath)
299
- if (newName) {
300
- if (isToRemote) {
301
- await rmCmd(props.pid, props.sessionId, path)
302
- } else {
303
- await fs.rmrf(path)
304
- }
305
- }
306
- onEnd()
307
- }
308
-
309
- async function doTransfer () {
310
- const {
311
- fromPath,
312
- toPath,
313
- typeFrom,
314
- fromFile: {
315
- mode: fromMode
316
- },
317
- toFile = {}
318
- } = transfer
319
- const transferType = typeFrom === typeMap.local ? transferTypeMap.upload : transferTypeMap.download
320
- const isDown = transferType === transferTypeMap.download
321
- const localPath = isDown
322
- ? toPath
323
- : fromPath
324
- const remotePath = isDown
325
- ? fromPath
326
- : toPath
327
- const mode = toFile.mode || fromMode
328
- inst.current.transport = await props.sftp[transferType]({
329
- remotePath,
330
- localPath,
331
- options: { mode },
332
- onData,
333
- onError,
334
- onEnd
335
- })
336
- }
337
- function isTransferAction (action) {
338
- return action.includes('rename') || action === 'transfer'
339
- }
340
- async function initTransfer () {
341
- if (inst.current.started) {
342
- return
343
- }
344
- const {
345
- typeFrom,
346
- typeTo,
347
- fromFile: {
348
- isDirectory
349
- },
350
- action,
351
- expanded,
352
- zip,
353
- unzip,
354
- inited
355
- } = transfer
356
- const t = Date.now()
357
- update({
358
- startTime: t
359
- })
360
- inst.current.startTime = t
361
- inst.current.started = true
362
- if (unzip && inited) {
363
- unzipFile()
364
- } else if (zip && inited) {
365
- zipTransfer()
366
- } else if (typeFrom === typeTo) {
367
- return mvOrCp()
368
- } else if (isDirectory && expanded && isTransferAction(action)) {
369
- return mkdir()
370
- .then(onEnd)
371
- .catch(onError)
372
- } else if (!isDirectory) {
373
- doTransfer()
374
- } else if (expanded && isDirectory && !isTransferAction(action)) {
375
- cancel()
376
- }
377
- }
378
- function onError (e) {
379
- const up = {
380
- status: 'exception',
381
- error: e.message
382
- }
383
- onEnd(up)
384
- window.store.onError(e)
385
- }
386
- async function mkdir () {
387
- const {
388
- typeTo,
389
- toPath
390
- } = transfer
391
- if (typeTo === typeMap.local) {
392
- return fs.mkdir(toPath)
393
- .catch(onError)
394
- }
395
- return props.sftp.mkdir(toPath)
396
- .catch(onError)
397
- }
398
- useEffect(() => {
399
- initEvent()
400
- if (props.transfer.inited) {
401
- initTransfer()
402
- }
403
- return onDestroy
404
- }, [])
405
- useConditionalEffect(() => {
406
- initTransfer()
407
- }, initRef && initRef.prev !== initRef.curr && initRef.curr === true)
408
- useConditionalEffect(() => {
409
- initTransfer()
410
- }, initRefExpand && initRefExpand.prev !== initRefExpand.curr && initRef.curr === true)
411
- return null
412
- }
@@ -1,108 +0,0 @@
1
- import { PureComponent } from 'react'
2
- import Confirms from './confirm-modal'
3
- import ConflictHandler from './transfer-conflict'
4
- import TransfersHandler from './transports-action'
5
- import deepCopy from 'json-deep-copy'
6
- import runIdle from '../../common/run-idle'
7
- import { commonActions } from '../../common/constants'
8
- import { pick } from 'lodash-es'
9
-
10
- export default class TransferEntry extends PureComponent {
11
- constructor (props) {
12
- super(props)
13
- this.state = {
14
- transferToConfirm: null,
15
- transferList: [],
16
- pauseAll: false
17
- }
18
- }
19
-
20
- componentDidMount () {
21
- window.addEventListener('message', this.onAdd)
22
- }
23
-
24
- componentWillUnmount () {
25
- window.removeEventListener('message', this.onAdd)
26
- }
27
-
28
- onAdd = e => {
29
- const {
30
- sessionId,
31
- list,
32
- action
33
- } = e?.data || {}
34
- if (
35
- action !== commonActions.addTransfer ||
36
- sessionId !== this.props.sessionId
37
- ) {
38
- return false
39
- }
40
- this.addTransferList(list)
41
- }
42
-
43
- modifier = (...args) => {
44
- runIdle(() => this.setState(...args))
45
- }
46
-
47
- addTransferList = list => {
48
- this.modifier((old) => {
49
- let transferList = deepCopy(old.transferList)
50
- transferList = [
51
- ...transferList,
52
- ...list
53
- ]
54
- window.store.setTransfers(transferList)
55
- return {
56
- transferList
57
- }
58
- })
59
- }
60
-
61
- render () {
62
- const prps1 = {
63
- transferToConfirm: this.state.transferToConfirm,
64
- modifier: this.modifier
65
- }
66
- const prps2 = {
67
- transferList: this.state.transferList,
68
- modifier: this.modifier,
69
- addTransferList: this.addTransferList,
70
- transferToConfirm: this.state.transferToConfirm,
71
- ...pick(this.props, [
72
- 'localList',
73
- 'remoteList',
74
- 'sftp',
75
- 'sessionId',
76
- 'host',
77
- 'tab'
78
- ])
79
- }
80
- const prps3 = {
81
- transferList: this.state.transferList,
82
- modifier: this.modifier,
83
- pauseAll: this.state.pauseAll,
84
- localList: this.props.localListDebounce,
85
- remoteList: this.props.remoteListDebounce,
86
- ...pick(this.props, [
87
- 'sftp',
88
- 'config',
89
- 'tab',
90
- 'sessionId',
91
- 'pid'
92
- ])
93
- }
94
- return (
95
- <div>
96
- <ConflictHandler
97
- {...prps2}
98
- />
99
- <TransfersHandler
100
- {...prps3}
101
- />
102
- <Confirms
103
- {...prps1}
104
- />
105
- </div>
106
- )
107
- }
108
- }
@@ -1,8 +0,0 @@
1
- export const transportTypes = {
2
- pauseTransport: 'pause-transport',
3
- resumeTransport: 'resume-transport',
4
- cancelTransport: 'cancel-transport',
5
- pauseOrResumeTransfer: 'pause-or-resume-transfer',
6
- pauseOrResumeAll: 'pause-or-resume-all',
7
- cancelAll: 'cancel-all'
8
- }
@@ -1,111 +0,0 @@
1
- /**
2
- * pass transfer list from props
3
- * when list changes, do transfer and other op
4
- */
5
-
6
- import { useDelta, useConditionalEffect } from 'react-delta'
7
- import copy from 'json-deep-copy'
8
- import Transports from './transports-ui'
9
- import { maxTransport } from '../../common/constants'
10
- import eq from 'fast-deep-equal'
11
- import { isUndefined } from 'lodash-es'
12
-
13
- export default (props) => {
14
- const { transferList, pauseAll, sessionId } = props
15
- const delta = useDelta(transferList)
16
- const pauseControl = useDelta(pauseAll)
17
- async function control () {
18
- props.modifier((old) => {
19
- let transferList = copy(old.transferList)
20
- transferList = transferList.map(t => {
21
- const {
22
- typeTo,
23
- typeFrom,
24
- fromFile,
25
- inited
26
- } = t
27
- const ready = !!fromFile
28
- if (typeTo === typeFrom && ready && !inited) {
29
- t.inited = true
30
- }
31
- return t
32
- })
33
- if (old.pauseAll) {
34
- window.store.setTransfers(transferList, sessionId)
35
- return {
36
- transferList
37
- }
38
- }
39
- let count = transferList.filter(t => {
40
- const {
41
- typeTo,
42
- typeFrom,
43
- inited
44
- } = t
45
- return typeTo !== typeFrom && inited
46
- }).length
47
- if (count >= maxTransport) {
48
- window.store.setTransfers(transferList, sessionId)
49
- return {
50
- transferList
51
- }
52
- }
53
- const len = transferList.length
54
- const ids = []
55
- for (let i = 0; i < len; i++) {
56
- const tr = transferList[i]
57
- const {
58
- typeTo,
59
- typeFrom,
60
- inited,
61
- fromFile,
62
- error,
63
- id,
64
- action,
65
- parentId,
66
- expanded
67
- } = tr
68
- if (!error) {
69
- ids.push(id)
70
- }
71
- const isTransfer = typeTo !== typeFrom
72
- const parentFolderNotFinished = parentId && ids.includes(parentId)
73
- const ready = (
74
- (action && fromFile && !fromFile.isDirectory) ||
75
- (action && fromFile && fromFile.isDirectory && expanded)
76
- )
77
- if (
78
- !ready ||
79
- inited ||
80
- !isTransfer ||
81
- parentFolderNotFinished
82
- ) {
83
- continue
84
- }
85
- // if (isTransfer && tr.fromFile.isDirectory) {
86
- // i = len
87
- // continue
88
- // }
89
- if (
90
- fromFile && count < maxTransport
91
- ) {
92
- count++
93
- tr.inited = true
94
- }
95
- }
96
- window.store.setTransfers(transferList, sessionId)
97
- return {
98
- transferList
99
- }
100
- })
101
- }
102
- useConditionalEffect(() => {
103
- control()
104
- }, pauseControl && pauseControl.prev && pauseControl.prev !== pauseControl.curr)
105
- useConditionalEffect(() => {
106
- control()
107
- }, delta && !isUndefined(delta.prev) && !eq(delta.prev, delta.curr))
108
- return (
109
- <Transports {...props} />
110
- )
111
- }