@electerm/electerm-react 1.51.3 → 1.51.18

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 (86) hide show
  1. package/client/common/constants.js +15 -1
  2. package/client/common/db.js +10 -9
  3. package/client/common/default-setting.js +0 -1
  4. package/client/common/is-color-dark.js +15 -11
  5. package/client/common/new-terminal.js +2 -5
  6. package/client/common/reverse-color.js +12 -0
  7. package/client/common/ws.js +4 -1
  8. package/client/components/batch-op/batch-op.jsx +16 -5
  9. package/client/components/bookmark-form/index.jsx +1 -1
  10. package/client/components/bookmark-form/render-connection-hopping.jsx +25 -2
  11. package/client/components/bookmark-form/ssh-form.jsx +4 -25
  12. package/client/components/bookmark-form/tree-delete.jsx +5 -10
  13. package/client/components/bookmark-form/use-submit.jsx +6 -15
  14. package/client/components/bookmark-form/use-ui.jsx +1 -2
  15. package/client/components/common/connection-hopping-warning-text.jsx +36 -0
  16. package/client/components/common/drag-handle.jsx +60 -0
  17. package/client/components/common/drag-handle.styl +12 -0
  18. package/client/components/context-menu/context-menu.styl +5 -5
  19. package/client/components/context-menu/history.jsx +2 -11
  20. package/client/components/context-menu/sub-tab-menu.jsx +1 -1
  21. package/client/components/footer/footer-entry.jsx +1 -6
  22. package/client/components/layout/layout-item.jsx +2 -2
  23. package/client/components/layout/layout.jsx +3 -2
  24. package/client/components/main/connection-hopping-warnning.jsx +45 -0
  25. package/client/components/main/error-wrapper.jsx +120 -5
  26. package/client/components/main/main.jsx +32 -8
  27. package/client/components/main/upgrade.jsx +4 -9
  28. package/client/components/main/wrapper.styl +2 -1
  29. package/client/components/profile/profile-form-ssh.jsx +1 -1
  30. package/client/components/rdp/resolution-edit.jsx +3 -5
  31. package/client/components/session/session.jsx +22 -3
  32. package/client/components/session/session.styl +3 -2
  33. package/client/components/setting-panel/list.styl +0 -1
  34. package/client/components/setting-panel/on-tree-drop.js +5 -5
  35. package/client/components/setting-panel/setting-common.jsx +28 -7
  36. package/client/components/setting-panel/setting-modal.jsx +0 -12
  37. package/client/components/setting-panel/setting-terminal.jsx +7 -4
  38. package/client/components/sftp/confirm-modal-store.jsx +3 -11
  39. package/client/components/sftp/file-mode-modal.jsx +2 -2
  40. package/client/components/sftp/sftp-entry.jsx +4 -7
  41. package/client/components/sftp/transfer-conflict-store.jsx +70 -69
  42. package/client/components/sftp/transport-action-store.jsx +42 -49
  43. package/client/components/sftp/transports-action-store.jsx +15 -15
  44. package/client/components/sftp/transports-ui-store.jsx +9 -5
  45. package/client/components/side-panel-r/side-panel-r.jsx +13 -40
  46. package/client/components/sidebar/bookmark-select.jsx +1 -4
  47. package/client/components/sidebar/bookmark.jsx +4 -63
  48. package/client/components/sidebar/history-item.jsx +34 -0
  49. package/client/components/sidebar/history.jsx +17 -52
  50. package/client/components/sidebar/index.jsx +5 -40
  51. package/client/components/sidebar/side-panel.jsx +27 -51
  52. package/client/components/sidebar/sidebar-panel.jsx +107 -0
  53. package/client/components/sidebar/sidebar.styl +14 -9
  54. package/client/components/sidebar/transfer-list-control.jsx +1 -0
  55. package/client/components/sidebar/transfer.styl +1 -1
  56. package/client/components/sidebar/transport-ui.jsx +179 -37
  57. package/client/components/ssh-config/load-ssh-configs.jsx +106 -0
  58. package/client/components/ssh-config/ssh-config-item.jsx +26 -0
  59. package/client/components/ssh-config/ssh-config-load-notify.jsx +60 -0
  60. package/client/components/tabs/index.jsx +4 -4
  61. package/client/components/tabs/tab.jsx +28 -20
  62. package/client/components/tabs/tabs.styl +6 -1
  63. package/client/components/terminal/index.jsx +4 -18
  64. package/client/components/tree-list/bookmark-toolbar.jsx +203 -0
  65. package/client/components/tree-list/bookmark-transport.jsx +2 -0
  66. package/client/components/tree-list/tree-list.jsx +33 -42
  67. package/client/entry/worker.js +5 -3
  68. package/client/store/bookmark-group.js +5 -18
  69. package/client/store/bookmark.js +43 -1
  70. package/client/store/common.js +13 -9
  71. package/client/store/db-upgrade.js +0 -2
  72. package/client/store/index.js +45 -53
  73. package/client/store/init-state.js +20 -23
  74. package/client/store/item.js +0 -19
  75. package/client/store/load-data.js +7 -10
  76. package/client/store/setting.js +10 -66
  77. package/client/store/sidebar.js +7 -8
  78. package/client/store/sync.js +7 -8
  79. package/client/store/tab.js +93 -14
  80. package/client/store/terminal-theme.js +1 -1
  81. package/client/store/transfer-history.js +3 -9
  82. package/client/store/transfer-list.js +67 -75
  83. package/client/store/ui-theme.js +0 -9
  84. package/client/store/watch.js +17 -9
  85. package/package.json +1 -1
  86. package/client/components/setting-panel/tab-history.jsx +0 -43
