@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.
- package/client/common/clipboard.js +1 -14
- package/client/common/constants.js +0 -43
- package/client/common/data-compare.js +55 -0
- package/client/common/default-setting.js +2 -10
- package/client/common/resolve.js +18 -22
- package/client/common/sftp.js +0 -3
- package/client/components/ai/ai-chat.jsx +30 -6
- package/client/components/ai/ai-config.jsx +17 -6
- package/client/components/batch-op/batch-op.jsx +3 -24
- package/client/components/bookmark-form/bookmark-group-tree-format.js +7 -9
- package/client/components/bookmark-form/form-ssh-common.jsx +0 -2
- package/client/components/bookmark-form/ssh-form.jsx +8 -41
- package/client/components/bookmark-form/tree-delete.jsx +6 -15
- package/client/components/common/animate-text.jsx +3 -4
- package/client/components/common/drag-handle.jsx +59 -45
- package/client/components/common/drag-handle.styl +2 -1
- package/client/components/common/input-auto-focus.jsx +29 -63
- package/client/components/common/ref.js +24 -0
- package/client/components/footer/batch-input.jsx +1 -6
- package/client/components/footer/footer-entry.jsx +13 -16
- package/client/components/footer/footer.styl +0 -5
- package/client/components/icons/ai-icon.jsx +17 -0
- package/client/components/icons/ai-icon.styl +3 -0
- package/client/components/layout/layout-item.jsx +14 -0
- package/client/components/main/main.jsx +8 -19
- package/client/components/main/upgrade.jsx +13 -25
- package/client/components/profile/profile-form-elem.jsx +1 -2
- package/client/components/quick-commands/on-drop.js +1 -12
- package/client/components/quick-commands/quick-command-transport-mod.jsx +3 -13
- package/client/components/quick-commands/quick-commands-form-elem.jsx +1 -2
- package/client/components/rdp/rdp-session.jsx +4 -4
- package/client/components/session/session.jsx +9 -11
- package/client/components/setting-panel/on-tree-drop.js +4 -35
- package/client/components/setting-panel/setting-common.jsx +4 -1
- package/client/components/setting-panel/setting-modal.jsx +7 -5
- package/client/components/setting-panel/tab-settings.jsx +0 -1
- package/client/components/setting-sync/setting-sync.jsx +0 -1
- package/client/components/sftp/address-bookmark-item.jsx +1 -15
- package/client/components/sftp/confirm-modal-store.jsx +2 -2
- package/client/components/sftp/{file-mode-modal.jsx → file-info-modal.jsx} +137 -37
- package/client/components/sftp/file-item.jsx +156 -192
- package/client/components/sftp/file-table-header.jsx +98 -0
- package/client/components/sftp/list-table-ui.jsx +125 -416
- package/client/components/sftp/sftp-entry.jsx +102 -128
- package/client/components/sftp/sftp.styl +6 -22
- package/client/components/sftp/transfer-conflict-store.jsx +8 -12
- package/client/components/sftp/transport-action-store.jsx +7 -15
- package/client/components/shortcuts/shortcut-control.jsx +72 -3
- package/client/components/shortcuts/shortcut-handler.js +0 -1
- package/client/components/side-panel-r/side-panel-r.jsx +7 -4
- package/client/components/sidebar/history.jsx +3 -0
- package/client/components/sidebar/index.jsx +1 -1
- package/client/components/sidebar/info-modal.jsx +3 -0
- package/client/components/sidebar/side-panel.jsx +7 -4
- package/client/components/sidebar/sidebar-panel.jsx +1 -1
- package/client/components/sidebar/sidebar.styl +3 -3
- package/client/components/sys-menu/icons-map.jsx +52 -0
- package/client/components/{context-menu → sys-menu}/menu-btn.jsx +33 -45
- package/client/components/sys-menu/sys-menu.jsx +163 -0
- package/client/components/{context-menu/context-menu.styl → sys-menu/sys-menu.styl} +2 -11
- package/client/components/tabs/index.jsx +5 -97
- package/client/components/tabs/tab.jsx +121 -73
- package/client/components/tabs/tabs.styl +4 -1
- package/client/components/terminal/term-search.jsx +16 -28
- package/client/components/terminal/terminal-interactive.jsx +0 -2
- package/client/components/terminal/{index.jsx → terminal.jsx} +126 -248
- package/client/components/terminal-info/base.jsx +21 -46
- package/client/components/terminal-info/terminal-info.jsx +3 -0
- package/client/components/text-editor/text-editor.jsx +38 -53
- package/client/components/theme/theme-form.jsx +0 -2
- package/client/components/tree-list/bookmark-toolbar.jsx +23 -47
- package/client/components/tree-list/bookmark-transport.jsx +2 -90
- package/client/components/tree-list/move-item-modal.jsx +101 -0
- package/client/components/tree-list/tree-list-item.jsx +6 -8
- package/client/components/tree-list/tree-list.jsx +48 -273
- package/client/components/vnc/vnc-session.jsx +5 -3
- package/client/store/app-upgrade.js +2 -5
- package/client/store/bookmark-group.js +74 -28
- package/client/store/common.js +36 -54
- package/client/store/event.js +4 -37
- package/client/store/init-state.js +9 -12
- package/client/store/item.js +34 -39
- package/client/store/load-data.js +5 -1
- package/client/store/quick-command.js +2 -12
- package/client/store/session.js +6 -7
- package/client/store/setting.js +3 -7
- package/client/store/sidebar.js +2 -8
- package/client/store/store.js +0 -20
- package/client/store/system-menu.js +1 -2
- package/client/store/tab.js +29 -1
- package/client/store/terminal-theme.js +0 -4
- package/client/store/watch.js +26 -4
- package/package.json +1 -1
- package/client/common/post-msg.js +0 -3
- package/client/components/common/native-input.jsx +0 -30
- package/client/components/context-menu/context-menu.jsx +0 -339
- package/client/components/sftp/file-props-modal.jsx +0 -210
- package/client/store/context-menu.js +0 -23
- /package/client/components/{context-menu → sys-menu}/boomarks.jsx +0 -0
- /package/client/components/{context-menu → sys-menu}/history.jsx +0 -0
- /package/client/components/{context-menu → sys-menu}/icon-holder.jsx +0 -0
- /package/client/components/{context-menu → sys-menu}/sub-tab-menu.jsx +0 -0
- /package/client/components/{context-menu → sys-menu}/tabs.jsx +0 -0
- /package/client/components/{context-menu → sys-menu}/zoom.jsx +0 -0
|
@@ -19,12 +19,10 @@ import {
|
|
|
19
19
|
permission2mode
|
|
20
20
|
} from '../../common/mode2permission'
|
|
21
21
|
import wait from '../../common/wait'
|
|
22
|
-
import postMessage from '../../common/post-msg'
|
|
23
22
|
import {
|
|
24
23
|
fileOperationsMap,
|
|
25
24
|
isWin, transferTypeMap, typeMap,
|
|
26
|
-
isMac, maxEditFileSize, ctrlOrCmd
|
|
27
|
-
commonActions
|
|
25
|
+
isMac, maxEditFileSize, ctrlOrCmd
|
|
28
26
|
} from '../../common/constants'
|
|
29
27
|
import findParent from '../../common/find-parent'
|
|
30
28
|
import sorter from '../../common/index-sorter'
|
|
@@ -35,16 +33,14 @@ import time from '../../common/time'
|
|
|
35
33
|
import { filesize } from 'filesize'
|
|
36
34
|
import { createTransferProps } from './transfer-common'
|
|
37
35
|
import generate from '../../common/uid'
|
|
36
|
+
import { refsStatic, refs } from '../common/ref'
|
|
37
|
+
import iconsMap from '../sys-menu/icons-map'
|
|
38
|
+
import {
|
|
39
|
+
Dropdown
|
|
40
|
+
} from 'antd'
|
|
38
41
|
|
|
39
42
|
const e = window.translate
|
|
40
43
|
|
|
41
|
-
const computePos = (e) => {
|
|
42
|
-
return {
|
|
43
|
-
left: e.clientX,
|
|
44
|
-
top: e.clientY
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
44
|
const fileItemCls = 'sftp-item'
|
|
49
45
|
const onDragCls = 'sftp-ondrag'
|
|
50
46
|
const onDragOverCls = 'sftp-dragover'
|
|
@@ -57,11 +53,13 @@ export default class FileSection extends React.Component {
|
|
|
57
53
|
file: copy(props.file),
|
|
58
54
|
overwriteStrategy: ''
|
|
59
55
|
}
|
|
60
|
-
|
|
56
|
+
// Create ref
|
|
57
|
+
this.domRef = React.createRef()
|
|
61
58
|
}
|
|
62
59
|
|
|
63
60
|
componentDidMount () {
|
|
64
|
-
this.
|
|
61
|
+
this.id = 'file-' + (this.props.file?.id || generate())
|
|
62
|
+
refs.add(this.id, this)
|
|
65
63
|
this.applyStyle()
|
|
66
64
|
}
|
|
67
65
|
|
|
@@ -75,17 +73,20 @@ export default class FileSection extends React.Component {
|
|
|
75
73
|
}
|
|
76
74
|
|
|
77
75
|
componentWillUnmount () {
|
|
76
|
+
refsStatic.remove(this.id)
|
|
78
77
|
clearTimeout(this.timer)
|
|
79
78
|
this.timer = null
|
|
80
|
-
this.
|
|
79
|
+
this.domRef = null
|
|
81
80
|
this.dropTarget = null
|
|
82
81
|
this.removeFileEditEvent()
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get editor () {
|
|
85
|
+
return refsStatic.get('text-editor')
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
applyStyle = () => {
|
|
88
|
-
if (!this.
|
|
89
|
+
if (!this.domRef) {
|
|
89
90
|
return
|
|
90
91
|
}
|
|
91
92
|
const {
|
|
@@ -95,7 +96,7 @@ export default class FileSection extends React.Component {
|
|
|
95
96
|
const headers = document.querySelectorAll(
|
|
96
97
|
`#id-${id} .${type} .sftp-file-table-header .sftp-header-box`
|
|
97
98
|
)
|
|
98
|
-
this.
|
|
99
|
+
this.domRef.current?.querySelectorAll('.sftp-file-prop').forEach((n, i) => {
|
|
99
100
|
const h = headers[i]
|
|
100
101
|
if (h) {
|
|
101
102
|
const s = pick(h.style, ['width', 'left'])
|
|
@@ -211,7 +212,7 @@ export default class FileSection extends React.Component {
|
|
|
211
212
|
const cls = this.props.selectedFiles.length > 1
|
|
212
213
|
? onDragCls + ' ' + onMultiDragCls
|
|
213
214
|
: onDragCls
|
|
214
|
-
addClass(this.
|
|
215
|
+
addClass(this.domRef.current, cls)
|
|
215
216
|
e.dataTransfer.setData('fromFile', JSON.stringify(this.props.file))
|
|
216
217
|
}
|
|
217
218
|
|
|
@@ -257,7 +258,7 @@ export default class FileSection extends React.Component {
|
|
|
257
258
|
if (!type) {
|
|
258
259
|
return
|
|
259
260
|
}
|
|
260
|
-
let toFile = this.props[type + 'FileTree']
|
|
261
|
+
let toFile = this.props[type + 'FileTree'].get(id) || {}
|
|
261
262
|
if (!toFile.id || !toFile.isDirectory) {
|
|
262
263
|
toFile = {
|
|
263
264
|
type,
|
|
@@ -272,7 +273,7 @@ export default class FileSection extends React.Component {
|
|
|
272
273
|
this.props.modifier({
|
|
273
274
|
onDrag: false
|
|
274
275
|
})
|
|
275
|
-
removeClass(this.
|
|
276
|
+
removeClass(this.domRef.current, onDragCls, onMultiDragCls)
|
|
276
277
|
document.querySelectorAll('.' + onDragOverCls).forEach((d) => {
|
|
277
278
|
removeClass(d, onDragOverCls)
|
|
278
279
|
})
|
|
@@ -381,7 +382,7 @@ export default class FileSection extends React.Component {
|
|
|
381
382
|
|
|
382
383
|
showInfo = () => {
|
|
383
384
|
const { type } = this.props
|
|
384
|
-
|
|
385
|
+
refsStatic.get('file-modal')?.showFileInfoModal({
|
|
385
386
|
file: this.state.file,
|
|
386
387
|
tab: this.props.tab,
|
|
387
388
|
visible: true,
|
|
@@ -463,8 +464,12 @@ export default class FileSection extends React.Component {
|
|
|
463
464
|
const { file } = this.state
|
|
464
465
|
const {
|
|
465
466
|
id,
|
|
466
|
-
type
|
|
467
|
+
type,
|
|
468
|
+
isParent
|
|
467
469
|
} = file
|
|
470
|
+
if (isParent) {
|
|
471
|
+
return
|
|
472
|
+
}
|
|
468
473
|
this.props.modifier({
|
|
469
474
|
lastClickedFile: file
|
|
470
475
|
})
|
|
@@ -505,42 +510,28 @@ export default class FileSection extends React.Component {
|
|
|
505
510
|
})
|
|
506
511
|
}
|
|
507
512
|
|
|
508
|
-
changeFileMode = async
|
|
509
|
-
const {
|
|
510
|
-
file = {},
|
|
511
|
-
action
|
|
512
|
-
} = e.data || {}
|
|
513
|
-
if (action === commonActions.submitFileModeClose) {
|
|
514
|
-
window.removeEventListener('message', this.changeFileMode)
|
|
515
|
-
return false
|
|
516
|
-
}
|
|
517
|
-
if (
|
|
518
|
-
action !== commonActions.submitFileModeEdit ||
|
|
519
|
-
file.id !== this.state.file.id
|
|
520
|
-
) {
|
|
521
|
-
return false
|
|
522
|
-
}
|
|
513
|
+
changeFileMode = async (file) => {
|
|
523
514
|
const { permission, type, path, name } = file
|
|
524
515
|
const func = type === typeMap.local
|
|
525
516
|
? fs.chmod
|
|
526
517
|
: this.props.sftp.chmod
|
|
527
518
|
const p = resolve(path, name)
|
|
528
519
|
await func(p, permission).catch(window.store.onError)
|
|
529
|
-
window.removeEventListener('message', this.changeFileMode)
|
|
530
520
|
this.props[type + 'List']()
|
|
531
521
|
}
|
|
532
522
|
|
|
533
523
|
openFileModeModal = () => {
|
|
534
524
|
const { type } = this.props
|
|
535
|
-
|
|
536
|
-
|
|
525
|
+
refsStatic.get('file-modal')?.showFileModeModal(
|
|
526
|
+
{
|
|
527
|
+
tab: this.props.tab,
|
|
528
|
+
visible: true,
|
|
529
|
+
uidTree: this.props[`${type}UidTree`],
|
|
530
|
+
gidTree: this.props[`${type}GidTree`]
|
|
531
|
+
},
|
|
532
|
+
this.state.file,
|
|
533
|
+
this.id
|
|
537
534
|
)
|
|
538
|
-
window.store.openFileModeModal({
|
|
539
|
-
tab: this.props.tab,
|
|
540
|
-
visible: true,
|
|
541
|
-
uidTree: this.props[`${type}UidTree`],
|
|
542
|
-
gidTree: this.props[`${type}GidTree`]
|
|
543
|
-
}, this.state.file)
|
|
544
535
|
}
|
|
545
536
|
|
|
546
537
|
handleBlur = () => {
|
|
@@ -596,11 +587,11 @@ export default class FileSection extends React.Component {
|
|
|
596
587
|
})
|
|
597
588
|
}
|
|
598
589
|
|
|
599
|
-
enterDirectory = (e, file) => {
|
|
590
|
+
enterDirectory = (e, file = this.state.file) => {
|
|
600
591
|
e && e.stopPropagation && e.stopPropagation()
|
|
601
|
-
const { type, name } = file
|
|
592
|
+
const { type, name, isParent } = file
|
|
602
593
|
const n = `${type}Path`
|
|
603
|
-
const path = this.props[n]
|
|
594
|
+
const path = isParent ? file.path : this.props[n]
|
|
604
595
|
const np = resolve(path, name)
|
|
605
596
|
const op = this.props[type + 'Path']
|
|
606
597
|
this.props.modifier({
|
|
@@ -620,39 +611,11 @@ export default class FileSection extends React.Component {
|
|
|
620
611
|
}
|
|
621
612
|
|
|
622
613
|
removeFileEditEvent = () => {
|
|
623
|
-
delete this.eid
|
|
624
614
|
if (this.watchingFile) {
|
|
625
615
|
window.pre.ipcOffEvent('file-change', this.onFileChange)
|
|
626
616
|
window.pre.runGlobalAsync('unwatchFile', this.watchingFile)
|
|
627
617
|
delete this.watchingFile
|
|
628
618
|
}
|
|
629
|
-
window.removeEventListener('message', this.onFileEditEvent)
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
onFileEditEvent = e => {
|
|
633
|
-
const {
|
|
634
|
-
action,
|
|
635
|
-
id,
|
|
636
|
-
text,
|
|
637
|
-
path,
|
|
638
|
-
mode,
|
|
639
|
-
type,
|
|
640
|
-
noClose
|
|
641
|
-
} = e.data || {}
|
|
642
|
-
if (id !== this.eid) {
|
|
643
|
-
return false
|
|
644
|
-
}
|
|
645
|
-
if (
|
|
646
|
-
action === commonActions.fetchTextEditorText
|
|
647
|
-
) {
|
|
648
|
-
this.fetchEditorText(path, type)
|
|
649
|
-
} else if (action === commonActions.submitTextEditorText) {
|
|
650
|
-
this.onSubmitEditFile(mode, type, path, text, noClose)
|
|
651
|
-
} else if (action === commonActions.onCloseTextEditor) {
|
|
652
|
-
this.removeFileEditEvent()
|
|
653
|
-
} else if (action === commonActions.editWithSystemEditor) {
|
|
654
|
-
this.editWithSystemEditor(text)
|
|
655
|
-
}
|
|
656
619
|
}
|
|
657
620
|
|
|
658
621
|
editWithSystemEditor = async (text) => {
|
|
@@ -667,7 +630,7 @@ export default class FileSection extends React.Component {
|
|
|
667
630
|
} else {
|
|
668
631
|
const id = generate()
|
|
669
632
|
tempPath = window.pre.resolve(
|
|
670
|
-
window.pre.tempDir, `temp-${id}-${name}`
|
|
633
|
+
window.pre.tempDir, `electerm-temp-${id}-${name}`
|
|
671
634
|
)
|
|
672
635
|
await fs.writeFile(tempPath, text)
|
|
673
636
|
}
|
|
@@ -676,12 +639,9 @@ export default class FileSection extends React.Component {
|
|
|
676
639
|
}
|
|
677
640
|
|
|
678
641
|
onFileChange = (e, text) => {
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
id: this.eid,
|
|
683
|
-
text
|
|
684
|
-
}
|
|
642
|
+
this.editor.editWithSystemEditorDone({
|
|
643
|
+
id: this.id,
|
|
644
|
+
text
|
|
685
645
|
})
|
|
686
646
|
}
|
|
687
647
|
|
|
@@ -714,13 +674,7 @@ export default class FileSection extends React.Component {
|
|
|
714
674
|
const text = typeMap.remote === type
|
|
715
675
|
? await this.props.sftp.readFile(path)
|
|
716
676
|
: await fs.readFile(path)
|
|
717
|
-
|
|
718
|
-
action: commonActions.loadTextEditorText,
|
|
719
|
-
data: {
|
|
720
|
-
text,
|
|
721
|
-
loading: false
|
|
722
|
-
}
|
|
723
|
-
})
|
|
677
|
+
return text
|
|
724
678
|
}
|
|
725
679
|
|
|
726
680
|
onSubmitEditFile = async (mode, type, path, text, noClose) => {
|
|
@@ -743,25 +697,17 @@ export default class FileSection extends React.Component {
|
|
|
743
697
|
data.file = null
|
|
744
698
|
data.text = ''
|
|
745
699
|
}
|
|
746
|
-
|
|
747
|
-
action: commonActions.openTextEditor,
|
|
748
|
-
data
|
|
749
|
-
})
|
|
700
|
+
this.editor?.setState(data)
|
|
750
701
|
if (r && !noClose) {
|
|
751
702
|
this.props[`${type}List`]()
|
|
752
703
|
}
|
|
753
704
|
}
|
|
754
705
|
|
|
755
706
|
editFile = () => {
|
|
756
|
-
this.
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
data: {
|
|
760
|
-
id: this.eid,
|
|
761
|
-
file: this.state.file
|
|
762
|
-
}
|
|
707
|
+
this.editor?.openEditor({
|
|
708
|
+
id: this.id,
|
|
709
|
+
file: this.state.file
|
|
763
710
|
})
|
|
764
|
-
window.addEventListener('message', this.onFileEditEvent)
|
|
765
711
|
}
|
|
766
712
|
|
|
767
713
|
transferOrEnterDirectory = async (e, edit) => {
|
|
@@ -861,15 +807,25 @@ export default class FileSection extends React.Component {
|
|
|
861
807
|
this.props.onGoto(this.props.file.type)
|
|
862
808
|
}
|
|
863
809
|
|
|
864
|
-
|
|
810
|
+
shouldShowSelectedMenu = () => {
|
|
811
|
+
const {
|
|
812
|
+
file: {
|
|
813
|
+
id
|
|
814
|
+
},
|
|
815
|
+
selectedFiles
|
|
816
|
+
} = this.props
|
|
817
|
+
return id &&
|
|
818
|
+
selectedFiles.length > 1 &&
|
|
819
|
+
some(selectedFiles, d => d.id === id)
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
del = async () => {
|
|
823
|
+
const delSelected = this.shouldShowSelectedMenu()
|
|
865
824
|
const { file, selectedFiles } = this.props
|
|
866
825
|
const { type } = file
|
|
867
826
|
const files = delSelected
|
|
868
827
|
? selectedFiles
|
|
869
828
|
: [file]
|
|
870
|
-
postMessage({
|
|
871
|
-
type: commonActions.closeContextMenu
|
|
872
|
-
})
|
|
873
829
|
await this.props.delFiles(type, files)
|
|
874
830
|
}
|
|
875
831
|
|
|
@@ -925,17 +881,42 @@ export default class FileSection extends React.Component {
|
|
|
925
881
|
return !isWin
|
|
926
882
|
}
|
|
927
883
|
|
|
884
|
+
renderContextMenu = () => {
|
|
885
|
+
return this.renderContextItems()
|
|
886
|
+
.map(r => {
|
|
887
|
+
const {
|
|
888
|
+
func,
|
|
889
|
+
text,
|
|
890
|
+
disabled,
|
|
891
|
+
icon,
|
|
892
|
+
subText,
|
|
893
|
+
requireConfirm
|
|
894
|
+
} = r
|
|
895
|
+
const IconCom = iconsMap[icon]
|
|
896
|
+
return {
|
|
897
|
+
key: func,
|
|
898
|
+
label: text,
|
|
899
|
+
disabled,
|
|
900
|
+
icon: <IconCom />,
|
|
901
|
+
extra: subText,
|
|
902
|
+
danger: requireConfirm
|
|
903
|
+
}
|
|
904
|
+
})
|
|
905
|
+
}
|
|
906
|
+
|
|
928
907
|
renderContextItems () {
|
|
929
908
|
const {
|
|
930
909
|
file: {
|
|
931
910
|
type,
|
|
932
911
|
isDirectory,
|
|
933
912
|
size,
|
|
934
|
-
id
|
|
913
|
+
id,
|
|
914
|
+
isParent
|
|
935
915
|
},
|
|
936
916
|
selectedFiles,
|
|
937
917
|
tab
|
|
938
918
|
} = this.props
|
|
919
|
+
const isRealFile = id && !isParent
|
|
939
920
|
const hasHost = !!tab.host
|
|
940
921
|
const { enableSsh } = tab
|
|
941
922
|
const isLocal = type === typeMap.local
|
|
@@ -955,7 +936,7 @@ export default class FileSection extends React.Component {
|
|
|
955
936
|
const showEdit = !isDirectory && id &&
|
|
956
937
|
size < maxEditFileSize
|
|
957
938
|
const res = []
|
|
958
|
-
if (isDirectory &&
|
|
939
|
+
if (isDirectory && isRealFile) {
|
|
959
940
|
res.push({
|
|
960
941
|
func: 'doEnterDirectory',
|
|
961
942
|
icon: 'EnterOutlined',
|
|
@@ -970,7 +951,7 @@ export default class FileSection extends React.Component {
|
|
|
970
951
|
})
|
|
971
952
|
}
|
|
972
953
|
if (
|
|
973
|
-
isDirectory &&
|
|
954
|
+
isDirectory && isRealFile &&
|
|
974
955
|
(
|
|
975
956
|
(hasHost && enableSsh !== false && isRemote) ||
|
|
976
957
|
(isLocal && !hasHost)
|
|
@@ -982,21 +963,21 @@ export default class FileSection extends React.Component {
|
|
|
982
963
|
text: e('gotoFolderInTerminal')
|
|
983
964
|
})
|
|
984
965
|
}
|
|
985
|
-
if (!(!
|
|
966
|
+
if (!(!isRealFile || !hasHost || shouldShowSelectedMenu)) {
|
|
986
967
|
res.push({
|
|
987
968
|
func: 'doTransfer',
|
|
988
969
|
icon: iconType,
|
|
989
970
|
text: transferText
|
|
990
971
|
})
|
|
991
972
|
}
|
|
992
|
-
if (!isDirectory &&
|
|
973
|
+
if (!isDirectory && isRealFile && isLocal) {
|
|
993
974
|
res.push({
|
|
994
975
|
func: 'transferOrEnterDirectory',
|
|
995
976
|
icon: 'ArrowRightOutlined',
|
|
996
977
|
text: e('open')
|
|
997
978
|
})
|
|
998
979
|
}
|
|
999
|
-
if (
|
|
980
|
+
if (isRealFile && isLocal) {
|
|
1000
981
|
res.push({
|
|
1001
982
|
func: 'showInDefaultFileManager',
|
|
1002
983
|
icon: 'ContainerOutlined',
|
|
@@ -1010,15 +991,12 @@ export default class FileSection extends React.Component {
|
|
|
1010
991
|
text: e('edit')
|
|
1011
992
|
})
|
|
1012
993
|
}
|
|
1013
|
-
if (
|
|
994
|
+
if (isRealFile) {
|
|
1014
995
|
res.push({
|
|
1015
996
|
func: 'del',
|
|
1016
997
|
icon: 'CloseCircleOutlined',
|
|
1017
998
|
text: delTxt,
|
|
1018
|
-
|
|
1019
|
-
requireConfirm: true,
|
|
1020
|
-
confirmTitle: this.renderDelConfirmTitle(shouldShowSelectedMenu),
|
|
1021
|
-
args: [shouldShowSelectedMenu]
|
|
999
|
+
requireConfirm: true
|
|
1022
1000
|
})
|
|
1023
1001
|
res.push({
|
|
1024
1002
|
func: 'onCopy',
|
|
@@ -1040,7 +1018,7 @@ export default class FileSection extends React.Component {
|
|
|
1040
1018
|
disabled: !canPaste,
|
|
1041
1019
|
subText: `${ctrlOrCmd}+v`
|
|
1042
1020
|
})
|
|
1043
|
-
if (
|
|
1021
|
+
if (isRealFile) {
|
|
1044
1022
|
res.push({
|
|
1045
1023
|
func: 'doRename',
|
|
1046
1024
|
icon: 'EditOutlined',
|
|
@@ -1075,14 +1053,14 @@ export default class FileSection extends React.Component {
|
|
|
1075
1053
|
icon: 'ReloadOutlined',
|
|
1076
1054
|
text: e('refresh')
|
|
1077
1055
|
})
|
|
1078
|
-
if (this.showModeEdit(type,
|
|
1056
|
+
if (this.showModeEdit(type, isRealFile)) {
|
|
1079
1057
|
res.push({
|
|
1080
1058
|
func: 'editPermission',
|
|
1081
1059
|
icon: 'LockOutlined',
|
|
1082
1060
|
text: e('editPermission')
|
|
1083
1061
|
})
|
|
1084
1062
|
}
|
|
1085
|
-
if (
|
|
1063
|
+
if (isRealFile) {
|
|
1086
1064
|
res.push({
|
|
1087
1065
|
func: 'showInfo',
|
|
1088
1066
|
icon: 'InfoCircleOutlined',
|
|
@@ -1092,46 +1070,8 @@ export default class FileSection extends React.Component {
|
|
|
1092
1070
|
return res
|
|
1093
1071
|
}
|
|
1094
1072
|
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
action,
|
|
1098
|
-
id,
|
|
1099
|
-
args = [],
|
|
1100
|
-
func
|
|
1101
|
-
} = e.data || {}
|
|
1102
|
-
if (action === commonActions.closeContextMenuAfter) {
|
|
1103
|
-
window.removeEventListener('message', this.onContextAction)
|
|
1104
|
-
return false
|
|
1105
|
-
}
|
|
1106
|
-
if (
|
|
1107
|
-
action !== commonActions.clickContextMenu ||
|
|
1108
|
-
id !== this.uid ||
|
|
1109
|
-
!this[func]
|
|
1110
|
-
) {
|
|
1111
|
-
return false
|
|
1112
|
-
}
|
|
1113
|
-
window.removeEventListener('message', this.onContextAction)
|
|
1114
|
-
this[func](...args)
|
|
1115
|
-
}
|
|
1116
|
-
|
|
1117
|
-
onContextMenu = e => {
|
|
1118
|
-
e.preventDefault()
|
|
1119
|
-
const { file } = this.state
|
|
1120
|
-
const selected = this.isSelected(file)
|
|
1121
|
-
if (!selected) {
|
|
1122
|
-
this.onClick(e)
|
|
1123
|
-
}
|
|
1124
|
-
this.props.modifier({
|
|
1125
|
-
lastClickedFile: file
|
|
1126
|
-
})
|
|
1127
|
-
const items = this.renderContextItems()
|
|
1128
|
-
this.uid = generate()
|
|
1129
|
-
window.store.openContextMenu({
|
|
1130
|
-
items,
|
|
1131
|
-
id: this.uid,
|
|
1132
|
-
pos: computePos(e)
|
|
1133
|
-
})
|
|
1134
|
-
window.addEventListener('message', this.onContextAction)
|
|
1073
|
+
onContextMenu = ({ key }) => {
|
|
1074
|
+
this[key]()
|
|
1135
1075
|
}
|
|
1136
1076
|
|
|
1137
1077
|
renderEditing (file) {
|
|
@@ -1154,27 +1094,28 @@ export default class FileSection extends React.Component {
|
|
|
1154
1094
|
)
|
|
1155
1095
|
}
|
|
1156
1096
|
|
|
1157
|
-
renderProp = ({
|
|
1097
|
+
renderProp = ({ id, size }) => {
|
|
1158
1098
|
const { file } = this.state
|
|
1159
|
-
let value = file[
|
|
1099
|
+
let value = file[id]
|
|
1160
1100
|
let typeIcon = null
|
|
1161
1101
|
let symbolicLinkText = null
|
|
1162
1102
|
const {
|
|
1163
1103
|
isDirectory,
|
|
1164
|
-
isSymbolicLink
|
|
1104
|
+
isSymbolicLink,
|
|
1105
|
+
isParent
|
|
1165
1106
|
} = file
|
|
1166
|
-
if (isDirectory &&
|
|
1107
|
+
if (isDirectory && id === 'size') {
|
|
1167
1108
|
value = null
|
|
1168
|
-
} else if (!isDirectory &&
|
|
1109
|
+
} else if (!isDirectory && id === 'size') {
|
|
1169
1110
|
value = filesize(value)
|
|
1170
|
-
} else if (
|
|
1111
|
+
} else if (id === 'owner') {
|
|
1171
1112
|
const { type } = this.props
|
|
1172
1113
|
value = this.props[`${type}UidTree`]['' + value] || value
|
|
1173
|
-
} else if (
|
|
1114
|
+
} else if (id === 'group') {
|
|
1174
1115
|
const { type } = this.props
|
|
1175
1116
|
value = this.props[`${type}GidTree`]['' + value] || value
|
|
1176
1117
|
}
|
|
1177
|
-
if (
|
|
1118
|
+
if (id === 'name') {
|
|
1178
1119
|
// const Icon = isDirectory
|
|
1179
1120
|
// ? FolderOutlined
|
|
1180
1121
|
// : FileOutlined
|
|
@@ -1182,17 +1123,29 @@ export default class FileSection extends React.Component {
|
|
|
1182
1123
|
symbolicLinkText = isSymbolicLink
|
|
1183
1124
|
? <sup className='color-blue symbolic-link-icon'>*</sup>
|
|
1184
1125
|
: null
|
|
1185
|
-
} else if (
|
|
1126
|
+
} else if (id === 'mode') {
|
|
1186
1127
|
value = permission2mode(mode2permission(value))
|
|
1187
|
-
} else if (
|
|
1128
|
+
} else if (id.toLowerCase().includes('time')) {
|
|
1188
1129
|
value = time(value)
|
|
1189
1130
|
}
|
|
1131
|
+
const divProps = {
|
|
1132
|
+
className: `sftp-file-prop noise shi-${id}`,
|
|
1133
|
+
style: {
|
|
1134
|
+
width: size + '%',
|
|
1135
|
+
flexBasis: `${size}%`
|
|
1136
|
+
},
|
|
1137
|
+
title: value
|
|
1138
|
+
}
|
|
1139
|
+
if (isParent && id !== 'name') {
|
|
1140
|
+
value = null
|
|
1141
|
+
divProps.title = ''
|
|
1142
|
+
} else if (isParent && id === 'name') {
|
|
1143
|
+
value = '..'
|
|
1144
|
+
}
|
|
1190
1145
|
return (
|
|
1191
1146
|
<div
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
className={`sftp-file-prop noise shi-${name}`}
|
|
1195
|
-
style={style}
|
|
1147
|
+
{...divProps}
|
|
1148
|
+
key={id}
|
|
1196
1149
|
>
|
|
1197
1150
|
{typeIcon}
|
|
1198
1151
|
{symbolicLinkText}
|
|
@@ -1207,7 +1160,8 @@ export default class FileSection extends React.Component {
|
|
|
1207
1160
|
const {
|
|
1208
1161
|
isDirectory,
|
|
1209
1162
|
id,
|
|
1210
|
-
isEditing
|
|
1163
|
+
isEditing,
|
|
1164
|
+
isParent
|
|
1211
1165
|
} = file
|
|
1212
1166
|
if (isEditing) {
|
|
1213
1167
|
return this.renderEditing(file)
|
|
@@ -1219,10 +1173,9 @@ export default class FileSection extends React.Component {
|
|
|
1219
1173
|
})
|
|
1220
1174
|
const props = {
|
|
1221
1175
|
className,
|
|
1222
|
-
draggable,
|
|
1176
|
+
draggable: draggable && !isParent,
|
|
1223
1177
|
onDoubleClick: this.transferOrEnterDirectory,
|
|
1224
1178
|
...pick(this, [
|
|
1225
|
-
'onContextMenu',
|
|
1226
1179
|
'onClick',
|
|
1227
1180
|
'onDrag',
|
|
1228
1181
|
'onDragEnter',
|
|
@@ -1232,23 +1185,34 @@ export default class FileSection extends React.Component {
|
|
|
1232
1185
|
'onDrop',
|
|
1233
1186
|
'onDragEnd'
|
|
1234
1187
|
]),
|
|
1235
|
-
onDragStart: onDragStart || this.onDragStart
|
|
1188
|
+
onDragStart: onDragStart || this.onDragStart,
|
|
1189
|
+
'data-id': id,
|
|
1190
|
+
id: this.id,
|
|
1191
|
+
'data-is-parent': isParent ? 'y' : 'n',
|
|
1192
|
+
'data-type': type,
|
|
1193
|
+
title: file.name
|
|
1194
|
+
}
|
|
1195
|
+
const ddProps = {
|
|
1196
|
+
menu: {
|
|
1197
|
+
items: this.renderContextMenu(),
|
|
1198
|
+
onClick: this.onContextMenu
|
|
1199
|
+
},
|
|
1200
|
+
trigger: ['contextMenu']
|
|
1236
1201
|
}
|
|
1237
1202
|
return (
|
|
1238
|
-
<
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
}
|
|
1203
|
+
<Dropdown {...ddProps}>
|
|
1204
|
+
<div
|
|
1205
|
+
ref={this.domRef}
|
|
1206
|
+
{...props}
|
|
1207
|
+
>
|
|
1208
|
+
<div className='file-bg' />
|
|
1209
|
+
<div className='file-props-div'>
|
|
1210
|
+
{
|
|
1211
|
+
properties.map(this.renderProp)
|
|
1212
|
+
}
|
|
1213
|
+
</div>
|
|
1250
1214
|
</div>
|
|
1251
|
-
</
|
|
1215
|
+
</Dropdown>
|
|
1252
1216
|
)
|
|
1253
1217
|
}
|
|
1254
1218
|
}
|