@electerm/electerm-react 1.60.16 → 1.60.29

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 (104) 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 +6 -15
  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/history.jsx +3 -0
  52. package/client/components/sidebar/index.jsx +1 -1
  53. package/client/components/sidebar/info-modal.jsx +3 -0
  54. package/client/components/sidebar/side-panel.jsx +7 -4
  55. package/client/components/sidebar/sidebar-panel.jsx +1 -1
  56. package/client/components/sidebar/sidebar.styl +3 -3
  57. package/client/components/sys-menu/icons-map.jsx +52 -0
  58. package/client/components/{context-menu → sys-menu}/menu-btn.jsx +33 -45
  59. package/client/components/sys-menu/sys-menu.jsx +163 -0
  60. package/client/components/{context-menu/context-menu.styl → sys-menu/sys-menu.styl} +2 -11
  61. package/client/components/tabs/index.jsx +5 -97
  62. package/client/components/tabs/tab.jsx +121 -73
  63. package/client/components/tabs/tabs.styl +4 -1
  64. package/client/components/terminal/term-search.jsx +16 -28
  65. package/client/components/terminal/terminal-interactive.jsx +0 -2
  66. package/client/components/terminal/{index.jsx → terminal.jsx} +126 -248
  67. package/client/components/terminal-info/base.jsx +21 -46
  68. package/client/components/terminal-info/terminal-info.jsx +3 -0
  69. package/client/components/text-editor/text-editor.jsx +38 -53
  70. package/client/components/theme/theme-form.jsx +0 -2
  71. package/client/components/tree-list/bookmark-toolbar.jsx +23 -47
  72. package/client/components/tree-list/bookmark-transport.jsx +2 -90
  73. package/client/components/tree-list/move-item-modal.jsx +101 -0
  74. package/client/components/tree-list/tree-list-item.jsx +6 -8
  75. package/client/components/tree-list/tree-list.jsx +48 -273
  76. package/client/components/vnc/vnc-session.jsx +5 -3
  77. package/client/store/app-upgrade.js +2 -5
  78. package/client/store/bookmark-group.js +74 -28
  79. package/client/store/common.js +36 -54
  80. package/client/store/event.js +4 -37
  81. package/client/store/init-state.js +9 -12
  82. package/client/store/item.js +34 -39
  83. package/client/store/load-data.js +5 -1
  84. package/client/store/quick-command.js +2 -12
  85. package/client/store/session.js +6 -7
  86. package/client/store/setting.js +3 -7
  87. package/client/store/sidebar.js +2 -8
  88. package/client/store/store.js +0 -20
  89. package/client/store/system-menu.js +1 -2
  90. package/client/store/tab.js +29 -1
  91. package/client/store/terminal-theme.js +0 -4
  92. package/client/store/watch.js +26 -4
  93. package/package.json +1 -1
  94. package/client/common/post-msg.js +0 -3
  95. package/client/components/common/native-input.jsx +0 -30
  96. package/client/components/context-menu/context-menu.jsx +0 -339
  97. package/client/components/sftp/file-props-modal.jsx +0 -210
  98. package/client/store/context-menu.js +0 -23
  99. /package/client/components/{context-menu → sys-menu}/boomarks.jsx +0 -0
  100. /package/client/components/{context-menu → sys-menu}/history.jsx +0 -0
  101. /package/client/components/{context-menu → sys-menu}/icon-holder.jsx +0 -0
  102. /package/client/components/{context-menu → sys-menu}/sub-tab-menu.jsx +0 -0
  103. /package/client/components/{context-menu → sys-menu}/tabs.jsx +0 -0
  104. /package/client/components/{context-menu → sys-menu}/zoom.jsx +0 -0
@@ -8,21 +8,13 @@ import {
8
8
  CloseOutlined,
9
9
  LoadingOutlined
10
10
  } from '@ant-design/icons'
11
- import {
12
- readClipboard,
13
- cut,
14
- hasBookmarkOrGroupInClipboardText
15
- } from '../../common/clipboard'
16
11
  import createName from '../../common/create-title'
17
12
  import InputAutoFocus from '../common/input-auto-focus'