@@ -2,18 +2,25 @@
2
2
  * tabs related functions
3
3
  */
4
4
 
5
- import { debounce } from 'lodash-es'
5
+ import { debounce, isEqual } from 'lodash-es'
6
6
  import {
7
7
  splitConfig,
8
8
  statusMap,
9
- paneMap
9
+ paneMap,
10
+ maxHistory
10
11
  } from '../common/constants'
11
12
  import * as ls from '../common/safe-local-storage'
12
13
  import deepCopy from 'json-deep-copy'
13
14
  import generate from '../common/id-with-stamp'
14
- import newTerm from '../common/new-terminal.js'
15
+ import uid from '../common/uid'
16
+ import newTerm, { updateCount } from '../common/new-terminal.js'
17
+ import { action } from 'manate'
15
18
 
16
19
  export default Store => {
20
+ Store.prototype.nextTabCount = function () {
21
+ return updateCount()
22
+ }
23
+
17
24
  Store.prototype.getTabs = function () {
18
25
  return window.store.tabs
19
26
  }
@@ -33,7 +40,10 @@ export default Store => {
33
40
  store.fileTransfers.map(d => d.tabId)
34
41
  )
35
42
  store.tabs.forEach(tab => {
36
- tab.isTransporting = tabIdSet.has(tab.id)
43
+ const t = tabIdSet.has(tab.id)
44
+ if (Boolean(tab.isTransporting) !== t) {
45
+ tab.isTransporting = t
46
+ }
37
47
  })
38
48
  }
39
49
 
@@ -82,30 +92,34 @@ export default Store => {
82
92
  }
83
93
 
84
94
  const oldTab = tabs[index]
95
+ const oldBatch = oldTab.batch
85
96
 
86
97
  // Create copy of old tab with new ID
87
98
  const newTab = {
88
99
  ...oldTab,
100
+ tabCount: store.nextTabCount(),
89
101
  id: generate(), // Need to create new ID
90
102
  status: statusMap.processing // Reset status
91
103
  }
92
104
 
93
105
  // Add new tab at next index
94
106
  tabs.splice(index + 1, 0, newTab)
107
+ store.updateHistory(newTab)
95
108
 
96
109
  // Remove old tab
97
110
  tabs.splice(index, 1)
98
111
 
