@electerm/electerm-react 1.60.18 → 1.60.32

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 (106) hide show
  1. package/client/common/clipboard.js +1 -14
  2. package/client/common/constants.js +0 -43
  3. package/client/common/data-compare.js +55 -0
  4. package/client/common/default-setting.js +2 -10
  5. package/client/common/resolve.js +18 -22
  6. package/client/common/sftp.js +0 -3
  7. package/client/components/ai/ai-chat.jsx +30 -6
  8. package/client/components/ai/ai-config.jsx +17 -6
  9. package/client/components/batch-op/batch-op.jsx +3 -24
  10. package/client/components/bookmark-form/bookmark-group-tree-format.js +7 -9
  11. package/client/components/bookmark-form/form-ssh-common.jsx +0 -2
  12. package/client/components/bookmark-form/ssh-form.jsx +8 -41
  13. package/client/components/bookmark-form/tree-delete.jsx +1 -13
  14. package/client/components/common/animate-text.jsx +3 -4
  15. package/client/components/common/drag-handle.jsx +59 -45
  16. package/client/components/common/drag-handle.styl +2 -1
  17. package/client/components/common/input-auto-focus.jsx +29 -63
  18. package/client/components/common/ref.js +24 -0
  19. package/client/components/footer/batch-input.jsx +1 -6
  20. package/client/components/footer/footer-entry.jsx +13 -16
  21. package/client/components/footer/footer.styl +0 -5
  22. package/client/components/icons/ai-icon.jsx +17 -0
  23. package/client/components/icons/ai-icon.styl +3 -0
  24. package/client/components/layout/layout-item.jsx +14 -0
  25. package/client/components/main/main.jsx +8 -19
  26. package/client/components/main/upgrade.jsx +13 -25
  27. package/client/components/profile/profile-form-elem.jsx +1 -2
  28. package/client/components/quick-commands/on-drop.js +1 -12
  29. package/client/components/quick-commands/quick-command-transport-mod.jsx +3 -13
  30. package/client/components/quick-commands/quick-commands-form-elem.jsx +1 -2
  31. package/client/components/rdp/rdp-session.jsx +4 -4
  32. package/client/components/session/session.jsx +9 -11
  33. package/client/components/setting-panel/on-tree-drop.js +4 -35
  34. package/client/components/setting-panel/setting-common.jsx +4 -1
  35. package/client/components/setting-panel/setting-modal.jsx +7 -5
  36. package/client/components/setting-panel/tab-settings.jsx +0 -1
  37. package/client/components/setting-sync/setting-sync.jsx +0 -1
  38. package/client/components/sftp/address-bookmark-item.jsx +1 -15
  39. package/client/components/sftp/confirm-modal-store.jsx +2 -2
  40. package/client/components/sftp/{file-mode-modal.jsx → file-info-modal.jsx} +137 -37
  41. package/client/components/sftp/file-item.jsx +156 -192
  42. package/client/components/sftp/file-table-header.jsx +98 -0
  43. package/client/components/sftp/list-table-ui.jsx +125 -416
  44. package/client/components/sftp/sftp-entry.jsx +102 -128
  45. package/client/components/sftp/sftp.styl +6 -22
  46. package/client/components/sftp/transfer-conflict-store.jsx +8 -12
  47. package/client/components/sftp/transport-action-store.jsx +7 -15
  48. package/client/components/shortcuts/shortcut-control.jsx +72 -3
  49. package/client/components/shortcuts/shortcut-handler.js +0 -1
  50. package/client/components/side-panel-r/side-panel-r.jsx +7 -4
  51. package/client/components/sidebar/bookmark-select.jsx +5 -3
  52. package/client/components/sidebar/history.jsx +3 -0
  53. package/client/components/sidebar/index.jsx +1 -1
  54. package/client/components/sidebar/info-modal.jsx +3 -0
  55. package/client/components/sidebar/side-panel.jsx +7 -4
  56. package/client/components/sidebar/sidebar-panel.jsx +1 -1
  57. package/client/components/sidebar/sidebar.styl +3 -3
  58. package/client/components/sys-menu/icons-map.jsx +52 -0
  59. package/client/components/{context-menu → sys-menu}/menu-btn.jsx +33 -45
  60. package/client/components/sys-menu/sys-menu.jsx +163 -0
  61. package/client/components/{context-menu/context-menu.styl → sys-menu/sys-menu.styl} +2 -11
  62. package/client/components/tabs/index.jsx +5 -97
  63. package/client/components/tabs/tab.jsx +121 -73
  64. package/client/components/tabs/tabs.styl +4 -1
  65. package/client/components/terminal/term-search.jsx +16 -28
  66. package/client/components/terminal/terminal-interactive.jsx +0 -2
  67. package/client/components/terminal/{index.jsx → terminal.jsx} +110 -240
  68. package/client/components/terminal-info/base.jsx +21 -46
  69. package/client/components/terminal-info/terminal-info.jsx +3 -0
  70. package/client/components/text-editor/text-editor.jsx +38 -53
  71. package/client/components/theme/theme-form.jsx +0 -2
  72. package/client/components/tree-list/bookmark-toolbar.jsx +23 -47
  73. package/client/components/tree-list/bookmark-transport.jsx +2 -90
  74. package/client/components/tree-list/move-item-modal.jsx +101 -0
  75. package/client/components/tree-list/tree-expander.jsx +2 -3
  76. package/client/components/tree-list/tree-list-item.jsx +8 -11
  77. package/client/components/tree-list/tree-list.jsx +75 -296
  78. package/client/components/vnc/vnc-session.jsx +5 -3
  79. package/client/store/app-upgrade.js +2 -5
  80. package/client/store/bookmark-group.js +116 -51
  81. package/client/store/common.js +36 -54
  82. package/client/store/event.js +4 -37
  83. package/client/store/init-state.js +9 -12
  84. package/client/store/item.js +34 -39
  85. package/client/store/load-data.js +5 -1
  86. package/client/store/quick-command.js +2 -12
  87. package/client/store/session.js +6 -7
  88. package/client/store/setting.js +3 -7
  89. package/client/store/sidebar.js +2 -8
  90. package/client/store/store.js +0 -20
  91. package/client/store/system-menu.js +1 -2
  92. package/client/store/tab.js +29 -1
  93. package/client/store/terminal-theme.js +0 -4
  94. package/client/store/watch.js +26 -4
  95. package/package.json +1 -1
  96. package/client/common/post-msg.js +0 -3
  97. package/client/components/common/native-input.jsx +0 -30
  98. package/client/components/context-menu/context-menu.jsx +0 -339
  99. package/client/components/sftp/file-props-modal.jsx +0 -210
  100. package/client/store/context-menu.js +0 -23
  101. /package/client/components/{context-menu → sys-menu}/boomarks.jsx +0 -0
  102. /package/client/components/{context-menu → sys-menu}/history.jsx +0 -0
  103. /package/client/components/{context-menu → sys-menu}/icon-holder.jsx +0 -0
  104. /package/client/components/{context-menu → sys-menu}/sub-tab-menu.jsx +0 -0
  105. /package/client/components/{context-menu → sys-menu}/tabs.jsx +0 -0
  106. /package/client/components/{context-menu → sys-menu}/zoom.jsx +0 -0