18
- import { find, uniq, isEqual, filter, pick } from 'lodash-es'
13
+ import { find, uniq, filter, pick } from 'lodash-es'
19
14
  import {
20
15
  maxBookmarkGroupTitleLength,
21
16
  defaultBookmarkGroupId,
22
- settingMap,
23
- commonActions,
24
- copyBookmarkItemPrefix,
25
- copyBookmarkGroupItemPrefix
17
+ settingMap
26
18
  } from '../../common/constants'
27
19
  import findParentBySel from '../../common/find-parent'
28
20
  import copy, { deepCopy } from 'json-deep-copy'
@@ -35,8 +27,7 @@ import './tree-list.styl'
35
27
  import TreeExpander from './tree-expander'
36
28
  import TreeListItem from './tree-list-item'
37
29
  import TreeSearch from './tree-search'
38
-
39
- const e = window.translate
30
+ import MoveItemModal from './move-item-modal'
40
31
 
41
32
  export default class ItemListTree extends Component {
42
33
  constructor (props) {
@@ -46,6 +37,9 @@ export default class ItemListTree extends Component {
46
37
  keyword: '',
47
38
  parentId: '',
48
39
  showNewBookmarkGroupForm: false,
40
+ openMoveModal: false,
41
+ moveItem: null,
42
+ moveItemIsGroup: false,
49
43
  bookmarkGroupTitle: '',
50
44
  categoryTitle: '',
51
45
  categoryId: '',
@@ -53,6 +47,10 @@ export default class ItemListTree extends Component {
53
47
  }
54
48
  }
55
49
 
50
+ onSubmit = false
51
+
52
+ onSubmitEdit = false
53
+
56
54
  componentDidMount () {
57
55
  this.timer = setTimeout(() => {
58
56
  this.setState({
@@ -74,7 +72,14 @@ export default class ItemListTree extends Component {
74
72
 
75
73
  componentWillUnmount () {
76
74
  clearTimeout(this.timer)
77
- window.removeEventListener('message', this.onContextAction)
75
+ }
76
+
77
+ onCancelMoveItem = () => {
78
+ this.setState({
79
+ openMoveModal: false,
80
+ moveItem: null,
81
+ moveItemIsGroup: false
82
+ })
78
83
  }
79
84
 
80
85
  filter = list => {
@@ -152,9 +157,7 @@ export default class ItemListTree extends Component {
152
157
  if (!categoryTitle) {
153
158
  return
154
159
  }
155
- const bookmarkGroups = copy(
156
- this.props.bookmarkGroups
157
- )
160
+ const { bookmarkGroups } = window.store
158
161
  const obj = find(
159
162
  bookmarkGroups,
160
163
  bg => bg.id === categoryId
@@ -166,27 +169,20 @@ export default class ItemListTree extends Component {
166
169
  this.setState({
167
170
  categoryId: ''
168
171
  })
169
- const { store } = window
170
- store.setBookmarkGroups(
171
- bookmarkGroups
172
- )
173
- store.batchDbUpdate([{
174
- id: categoryId,
175
- db: 'bookmarkGroups',
176
- upsert: false,
177
- update: {
178
- title: categoryTitle
179
- }
180
- }])
181
172
  }
182
173
 
183
174
  onClick = () => {
184
175
 
185
176
  }
186
177
 
187
- onSubmit = false
188
-
189
- onSubmitEdit = false
178
+ openMoveModal = (e, item, isGroup) => {
179
+ e.stopPropagation()
180
+ this.setState({
181
+ openMoveModal: true,
182
+ moveItem: item,
183
+ moveItemIsGroup: isGroup
184
+ })
185
+ }
190
186
 
191
187
  handleChangeBookmarkGroupTitle = e => {
192
188
  let { value } = e.target
@@ -233,19 +229,14 @@ export default class ItemListTree extends Component {
233
229
  parentId: ''
234
230
  }, () => {
235
231
  this.onSubmit = false
236
- let bookmarkGroups = copy(
237
- this.props.bookmarkGroups
238
- )
232
+ const { bookmarkGroups } = window.store
239
233
  const newCat = {
240
234
  id: uid(),
241
235
  title: this.state.bookmarkGroupTitle,
242
236
  level: 2,
243
237
  bookmarkIds: []
244
238
  }
245
- bookmarkGroups = [
246
- newCat,
247
- ...bookmarkGroups
248
- ]
239
+ bookmarkGroups.unshift(newCat)
249
240
  const cat = find(
250
241
  bookmarkGroups,
251
242
  d => d.id === id
@@ -257,22 +248,6 @@ export default class ItemListTree extends Component {
257
248
  ...(cat.bookmarkGroupIds || []),
258
249
  newCat.id
259
250
  ]
260
- const { store } = window
261
- store.setBookmarkGroups(
262
- bookmarkGroups
263
- )
264
- store.batchDbAdd([{
265
- db: 'bookmarkGroups',
266
- obj: newCat
267
- }])
268
- store.batchDbUpdate([{
269
- upsert: false,
270
- id,
271
- update: {
272
- bookmarkGroupIds: cat.bookmarkGroupIds
273
- },
274
- db: 'bookmarkGroups'
275
- }])
276
251
  })
277
252
  }
278
253
 
@@ -345,137 +320,6 @@ export default class ItemListTree extends Component {
345
320
  )
346
321
  }
347
322
 
348
- onCut = (item, isGroup) => {
349
- const str = isGroup
350
- ? copyBookmarkGroupItemPrefix
351
- : copyBookmarkItemPrefix
352
- const txt = str + item.id
353
- cut(txt, createName(item))
354
- }
355
-
356
- onPaste = (item) => {
357
- const str = readClipboard()
358
- const id = str.split(':')[1]
359
- const bookmarkGroups = copy(
360
- this.props.bookmarkGroups
361
- )
362
- const from = bookmarkGroups.find(t => {
363
- return t.bookmarkIds.includes(id)
364
- })
365
- from.bookmarkIds = from.bookmarkIds.filter(d => {
366
- return d !== id
367
- })
368
- const to = bookmarkGroups.find(t => {
369
- return t.id === item.id
370
- })
371
- if (!to.bookmarkIds) {
372
- to.bookmarkIds = []
373
- }
374
- to.bookmarkIds = uniq(
375
- [
376
- ...to.bookmarkIds,
377
- id
378
- ]
379
- )
380
- const { store } = window
381
- if (from) {
382
- store.editBookmarkGroup(
383
- from.id,
384
- {
385
- bookmarkIds: (from.bookmarkIds || []).filter(d => {
386
- return d !== id
387
- })
388
- }
389
- )
390
- }
391
- store.editBookmarkGroup(
392
- item.id,
393
- {
394
- bookmarkIds: uniq(
395
- [
396
- ...(item.bookmarkIds || []),
397
- id
398
- ]
399
- )
400
- }
401
- )
402
- }
403
-
404
- computePos = (e) => {
405
- return {
406
- left: e.clientX,
407
- top: e.clientY
408
- }
409
- }
410
-
411
- onContextAction = e => {
412
- const {
413
- action,
414
- id,
415
- args = [],
416
- func
417
- } = e.data || {}
418
- if (action === commonActions.closeContextMenuAfter) {
419
- window.removeEventListener('message', this.onContextAction)
420
- return false
421
- }
422
- if (
423
- action !== commonActions.clickContextMenu ||
424
- id !== this.uid ||
425
- !this[func]
426
- ) {
427
- return false
428
- }
429
- window.removeEventListener('message', this.onContextAction)
430
- this[func](...args)
431
- }
432
-
433
- onContextMenu = (e, item, isGroup) => {
434
- e.preventDefault()
435
- if (this.props.staticList) {
436
- return null
437
- }
438
- const menus = this.renderContextItems(item, isGroup)
439
- this.uid = uid()
440
- window.store.openContextMenu({
441
- items: menus,
442
- id: this.uid,
443
- pos: this.computePos(e)
444
- })
445
- window.addEventListener('message', this.onContextAction)
446
- this.closeNewGroupForm()
447
- }
448
-
449
- renderContextItems (item, isGroup) {
450
- const res = []
451
- const args = [copy(item), isGroup]
452
- if (!isGroup) {
453
- // res.push({
454
- // func: 'onCopy',
455
- // icon: 'CopyOutlined',
456
- // text: e('copy'),
457
- // args
458
- // })
459
- res.push({
460
- func: 'onCut',
461
- icon: 'FileExcelOutlined',
462
- text: e('cut'),
463
- args
464
- })
465
- }
466
- const canPaste = hasBookmarkOrGroupInClipboardText()
467
- if (isGroup) {
468
- res.push({
469
- func: 'onPaste',
470
- icon: 'CopyOutlined',
471
- text: e('paste'),
472
- disabled: !canPaste,
473
- args
474
- })
475
- }
476
- return res
477
- }
478
-
479
323
  editItem = (e, item, isGroup) => {
480
324
  e.stopPropagation()
481
325
  if (isGroup) {
@@ -604,9 +448,8 @@ export default class ItemListTree extends Component {
604
448
  0,
605
449
  dragItem
606
450
  )
607
- return window.store.setState('bookmarkGroups', bookmarkGroups)
451
+ return
608
452
  }
609
- const updates = []
610
453
  if (isGroupDrag) {
611
454
  const parentDrag = pidDragged
612
455
  ? bookmarkGroups.find(
@@ -617,14 +460,6 @@ export default class ItemListTree extends Component {
617
460
  parentDrag.bookmarkGroupIds = (parentDrag.bookmarkGroupIds || []).filter(
618
461
  id => id !== idDragged
619
462
  )
620
- updates.push({
621
- upsert: false,
622
- id: parentDrag.id,
623
- update: {
624
- bookmarkGroupIds: parentDrag.bookmarkGroupIds
625
- },
626
- db: 'bookmarkGroups'
627
- })
628
463
  }
629
464
  const parentDrop = pidDrop
630
465
  ? bookmarkGroups.find(
@@ -651,14 +486,6 @@ export default class ItemListTree extends Component {
651
486
  }
652
487
  arr.splice(index, 0, idDragged)
653
488
  }
654
- updates.push({
655
- upsert: false,
656
- id: parentDrop.id,
657
- update: {
658
- bookmarkGroupIds: parentDrop.bookmarkGroupIds
659
- },
660
- db: 'bookmarkGroups'
661
- })
662
489
  } else {
663
490
  const parentDrag = bookmarkGroups.find(
664
491
  item => item.id === pidDragged
@@ -669,14 +496,6 @@ export default class ItemListTree extends Component {
669
496
  parentDrag.bookmarkIds = (parentDrag.bookmarkIds || []).filter(
670
497
  id => id !== idDragged
671
498
  )
672
- updates.push({
673
- upsert: false,
674
- id: parentDrag.id,
675
- update: {
676
- bookmarkIds: parentDrag.bookmarkIds
677
- },
678
- db: 'bookmarkGroups'
679
- })
680
499
  const parentDrop = isGroupDrop
681
500
  ? bookmarkGroups.find(
682
501
  item => item.id === idDrop
@@ -702,14 +521,6 @@ export default class ItemListTree extends Component {
702
521
  }
703
522
  arr.splice(index, 0, idDragged)
704
523
  }
705
- updates.push({
706
- upsert: false,
707
- id: parentDrop.id,
708
- update: {
709
- bookmarkIds: parentDrop.bookmarkIds
710
- },
711
- db: 'bookmarkGroups'
712
- })
713
524
  }
714
525
  if (
715
526
  isGroupDrag &&
@@ -720,18 +531,8 @@ export default class ItemListTree extends Component {
720
531
  if (i >= 0) {
721
532
  const item = bookmarkGroups[i]
722
533
  item.level = 2
723
- updates.push({
724
- upsert: false,
725
- id: item.id,
726
- update: {
727
- level: item.level
728
- },
729
- db: 'bookmarkGroups'
730
- })
731
534
  }
732
535
  }
733
- window.store.batchDbUpdate(updates)
734
- return window.store.setState('bookmarkGroups', bookmarkGroups)
735
536
  }
736
537
 
737
538
  editCategory = () => {
@@ -757,9 +558,7 @@ export default class ItemListTree extends Component {
757
558
  duplicateItem = (e, item) => {
758
559
  e.stopPropagation()
759
560
  const { addItem } = window.store
760
- const bookmarkGroups = copy(
761
- this.props.bookmarkGroups
762
- )
561
+ const { bookmarkGroups } = this.props
763
562
 
764
563
  const newbookmark = copy(item)
765
564
  newbookmark.id = uid()
@@ -779,14 +578,16 @@ export default class ItemListTree extends Component {
779
578
  addItem(newbookmark, settingMap.bookmarks)
780
579
  // update bookmark groups
781
580
  this.updateBookmarkGroups(
782
- bookmarkGroups,
783
581
  newbookmark,
784
582
  categoryId
785
583
  )
786
584
  this.props.onClickItem(newbookmark)
787
585
  }
788
586
 
789
- updateBookmarkGroups = (bookmarkGroups, bookmark, categoryId) => {
587
+ updateBookmarkGroups = (bookmark, categoryId) => {
588
+ const {
589
+ bookmarkGroups
590
+ } = window.store
790
591
  let index = bookmarkGroups.findIndex(
791
592
  bg => bg.id === categoryId
792
593
  )
@@ -795,48 +596,20 @@ export default class ItemListTree extends Component {
795
596
  bg => bg.id === defaultBookmarkGroupId
796
597
  )
797
598
  }
798
- const updates = []
799
599
  const bid = bookmark.id
800
600
  const bg = bookmarkGroups[index]
801
- const old = copy(bg.bookmarkIds)
802
601
  if (!bg.bookmarkIds.includes(bid)) {
803
602
  bg.bookmarkIds.unshift(bid)
804
603
  }
805
604
  bg.bookmarkIds = uniq(bg.bookmarkIds)
806
- if (!isEqual(old, copy(bg.bookmarkIds))) {
807
- updates.push({
808
- id: bg.id,
809
- db: 'bookmarkGroups',
810
- upsert: false,
811
- update: {
812
- bookmarkIds: bg.bookmarkIds
813
- }
814
- })
815
- }
816
- bookmarkGroups = bookmarkGroups.map((bg, i) => {
605
+ bookmarkGroups.forEach((bg, i) => {
817
606
  if (i === index) {
818
- return bg
607
+ return
819
608
  }
820
- const old = copy(bg.bookmarkIds)
821
609
  bg.bookmarkIds = bg.bookmarkIds.filter(
822
610
  g => g !== bid
823
611
  )
824
- if (!isEqual(old, copy(bg.bookmarkIds))) {
825
- updates.push({
826
- id: bg.id,
827
- db: 'bookmarkGroups',
828
- upsert: false,
829
- update: {
830
- bookmarkIds: bg.bookmarkIds
831
- }
832
- })
833
- }
834
- return bg
835
612
  })
836
- window.store.setBookmarkGroups(
837
- bookmarkGroups
838
- )
839
- window.store.batchDbUpdate(updates)
840
613
  }
841
614
 
842
615
  findBookmarkByTitle = (bookmarks, oldBookmark) => {
@@ -861,7 +634,7 @@ export default class ItemListTree extends Component {
861
634
  [
862
635
  'del',
863
636
  'openAll',
864
- 'onContextMenu',
637
+ 'openMoveModal',
865
638
  'editItem',
866
639
  'addSubCat',
867
640
  'onSelect',
@@ -875,13 +648,7 @@ export default class ItemListTree extends Component {
875
648
  ...pick(
876
649
  this.state,
877
650
  [
878
- 'keyword',
879
- 'openAll',
880
- 'onContextMenu',
881
- 'editItem',
882
- 'addSubCat',
883
- 'onSelect',
884
- 'duplicateItem'
651
+ 'keyword'
885
652
  ]
886
653
  )
887
654
  }
@@ -1024,7 +791,7 @@ export default class ItemListTree extends Component {
1024
791
  }
1025
792
 
1026
793
  render () {
1027
- const { ready } = this.state
794
+ const { ready, openMoveModal, moveItem, moveItemIsGroup } = this.state
1028
795
  if (!ready) {
1029
796
  return (
1030
797
  <div className='pd3 aligncenter'>
@@ -1038,6 +805,13 @@ export default class ItemListTree extends Component {
1038
805
  staticList,
1039
806
  listStyle = {}
1040
807
  } = this.props
808
+ const moveProps = {
809
+ openMoveModal,
810
+ moveItem,
811
+ moveItemIsGroup,
812
+ bookmarkGroups,
813
+ onCancelMoveItem: this.onCancelMoveItem
814
+ }
1041
815
  const level1Bookgroups = ready
1042
816
  ? bookmarkGroups.filter(
1043
817
  d => !d.level || d.level < 2
@@ -1045,6 +819,7 @@ export default class ItemListTree extends Component {
1045
819
  : []
1046
820
  return (
1047
821
  <div className={`tree-list item-type-${type}`}>
822
+ <MoveItemModal {...moveProps} />
1048
823
  {
1049
824
  staticList
1050
825
  ? null
@@ -1,3 +1,4 @@
1
+ import { createRef } from 'react'
1
2
  import RdpSession from '../rdp/rdp-session'
2
3
  import { createTerm } from '../terminal/terminal-apis'
3
4
  import deepCopy from 'json-deep-copy'
@@ -35,6 +36,8 @@ export default class VncSession extends RdpSession {
35
36
  }
36
37
  }
37
38
 
39
+ domRef = createRef()
40
+
38
41
  componentDidMount () {
39
42
  this.remoteInit()
40
43
  }
@@ -203,8 +206,7 @@ export default class VncSession extends RdpSession {
203
206
  }
204
207
 
205
208
  getDom = () => {
206
- const id = 'canvas_' + this.props.tab.id
207
- return document.getElementById(id)
209
+ return this.domRef.current
208
210
  }
209
211
 
210
212
  handleReInit = () => {
@@ -282,7 +284,7 @@ export default class VncSession extends RdpSession {
282
284
  <div
283
285
  {...divProps}
284
286
  className='vnc-session-wrap session-v-wrap'
285
- id={'canvas_' + this.props.tab.id}
287
+ ref={this.domRef}
286
288
  />
287
289
  {this.renderConfirm()}
288
290
  </div>
@@ -2,14 +2,11 @@
2
2
  * app upgrade
3
3
  */
4
4
 
5
- import { commonActions } from '../common/constants'
5
+ import { refsStatic } from '../components/common/ref'
6
6
 
7
7
  export default Store => {
8
8
  Store.prototype.onCheckUpdate = (noSkip = true) => {
9
- window.postMessage({
10
- action: commonActions.appUpdateCheck,
11
- noSkip
12
- }, '*')
9
+ refsStatic.get('upgrade')?.appUpdateCheck(noSkip)
13
10
  }
14
11
  Store.prototype.getProxySetting = function () {
15
12
  const {
@@ -7,6 +7,7 @@ import {
7
7
  defaultBookmarkGroupId,
8
8
  settingMap
9
9
  } from '../common/constants'
10
+ import { action } from 'manate'
10
11
 
11
12
  export default Store => {
12
13
  Store.prototype.getBookmarkGroupsTotal = function () {
@@ -44,17 +45,17 @@ export default Store => {
44
45
  }
45
46
  }
46
47
 
47
- Store.prototype.delBookmarkGroup = function ({ id }) {
48
+ Store.prototype.delBookmarkGroup = action(function ({ id }) {
48
49
  const { store } = window
49
50
  if (id === defaultBookmarkGroupId) {
50
51
  return
51
52
  }
52
- let bookmarkGroups = store.bookmarkGroups
53
+ let { bookmarkGroups } = store
53
54
  const tobeDel = find(bookmarkGroups, bg => bg.id === id)
54
55
  if (!tobeDel) {
55
56
  return
56
57
  }
57
- let groups = [tobeDel]
58
+ const groups = [tobeDel]
58
59
  if (
59
60
  tobeDel.level !== 2 &&
60
61
  tobeDel.bookmarkGroupIds &&
@@ -63,13 +64,9 @@ export default Store => {
63
64
  const childs = bookmarkGroups.filter(
64
65
  bg => tobeDel.bookmarkGroupIds.includes(bg.id)
65
66
  )
66
- groups = [
67
- ...groups,
68
- ...childs
69
- ]
67
+ groups.push(...childs)
70
68
  }
71
69
  const groupIds = groups.map(g => g.id)
72
- const updates = []
73
70
  const defaultCatIndex = tobeDel.level !== 2
74
71
  ? bookmarkGroups.findIndex(
75
72
  g => g.id === defaultBookmarkGroupId
@@ -80,33 +77,82 @@ export default Store => {
80
77
  for (const g of groups) {
81
78
  if (g.bookmarkIds.length) {
82
79
  const def = bookmarkGroups[defaultCatIndex]
83
- def.bookmarkIds = [
84
- ...g.bookmarkIds,
85
- ...def.bookmarkIds
86
- ]
87
- updates.push({
88
- id: def.id,
89
- db: 'bookmarkGroups',
90
- upsert: false,
91
- update: {
92
- bookmarkIds: def.bookmarkIds
93
- }
94
- })
80
+ def.bookmarkIds.push(...g.bookmarkIds)
95
81
  }
96
82
  }
97
83
  bookmarkGroups = bookmarkGroups.filter(t => {
98
84
  return !groupIds.includes(t.id)
99
85
  })
100
- store.batchDbUpdate(updates)
101
- store.batchDbDel(groupIds.map(id => {
102
- return {
103
- id,
104
- db: 'bookmarkGroups'
105
- }
106
- }))
107
- store.setBookmarkGroups(bookmarkGroups)
108
86
  if (id === store.currentBookmarkGroupId) {
109
87
  store.currentBookmarkGroupId = ''
110
88
  }
89
+ })
90
+
91
+ Store.prototype.fixBookmarkGroups = function () {
92
+ const { store } = window
93
+ const { bookmarks, bookmarkGroups } = store
94
+
95
+ // Create sets for quick lookup
96
+ const bookmarkIds = new Set(bookmarks.map(b => b.id))
97
+ const groupIds = new Set(bookmarkGroups.map(g => g.id))
98
+
99
+ // Fix bookmarkGroups
100
+ for (const group of bookmarkGroups) {
101
+ // Fix bookmarkIds - remove non-existent bookmark references
102
+ if (group.bookmarkIds) {
103
+ group.bookmarkIds = group.bookmarkIds.filter(id => bookmarkIds.has(id))
104
+ } else {
105
+ group.bookmarkIds = []
106
+ }
107
+
108
+ // Fix bookmarkGroupIds - remove non-existent group references
109
+ if (group.bookmarkGroupIds) {
110
+ group.bookmarkGroupIds = group.bookmarkGroupIds.filter(id =>
111
+ groupIds.has(id) && id !== group.id // Prevent self-reference
112
+ )
113
+ } else {
114
+ group.bookmarkGroupIds = []
115
+ }
116
+ }
117
+
118
+ // Find stray bookmarks (not belonging to any group)
119
+ const assignedBookmarkIds = new Set(
120
+ bookmarkGroups.reduce((acc, group) =>
121
+ [...acc, ...(group.bookmarkIds || [])],
122
+ [])
123
+ )
124
+ const defaultGroup = bookmarkGroups.find(g => g.id === defaultBookmarkGroupId)
125
+ const strayBookmarkIds = bookmarks
126
+ .map(b => b.id)
127
+ .filter(id => !assignedBookmarkIds.has(id))
128
+
129
+ // Add stray bookmarks to default group
130
+ if (strayBookmarkIds.length) {
131
+ if (defaultGroup) {
132
+ defaultGroup.bookmarkIds = [
133
+ ...new Set([...defaultGroup.bookmarkIds, ...strayBookmarkIds])
134
+ ]
135
+ }
136
+ }
137
+
138
+ // Find stray groups (not belonging to any parent group and not being a top-level group)
139
+ const assignedGroupIds = new Set(
140
+ bookmarkGroups.reduce((acc, group) =>
141
+ [...acc, ...(group.bookmarkGroupIds || [])],
142
+ [])
143
+ )
144
+
145
+ const strayGroups = bookmarkGroups.filter(group =>
146
+ group.level === 2 && // Only check non-top-level groups
147
+ group.id !== defaultBookmarkGroupId && // Exclude default group
148
+ !assignedGroupIds.has(group.id) // Not assigned to any parent
149
+ )
150
+
151
+ // Find a suitable parent for stray groups
152
+ if (strayGroups.length) {
153
+ defaultGroup.bookmarkGroupIds = [
154
+ ...new Set([...defaultGroup.bookmarkGroupIds, ...strayGroups.map(g => g.id)])
155
+ ]
156
+ }
111
157
  }
112
158
  }