99
- // Update current tab ID if needed
100
- if (store.activeTabId === tabId) {
101
- store.activeTabId = newTab.id
102
- }
112
+ setTimeout(() => {
113
+ if (store.activeTabId === tabId) {
114
+ store.activeTabId = newTab.id
115
+ }
103
116
 
104
- // Update batch current tab ID if needed
105
- const batchProp = `activeTabId${oldTab.batch}`
106
- if (store[batchProp] === tabId) {
107
- store[batchProp] = newTab.id
108
- }
117
+ // Update batch current tab ID if needed
118
+ const batchProp = `activeTabId${oldBatch}`
119
+ if (store[batchProp] === tabId) {
120
+ store[batchProp] = newTab.id
121
+ }
122
+ }, 0)
109
123
  }
110
124
 
111
125
  Store.prototype.duplicateTab = function (tabId) {
@@ -122,12 +136,14 @@ export default Store => {
122
136
  const duplicatedTab = {
123
137
  ...deepCopy(sourceTab),
124
138
  id: generate(),
139
+ tabCount: store.nextTabCount(),
125
140
  status: statusMap.processing,
126
141
  isTransporting: undefined
127
142
  }
128
143
 
129
144
  // Insert the duplicated tab after the source tab
130
145
  tabs.splice(targetIndex + 1, 0, duplicatedTab)
146
+ store.updateHistory(duplicatedTab)
131
147
 
132
148
  // Set the duplicated tab as current
133
149
  store.activeTabId = duplicatedTab.id
@@ -297,6 +313,7 @@ export default Store => {
297
313
  ) {
298
314
  const { store } = window
299
315
  const { tabs } = store
316
+ newTab.tabCount = store.nextTabCount()
300
317
  newTab.batch = batch ?? newTab.batch ?? window.openTabBatch ?? window.store.currentLayoutBatch
301
318
  if (typeof index === 'number' && index >= 0 && index <= tabs.length) {
302
319
  tabs.splice(index, 0, newTab)
@@ -307,6 +324,7 @@ export default Store => {
307
324
  store[`activeTabId${batchNum}`] = newTab.id
308
325
  store.activeTabId = newTab.id
309
326
  store.currentLayoutBatch = batchNum
327
+ store.updateHistory(newTab)
310
328
  }
311
329
 
312
330
  Store.prototype.clickNextTab = debounce(function () {
@@ -380,7 +398,7 @@ export default Store => {
380
398
 
381
399
  // If layout hasn't changed, do nothing
382
400
  if (prevLayout === layout) {
383
- return
401
+ return store.focus()
384
402
  }
385
403
 
386
404
  // Update layout related properties
@@ -413,4 +431,65 @@ export default Store => {
413
431
  }
414
432
  store.focus()
415
433
  }
434
+
435
+ Store.prototype.changeActiveTabId = function (id) {
436
+ const { store } = window
437
+ const { tabs } = store
438
+ const tab = tabs.find(t => t.id === id)
439
+ if (!tab) {
440
+ return
441
+ }
442
+ store.activeTabId = id
443
+ store[`activeTabId${tab.batch}`] = id
444
+ store.focus()
445
+ }
446
+
447
+ Store.prototype.updateHistory = function (tab) {
448
+ if (!tab.type && !tab.host) {
449
+ return
450
+ }
451
+ const { store } = window
452
+ const tabPropertiesExcludes = [
453
+ 'id',
454
+ 'from',
455
+ 'srcId',
456
+ 'status',
457
+ 'pane',
458
+ 'batch'
459
+ ]
460
+ const { history } = store
461
+ const index = history.findIndex(d => {
462
+ for (const key in tab) {
463
+ if (tabPropertiesExcludes.includes(key)) {
464
+ continue
465
+ }
466
+ if (!isEqual(d.tab[key], tab[key])) {
467
+ return false
468
+ }
469
+ }
470
+ return true
471
+ })
472
+ if (index === -1) {
473
+ const copiedTab = deepCopy(tab)
474
+ tabPropertiesExcludes.forEach(d => {
475
+ delete copiedTab[d]
476
+ })
477
+ return history.unshift({
478
+ tab: copiedTab,
479
+ time: Date.now(),
480
+ count: 1,
481
+ id: uid()
482
+ })
483
+ }
484
+ const match = history[index]
485
+ match.count = (match.count || 0) + 1
486
+ match.time = Date.now()
487
+ action(function () {
488
+ const [m] = history.splice(index, 1)
489
+ history.unshift(m)
490
+ if (history.length > maxHistory) {
491
+ history.pop()
492
+ }
493
+ })()
494
+ }
416
495
  }
@@ -65,7 +65,7 @@ export default Store => {
65
65
  }
66
66
 
67
67
  Store.prototype.setItermThemes = function (arr) {
68
- window.store._itermThemes = JSON.stringify(arr)
68
+ window.store.itermThemes = arr
69
69
  }
70
70
 
71
71
  Store.prototype.fetchItermThemes = async function () {
@@ -4,20 +4,14 @@
4
4
 
5
5
  export default Store => {
6
6
  Store.prototype.clearTransferHistory = function () {
7
- window.store.setItems('transferHistory', [])
7
+ window.store.transferHistory = []
8
8
  }
9
9
 
10
10
  Store.prototype.getTransferHistory = function () {
11
- return window.store.getItems('transferHistory')
11
+ return window.store.transferHistory
12
12
  }
13
13
 
14
14
  Store.prototype.addTransferHistory = function (item) {
15
- const { store } = window
16
- const transferHistory = store.getItems('transferHistory')
17
- transferHistory.unshift(item)
18
- store.setItems(
19
- 'transferHistory',
20
- transferHistory
21
- )
15
+ window.store.transferHistory.unshift(item)
22
16
  }
23
17
  }
@@ -1,103 +1,95 @@
1
- import { findIndex } from 'lodash-es'
1
+ /**
2
+ * file transfer list related functions
3
+ */
4
+ const { assign } = Object
5
+
2
6
  export default Store => {
3
7
  Store.prototype.handleTransferTab = function (tab) {
4
8
  window.store.transferTab = tab
5
9
  }
6
10
 
7
- Store.prototype.setTransfers = function (list, _sessId) {
8
- const { store } = window
9
- let oldList = store.fileTransfers
10
- const sessId = _sessId || list[0].sessionId
11
- const arr2 = oldList.filter(t => {
12
- return t.sessionId === sessId
13
- })
14
- const idsToRm = arr2.reduce((prev, curr) => {
15
- if (!list.find(l => l.id === curr.id)) {
16
- prev.push(curr.id)
17
- }
18
- return prev
19
- }, [])
20
- if (idsToRm.length) {
21
- oldList = oldList.filter(t => {
22
- return !idsToRm.includes(t.id)
23
- })
24
- }
25
- for (const ntm of list) {
26
- const index = findIndex(oldList, t => {
27
- return t.id === ntm.id
28
- })
29
- if (index >= 0) {
30
- oldList[index] = ntm
31
- continue
32
- } else {
33
- oldList.unshift(ntm)
34
- }
11
+ Store.prototype.updateTransfer = function (id, update) {
12
+ const { fileTransfers } = window.store
13
+ const index = fileTransfers.findIndex(t => t.id === id)
14
+ if (index < 0) {
15
+ return
35
16
  }
36
- store.setItems('fileTransfers', oldList)
37
- }
38
- Store.prototype.getTransfers = function () {
39
- return window.store.getItems('fileTransfers')
40
- }
41
- Store.prototype.delTransfers = function (ids) {
42
- return window.store.delItems(ids, 'fileTransfers')
43
- }
44
- Store.prototype.editTransfer = function (id, updates) {
45
- return window.store.editItem(id, updates, 'fileTransfers')
46
- }
47
- Store.prototype.addTransfers = function (objs) {
48
- return window.store.addItems(objs, 'fileTransfers')
17
+ assign(fileTransfers[index], update)
49
18
  }
50
- Store.prototype.setFileTransfers = function (objs) {
51
- return window.store.setState('fileTransfers', objs.filter(d => !d.cancel))
52
- }
53
- Store.prototype.addTransferList = function (objs) {
54
- const { store } = window
55
- store.setFileTransfers([
56
- ...store.fileTransfers,
57
- ...objs
58
- ])
19
+
20
+ Store.prototype.addTransferList = function (items) {
21
+ const { fileTransfers } = window.store
22
+ fileTransfers.push(...items)
59
23
  }
24
+
60
25
  Store.prototype.toggleTransfer = function (itemId) {
61
- const { store } = window
62
- const { fileTransfers } = store
63
- const index = findIndex(fileTransfers, t => t.id === itemId)
26
+ const { fileTransfers } = window.store
27
+ const index = fileTransfers.findIndex(t => t.id === itemId)
64
28
  if (index < 0) {
65
29
  return
66
30
  }
67
31
  fileTransfers[index].pausing = !fileTransfers[index].pausing
68
- store.setFileTransfers(fileTransfers)
69
32
  }
70
33
 
71
34
  Store.prototype.pauseAll = function () {
72
- const { store } = window
73
- store.pauseAllTransfer = true
74
- store.setFileTransfers(store.fileTransfers.map(t => {
75
- t.pausing = true
76
- return t
77
- }))
35
+ const { fileTransfers } = window.store
36
+ window.store.pauseAllTransfer = true
37
+ const len = fileTransfers.length
38
+ for (let i = 0; i < len; i++) {
39
+ fileTransfers[i].pausing = true
40
+ }
78
41
  }
42
+
79
43
  Store.prototype.resumeAll = function () {
80
- const { store } = window
81
- store.pauseAllTransfer = false
82
- store.setFileTransfers(store.fileTransfers.map(t => {
83
- t.pausing = false
84
- return t
85
- }))
44
+ const { fileTransfers } = window.store
45
+ window.store.pauseAllTransfer = false
46
+ const len = fileTransfers.length
47
+ for (let i = 0; i < len; i++) {
48
+ fileTransfers[i].pausing = false
49
+ }
86
50
  }
51
+
87
52
  Store.prototype.cancelAll = function () {
88
- const arr = document.querySelectorAll('.sftp-transport .transfer-control-cancel')
89
- arr.forEach(d => {
90
- d.click()
91
- })
53
+ const { fileTransfers } = window.store
54
+ const len = fileTransfers.length
55
+ for (let i = len - 1; i >= 0; i--) {
56
+ fileTransfers[i].cancel = true
57
+ fileTransfers.splice(i, 1)
58
+ }
92
59
  }
60
+
93
61
  Store.prototype.cancelTransfer = function (itemId) {
94
- const { store } = window
95
- const { fileTransfers } = store
96
- const index = findIndex(fileTransfers, t => t.id === itemId)
62
+ const { fileTransfers } = window.store
63
+ const index = fileTransfers.findIndex(t => t.id === itemId)
97
64
  if (index < 0) {
98
65
  return
99
66
  }
100
67
  fileTransfers[index].cancel = true
101
- store.setFileTransfers(fileTransfers)
68
+ fileTransfers.splice(index, 1)
69
+ }
70
+
71
+ Store.prototype.skipAllTransfersSinceIndex = function (index) {
72
+ window.store.fileTransfers.splice(index)
73
+ }
74
+
75
+ Store.prototype.updateTransfersFromIndex = function (index, update) {
76
+ const { fileTransfers } = window.store
77
+ if (index < 0 || index >= fileTransfers.length) {
78
+ return
79
+ }
80
+ const len = fileTransfers.length
81
+ for (let i = index; i < len; i++) {
82
+ assign(fileTransfers[i], update)
83
+ }
84
+ }
85
+
86
+ // Add a new method to find index by ID and then update
87
+ Store.prototype.updateTransfersFromId = function (id, update) {
88
+ const { fileTransfers } = window.store
89
+ const index = fileTransfers.findIndex(t => t.id === id)
90
+ if (index < 0) {
91
+ return
92
+ }
93
+ window.store.updateTransfersFromIndex(index, update)
102
94
  }
103
95
  }
@@ -15,15 +15,6 @@ import {
15
15
  import copy from 'json-deep-copy'
16
16
 
17
17
  export default Store => {
18
- // Store.prototype.toCss = async function (stylus) {
19
- // const { host, port } = window._config
20
- // const url = `http://${host}:${port}/to-css`
21
- // const data = await fetch.post(url, {
22
- // stylus
23
- // })
24
- // return data
25
- // }
26
-
27
18
  Store.prototype.getDefaultUiThemeConfig = function (stylus) {
28
19
  const reg = /[^\n]+ = [^\n]+\n/g
29
20
  const arr = stylus.match(reg)
@@ -43,12 +43,12 @@ export default store => {
43
43
  await store.uploadSettingAll()
44
44
  }
45
45
  return store['_' + name]
46
- }, func => debounce(func, 100)).start()
46
+ }).start()
47
47
  }
48
48
 
49
49
  autoRun(async () => {
50
- ls.setItem(resolutionsLsKey, store._resolutions)
51
- return store._resolutions
50
+ ls.setItemJSON(resolutionsLsKey, store.resolutions)
51
+ return store.resolutions
52
52
  }).start()
53
53
 
54
54
  autoRun(() => {
@@ -64,7 +64,7 @@ export default store => {
64
64
  if (!isEmpty(store.config)) {
65
65
  window.pre.runGlobalAsync('saveUserConfig', store.config)
66
66
  }
67
- return store._config
67
+ return store.config
68
68
  }, func => debounce(func, 100)).start()
69
69
 
70
70
  autoRun(() => {
@@ -74,17 +74,17 @@ export default store => {
74
74
 
75
75
  autoRun(() => {
76
76
  store.updateTabsStatus()
77
- return store.fileTransfers
78
- }, func => debounce(func, 100)).start()
77
+ return store.transferCount
78
+ }).start()
79
79
 
80
80
  autoRun(() => {
81
81
  ls.setItemJSON(sftpDefaultSortSettingKey, store.sftpSortSetting)
82
- return store._sftpSortSetting
82
+ return store.sftpSortSetting
83
83
  }).start()
84
84
 
85
85
  autoRun(() => {
86
86
  ls.setItemJSON(expandedKeysLsKey, store.expandedKeys)
87
- return store._expandedKeys
87
+ return store.expandedKeys
88
88
  }).start()
89
89
 
90
90
  autoRun(() => {
@@ -94,7 +94,12 @@ export default store => {
94
94
 
95
95
  autoRun(() => {
96
96
  ls.setItemJSON(checkedKeysLsKey, store.checkedKeys)
97
- return store._checkedKeys
97
+ return store.checkedKeys
98
+ }).start()
99
+
100
+ autoRun(() => {
101
+ ls.setItemJSON('history', store.history)
102
+ return store.history
98
103
  }).start()
99
104
 
100
105
  autoRun(() => {
@@ -106,6 +111,9 @@ export default store => {
106
111
  window.pre.runGlobalAsync('setTitle', title)
107
112
  window.store.currentLayoutBatch = tab.batch
108
113
  }
114
+ if (tab && store.rightPanelVisible) {
115
+ window.store.openInfoPanel()
116
+ }
109
117
  return store.activeTabId
110
118
  }).start()
111
119
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "1.51.3",
3
+ "version": "1.51.18",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",
@@ -1,43 +0,0 @@
1
- import SettingCol from './col'
2
- import BookmarkForm from '../bookmark-form'
3
- import List from './list'
4
- import {
5
- settingMap
6
- } from '../../common/constants'
7
-
8
- const e = window.translate
9
-
10
- export default function TabHistory (props) {
11
- const {
12
- settingTab
13
- } = props
14
- if (settingTab !== settingMap.history) {
15
- return null
16
- }
17
- const {
18
- settingItem,
19
- listProps,
20
- formProps
21
- } = props
22
- return (
23
- <div
24
- className='setting-tabs-history'
25
- >
26
- <SettingCol>
27
- <List
28
- {...listProps}
29
- />
30
- {
31
- settingItem.id
32
- ? (
33
- <BookmarkForm
34
- key={settingItem.id}
35
- {...formProps}
36
- />
37
- )
38
- : <div className='form-wrap pd2 aligncenter'>{e('notFoundContent')}</div>
39
- }
40
- </SettingCol>
41
- </div>
42
- )
43
- }