@@ -1,10 +1,13 @@
1
- import { useCallback, useRef, useState, memo } from 'react'
1
+ import {
2
+ Splitter
3
+ } from 'antd'
2
4
  import './drag-handle.styl'
3
5
 
4
- export default memo(function DragHandle (props) {
5
- const [isDragging, setIsDragging] = useState(false)
6
- const dragStartRef = useRef(false)
7
- const clientXRef = useRef(0)
6
+ const {
7
+ Panel
8
+ } = Splitter
9
+
10
+ export default function DragHandle (props) {
8
11
  const {
9
12
  max,
10
13
  min,
@@ -12,49 +15,60 @@ export default memo(function DragHandle (props) {
12
15
  left = true
13
16
  } = props
14
17
 
15
- const calc = useCallback((clientX) => {
16
- let nw = left
17
- ? clientX - clientXRef.current + width
18
- : clientXRef.current - clientX + width
19
- if (nw < min) {
20
- nw = min
21
- } else if (nw > max) {
22
- nw = max
23
- }
24
- return nw
25
- }, [props.max, props.min, props.left])
26
-
27
- const handleMousedown = useCallback((e) => {
28
- e.stopPropagation()
29
- setIsDragging(true)
30
- dragStartRef.current = true
31
- clientXRef.current = e.clientX
32
- window.addEventListener('mouseup', handleMouseup)
33
- window.addEventListener('mousemove', handleMousemove)
34
- }, [])
35
-
36
- const handleMouseup = useCallback((e) => {
37
- setIsDragging(false)
38
- dragStartRef.current = false
39
- const nw = calc(e.clientX)
40
- props.onDragEnd(nw)
41
- window.store.onResize()
42
- window.removeEventListener('mouseup', handleMouseup)
43
- window.removeEventListener('mousemove', handleMousemove)
44
- }, [])
45
-
46
- const handleMousemove = useCallback((e) => {
47
- const nw = calc(e.clientX)
48
- props.onDragMove(nw)
49
- }, [width])
50
18
  const divProps = {
51
- className: 'drag-handle' + (isDragging ? ' dragging' : ''),
52
- onMouseDown: handleMousedown,
53
- draggable: false
19
+ className: 'drag-handle'
20
+ }
21
+ const w = max * 2
22
+ function newSize (sizes) {
23
+ return left ? sizes[0] : sizes[1]
24
+ }
25
+ function onResizeEnd (sizes) {
26
+ props.onDragEnd(newSize(sizes))
27
+ }
28
+ function onResize (sizes) {
29
+ props.onDragEnd(newSize(sizes))
30
+ }
31
+
32
+ const l = left ? -width : -(w - width)
33
+ const r = left ? w - width : width
34
+ const splitProps = {
35
+ // lazy: true,
36
+ onResizeEnd,
37
+ onResize,
38
+ style: {
39
+ width: w + 'px',
40
+ position: 'absolute',
41
+ left: l + 'px',
42
+ right: r + 'px',
43
+ top: 0,
44
+ bottom: 0
45
+ }
46
+ }
47
+ const panelPropsL = {
48
+ min,
49
+ max,
50
+ size: width
51
+ }
52
+ const panelPropsR = {
53
+ min: max,
54
+ max: w - min,
55
+ size: w - width
54
56
  }
57
+ const panelPropsLeft = left
58
+ ? panelPropsL
59
+ : panelPropsR
55
60
  return (
56
61
  <div
57
62
  {...divProps}
58
- />
63
+ >
64
+ <Splitter
65
+ {...splitProps}
66
+ >
67
+ <Panel
68
+ {...panelPropsLeft}
69
+ />
70
+ <Panel />
71
+ </Splitter>
72
+ </div>
59
73
  )
60
- })
74
+ }
@@ -5,8 +5,9 @@
5
5
  top 0
6
6
  width 3px
7
7
  bottom 0
8
- cursor ew-resize
8
+ // cursor ew-resize
9
9
  display none
10
10
  z-index 201
11
+ overflow hidden
11
12
  &.dragging
12
13
  background #08c
@@ -1,69 +1,35 @@
1
- /**
2
- * input with auto focus
3
- */
4
-
5
- import { Input } from 'antd'
6
- import InputNative from './native-input'
7
- import React from 'react'
8
- import { findLastIndex } from 'lodash-es'
9
- import uid from '../../common/uid'
10
-
11
- export default class InputAutoFocus extends React.PureComponent {
12
- constructor (props) {
13
- super(props)
14
- this.uid = 'InputAutoFocus-' + uid()
15
- }
16
-
17
- componentDidMount () {
18
- this.timer = setTimeout(this.doFocus, 50)
19
- }
20
-
21
- componentDidUpdate (prevProps) {
22
- if (!prevProps.selectall) {
23
- return
24
- }
25
- if (prevProps.autofocustrigger !== this.props.autofocustrigger) {
26
- this.timer = setTimeout(this.doFocus, 50)
27
- }
28
- }
29
-
30
- componentWillUnmount () {
31
- clearTimeout(this.timer)
32
- }
33
-
34
- doFocus = () => {
35
- const dom = this.getDom()
36
- if (dom && dom.focus) {
37
- const { value, selectall = false } = this.props
38
- const index = findLastIndex(value, v => v === '.')
39
- const hasExt = index > 0
40
- if (value && !selectall && hasExt) {
41
- dom.focus()
42
- dom.setSelectionRange(0, index)
1
+ import { useEffect, useRef } from 'react'
2
+ import {
3
+ Input
4
+ } from 'antd'
5
+
6
+ export default function InputAutoFocus (props) {
7
+ const { type, selectall = false, ...rest } = props
8
+ const inputRef = useRef(null)
9
+
10
+ useEffect(() => {
11
+ if (inputRef.current) {
12
+ const { value } = props
13
+ if (value && selectall) {
14
+ inputRef.current.setSelectionRange(0, value.length)
43
15
  } else {
44
- dom.select()
16
+ inputRef.current.focus()
45
17
  }
46
18
  }
19
+ }, [props.value, props.selectall]) // Focus when these props change
20
+ let InputComponent
21
+ switch (type) {
22
+ case 'password':
23
+ InputComponent = Input.Password
24
+ break
25
+ default:
26
+ InputComponent = Input
47
27
  }
28
+ return (
29
+ <InputComponent
30
+ ref={inputRef}
31
+ {...rest}
32
+ />
48
33
 
49
- getDom () {
50
- const root = document.querySelector(`[data-id="${this.uid}"]`)
51
- const dom = root.tagName === 'INPUT'
52
- ? root
53
- : root.querySelector('input')
54
- return dom
55
- }
56
-
57
- render () {
58
- const { type, ...rest } = this.props
59
- const Dom = type === 'password'
60
- ? Input.Password
61
- : type === 'native' ? InputNative : Input
62
- return (
63
- <Dom
64
- {...rest}
65
- data-id={this.uid}
66
- />
67
- )
68
- }
34
+ )
69
35
  }
@@ -0,0 +1,24 @@
1
+ // components instance reference holder
2
+ window.refs = new Map()
3
+ window.refsStatic = new Map()
4
+
5
+ class Ref {
6
+ constructor (key) {
7
+ this.key = key
8
+ }
9
+
10
+ add (key, inst) {
11
+ window[this.key].set(key, inst)
12
+ }
13
+
14
+ get (key) {
15
+ return window[this.key].get(key)
16
+ }
17
+
18
+ remove (key) {
19
+ window[this.key].delete(key)
20
+ }
21
+ }
22
+
23
+ export const refs = new Ref('refs')
24
+ export const refsStatic = new Ref('refsStatic')
@@ -9,13 +9,11 @@ import {
9
9
  } from 'antd'
10
10
  import {
11
11
  batchInputLsKey,
12
- commonActions,
13
12
  terminalWebType,
14
13
  terminalRdpType,
15
14
  terminalVncType
16
15
  } from '../../common/constants'
17
16
  import TabSelect from './tab-select'
18
- import postMsg from '../../common/post-msg'
19
17
  import classNames from 'classnames'
20
18
  import deepCopy from 'json-deep-copy'
21
19
 
@@ -53,10 +51,7 @@ export default class BatchInput extends Component {
53
51
  handleChange = (v = '') => {
54
52
  let vv = v.replace(/^\d+:/, '').replace(/\n$/, '')
55
53
  if (vv === batchInputLsKey) {
56
- postMsg({
57
- action: commonActions.updateStore,
58
- func: 'clearBatchInput'
59
- })
54
+ window.store.clearBatchInput()
60
55
  vv = ''
61
56
  }
62
57
  this.setState({
@@ -4,11 +4,12 @@ import {
4
4
  } from 'antd'
5
5
  import { InfoCircleOutlined } from '@ant-design/icons'
6
6
  import './footer.styl'
7
- import { paneMap, terminalActions, statusMap } from '../../common/constants'
8
- import postMessage from '../../common/post-msg'
7
+ import { paneMap, statusMap } from '../../common/constants'
9
8
  import BatchInput from './batch-input'
10
9
  import encodes from '../bookmark-form/encodes'
10
+ import { refs } from '../common/ref'
11
11
  import Qm from '../quick-commands/quick-commands-select'
12
+ import AIIcon from '../icons/ai-icon'
12
13
 
13
14
  const {
14
15
  Option
@@ -22,19 +23,18 @@ export default auto(function FooterEntry (props) {
22
23
  }
23
24
 
24
25
  function batchInput (cmd, selectedTabIds) {
25
- postMessage({
26
- action: terminalActions.batchInput,
27
- selectedTabIds,
28
- cmd
26
+ selectedTabIds.map(id => {
27
+ return refs.get('term-' + id)
28
+ }).forEach(term => {
29
+ term?.batchInput(cmd)
29
30
  })
30
31
  }
31
32
 
32
33
  function handleSwitchEncoding (encode) {
33
- postMessage({
34
- encode,
35
- action: terminalActions.changeEncode,
36
- activeTabId: props.store.activeTabId
37
- })
34
+ const term = refs.get('term-' + props.store.activeTabId)
35
+ if (term) {
36
+ term.switchEncoding(encode)
37
+ }
38
38
  }
39
39
 
40
40
  function isLoading () {
@@ -77,12 +77,9 @@ export default auto(function FooterEntry (props) {
77
77
  function renderAIIcon () {
78
78
  return (
79
79
  <div className='terminal-footer-unit terminal-footer-ai'>
80
- <span
81
- className='ai-icon'
80
+ <AIIcon
82
81
  onClick={window.store.handleOpenAIPanel}
83
- >
84
- AI
85
- </span>
82
+ />
86
83
  </div>
87
84
  )
88
85
  }
@@ -14,11 +14,6 @@
14
14
  .qm-wrap-tooltip
15
15
  left 343px
16
16
 
17
- .ai-icon
18
- display inline-block
19
- padding 0 6px
20
- cursor pointer
21
-
22
17
  .terminal-footer-flex
23
18
  display flex
24
19
  .terminal-footer-unit .ant-select-selector .ant-select-selection-placeholder
@@ -0,0 +1,17 @@
1
+ import './ai-icon.styl'
2
+
3
+ export default function AIIcon (props) {
4
+ const {
5
+ className,
6
+ ...rest
7
+ } = props
8
+ const cls = 'ai-icon' + (props.className ? ' ' + props.className : '')
9
+ return (
10
+ <span
11
+ className={cls}
12
+ {...rest}
13
+ >
14
+ AI
15
+ </span>
16
+ )
17
+ }
@@ -0,0 +1,3 @@
1
+ .ai-icon
2
+ display inline-block
3
+ cursor pointer
@@ -34,7 +34,21 @@ export default function LayoutItem (props) {
34
34
  if (!t) {
35
35
  return
36
36
  }
37
+
38
+ // Handle source batch's activeTabId
39
+ const fromBatch = fromTab.batch
40
+ if (store[`activeTabId${fromBatch}`] === fromTab.id) {
41
+ // Find next tab in the source batch
42
+ const nextTab = tabs.find(tab =>
43
+ tab.id !== fromTab.id && tab.batch === fromBatch
44
+ )
45
+ store[`activeTabId${fromBatch}`] = nextTab ? nextTab.id : ''
46
+ }
47
+
48
+ // Update tab's batch
37
49
  t.batch = batch
50
+
51
+ store[`activeTabId${batch}`] = t.id
38
52
  clearCls()
39
53
  }
40
54
 
@@ -1,9 +1,7 @@
1
1
  import { auto } from 'manate/react'
2
2
  import { useEffect } from 'react'
3
3
  import Layout from '../layout/layout'
4
- import ContextMenu from '../context-menu/context-menu'
5
- import FileInfoModal from '../sftp/file-props-modal'
6
- import FileModeModal from '../sftp/file-mode-modal'
4
+ import FileInfoModal from '../sftp/file-info-modal'
7
5
  import UpdateCheck from './upgrade'
8
6
  import SettingModal from '../setting-panel/setting-modal'
9
7
  import TextEditor from '../text-editor/text-editor'
@@ -52,7 +50,6 @@ export default auto(function Index (props) {
52
50
  const { store } = props
53
51
  window.addEventListener('resize', store.onResize)
54
52
  setTimeout(store.triggerResize, 200)
55
- store.initStoreEvents()
56
53
  const { ipcOnEvent } = window.pre
57
54
  ipcOnEvent('checkupdate', store.onCheckUpdate)
58
55
  ipcOnEvent('open-about', store.openAbout)
@@ -183,13 +180,7 @@ export default auto(function Index (props) {
183
180
  resolutions: deepCopy(store.resolutions),
184
181
  openResolutionEdit
185
182
  }
186
- const contextMenuProps = {
187
- ...pick(store, [
188
- 'history'
189
- ]),
190
- tabs: store.getTabs(),
191
- config
192
- }
183
+
193
184
  const rightPanelProps = {
194
185
  rightPanelVisible: store.rightPanelVisible,
195
186
  rightPanelPinned: store.rightPanelPinned,
@@ -198,6 +189,7 @@ export default auto(function Index (props) {
198
189
  rightPanelTab
199
190
  }
200
191
  const terminalInfoProps = {
192
+ rightPanelTab,
201
193
  ...deepCopy(store.terminalInfoProps),
202
194
  ...pick(
203
195
  config,
@@ -224,11 +216,9 @@ export default auto(function Index (props) {
224
216
  selectedTabIds: store.batchInputSelectedTabIds,
225
217
  tabs: store.getTabs(),
226
218
  activeTabId: store.activeTabId,
227
- showAIConfig: store.showAIConfig
219
+ showAIConfig: store.showAIConfig,
220
+ rightPanelTab
228
221
  }
229
- const rightPanelContent = rightPanelTab === 'ai'
230
- ? <AIChat {...aiChatProps} />
231
- : <TerminalInfo {...terminalInfoProps} />
232
222
  return (
233
223
  <ConfigProvider
234
224
  theme={uiThemeConfig}
@@ -251,14 +241,13 @@ export default auto(function Index (props) {
251
241
  buildTheme={store.buildTheme}
252
242
  />
253
243
  <CustomCss customCss={config.customCss} />
254
- <TextEditor customCss={cpConf.customCss} />
244
+ <TextEditor />
255
245
  <UpdateCheck
256
246
  skipVersion={cpConf.skipVersion}
257
247
  upgradeInfo={upgradeInfo}
258
248
  installSrc={installSrc}
259
249
  />
260
250
  <FileInfoModal />
261
- <FileModeModal />
262
251
  <SettingModal store={store} />
263
252
  <BatchOp {...batchOpProps} />
264
253
  <div
@@ -270,7 +259,6 @@ export default auto(function Index (props) {
270
259
  store={store}
271
260
  />
272
261
  </div>
273
- <ContextMenu {...contextMenuProps} />
274
262
  <ConfirmModalStore
275
263
  transferToConfirm={transferToConfirm}
276
264
  />
@@ -285,7 +273,8 @@ export default auto(function Index (props) {
285
273
  <Resolutions {...resProps} />
286
274
  <InfoModal {...infoModalProps} />
287
275
  <RightSidePanel {...rightPanelProps}>
288
- {rightPanelContent}
276
+ <AIChat {...aiChatProps} />
277
+ <TerminalInfo {...terminalInfoProps} />
289
278
  </RightSidePanel>
290
279
  <SshConfigLoadNotify {...sshConfigProps} />
291
280
  <LoadSshConfigs
@@ -9,14 +9,15 @@ import {
9
9
  isMac,
10
10
  isWin,
11
11
  packInfo,
12
- commonActions,
13
12
  srcsSkipUpgradeCheck,
14
13
  downloadUpgradeTimeout,
15
14
  mirrors
16
15
  } from '../../common/constants'
16
+ import { debounce } from 'lodash-es'
17
17
  import newTerm from '../../common/new-terminal'
18
18
  import Markdown from '../common/markdown'
19
19
  import downloadMirrors from '../../common/download-mirrors'
20
+ import { refsStatic } from '../common/ref'
20
21
  import './upgrade.styl'
21
22
 
22
23
  const e = window.translate
@@ -36,30 +37,17 @@ export default class Upgrade extends PureComponent {
36
37
  setTimeout(() => {
37
38
  getLatestReleaseVersion(1)
38
39
  }, 5000)
39
- this.watch()
40
+ this.id = 'upgrade'
41
+ refsStatic.add(this.id, this)
40
42
  }
41
43
 
42
- componentWillUnmount () {
43
- this.unwatch()
44
- }
45
-
46
- watch = () => {
47
- window.addEventListener('message', this.onEvent)
48
- }
49
-
50
- unwatch = () => {
51
- window.removeEventListener('message', this.onEvent)
52
- }
53
-
54
- onEvent = (e) => {
55
- if (e && e.data && e.data.action === commonActions.appUpdateCheck) {
56
- this.setState(old => {
57
- return {
58
- showCount: old.showCount + 1
59
- }
60
- })
61
- this.getLatestRelease(e.data.noSkip)
62
- }
44
+ appUpdateCheck = (noSkip) => {
45
+ this.setState(old => {
46
+ return {
47
+ showCount: old.showCount + 1
48
+ }
49
+ })
50
+ this.getLatestRelease(noSkip)
63
51
  }
64
52
 
65
53
  changeProps = (update) => {
@@ -122,7 +110,7 @@ export default class Upgrade extends PureComponent {
122
110
  this.handleClose()
123
111
  }
124
112
 
125
- doUpgrade = async () => {
113
+ doUpgrade = debounce(async () => {
126
114
  const { installSrc } = this.props
127
115
  if (!isMac && !isWin && installSrc === 'npm') {
128
116
  return window.store.addTab(
@@ -144,7 +132,7 @@ export default class Upgrade extends PureComponent {
144
132
  onError: this.onError
145
133
  })
146
134
  this.downloadTimer = setTimeout(this.timeout, downloadUpgradeTimeout)
147
- }
135
+ }, 100)
148
136
 
149
137
  handleSkipVersion = () => {
150
138
  window.store.setConfig({
@@ -18,7 +18,7 @@ const e = window.translate
18
18
  export default function ProfileFormElem (props) {
19
19
  const [form] = Form.useForm()
20
20
  const [activeTab, setActiveTab] = useState('ssh')
21
- const { autofocustrigger, profiles } = props.store
21
+ const { profiles } = props.store
22
22
  function genId () {
23
23
  let count = profiles.length ? profiles.length : ''
24
24
  let id = 'PROFILE' + count
@@ -73,7 +73,6 @@ export default function ProfileFormElem (props) {
73
73
  >
74
74
  <InputAutoFocus
75
75
  selectall='yes'
76
- autofocustrigger={autofocustrigger}
77
76
  />
78
77
  </FormItem>
79
78
  <ProfileTabs {...tabsProps} />
@@ -1,19 +1,8 @@
1
1
  export default function onDrop (e, cls) {
2
2
  e.preventDefault()
3
3
  const { store } = window
4
- const { quickCommands } = store
5
4
  const idDragged = e.dataTransfer.getData('idDragged')
6
5
  const tar = cls ? e.target.closest(cls) : e.target
7
6
  const idDrop = tar.getAttribute('data-id')
8
- const idDraggedIndex = quickCommands.findIndex(
9
- ({ id }) => id === idDragged
10
- )
11
- const targetIndex = quickCommands.findIndex(
12
- ({ id }) => id === idDrop
13
- )
14
- if (idDraggedIndex !== targetIndex) {
15
- const [removed] = quickCommands.splice(idDraggedIndex, 1)
16
- quickCommands.splice(targetIndex, 0, removed)
17
- store.setItems('quickCommands', quickCommands)
18
- }
7
+ store.adjustOrder('quickCommands', idDragged, idDrop)
19
8
  }
@@ -10,29 +10,19 @@ export default class QmTransport extends BookmarkTransport {
10
10
  const txt = await window.fs.readFile(file.path)
11
11
  try {
12
12
  const arr = JSON.parse(txt)
13
- const arrOld = copy(store[this.name])
13
+ const state = store[this.name]
14
+ const arrOld = copy(state)
14
15
  const bmTreeOld = arrOld.reduce((p, v) => {
15
16
  return {
16
17
  ...p,
17
18
  [v.id]: v
18
19
  }
19
20
  }, {})
20
- const add = []
21
- const dbAdd = []
22
21
  arr.forEach(bg => {
23
22
  if (!bmTreeOld[bg.id]) {
24
- arrOld.push(bg)
25
- add.push(bg)
26
- dbAdd.push({
27
- db: this.name,
28
- obj: bg
29
- })
23
+ state.push(bg)
30
24
  }
31
25
  })
32
- store.setState(
33
- this.name, arrOld
34
- )
35
- store.batchDbAdd(dbAdd)
36
26
  } catch (e) {
37
27
  store.onError(e)
38
28
  }
@@ -25,7 +25,7 @@ const shortcutsDefaults = shortcutsDefaultsGen()
25
25
  export default function QuickCommandForm (props) {
26
26
  const [form] = Form.useForm()
27
27
  const { store, formData } = props
28
- const { autofocustrigger, quickCommandTags = [] } = store
28
+ const { quickCommandTags = [] } = store
29
29
  const [shortcut, setShortcut] = useState(formData.shortcut || '')
30
30
  const uid = formData.id || generate()
31
31
  const updateConfig = (name, value) => {
@@ -150,7 +150,6 @@ export default function QuickCommandForm (props) {
150
150
  >
151
151
  <InputAutoFocus
152
152
  selectall='yes'
153
- autofocustrigger={autofocustrigger}
154
153
  />
155
154
  </FormItem>
156
155
  {renderQm()}
@@ -1,4 +1,4 @@
1
- import { PureComponent } from 'react'
1
+ import { PureComponent, createRef } from 'react'
2
2
  import { createTerm } from '../terminal/terminal-apis'
3
3
  import deepCopy from 'json-deep-copy'
4
4
  import clone from '../../common/to-simple-obj'
@@ -27,6 +27,7 @@ export default class RdpSession extends PureComponent {
27
27
  const id = `rdp-reso-${props.tab.host}`
28
28
  const resObj = ls.getItemJSON(id, resolutions[0])
29
29
  super(props)
30
+ this.canvasRef = createRef()
30
31
  this.state = {
31
32
  loading: false,
32
33
  bitmapProps: {},
@@ -230,8 +231,7 @@ export default class RdpSession extends PureComponent {
230
231
  loading: false
231
232
  })
232
233
  }
233
- const id = 'canvas_' + this.props.tab.id
234
- const canvas = document.getElementById(id)
234
+ const canvas = this.canvasRef.current
235
235
  const ctx = canvas.getContext('2d')
236
236
  const {
237
237
  width,
@@ -418,7 +418,7 @@ export default class RdpSession extends PureComponent {
418
418
  {this.renderControl()}
419
419
  <canvas
420
420
  {...canvasProps}
421
- id={'canvas_' + this.props.tab.id}
421
+ ref={this.canvasRef}
422
422
  />
423
423
  </div>
424
424
  </Spin>