@electerm/electerm-react 1.72.48 → 1.80.3
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/constants.js +1 -1
- package/client/common/sftp.js +3 -1
- package/client/components/ai/ai-config.jsx +7 -1
- package/client/components/batch-op/batch-op.jsx +4 -5
- package/client/components/bg/css-overwrite.jsx +179 -0
- package/client/components/bg/shapes.js +501 -0
- package/client/components/bookmark-form/form-tabs.jsx +1 -0
- package/client/components/bookmark-form/local-form-ui.jsx +7 -1
- package/client/components/bookmark-form/render-bg.jsx +43 -0
- package/client/components/bookmark-form/serial-form-ui.jsx +7 -1
- package/client/components/bookmark-form/ssh-form-ui.jsx +14 -3
- package/client/components/bookmark-form/telnet-form-ui.jsx +7 -1
- package/client/components/bookmark-form/use-ui.jsx +68 -72
- package/client/components/common/ref.js +2 -0
- package/client/components/{sftp/confirm-modal-store.jsx → file-transfer/conflict-resolve.jsx} +86 -48
- package/client/components/file-transfer/transfer-queue.jsx +151 -0
- package/client/components/file-transfer/transfer.jsx +582 -0
- package/client/components/{sftp → file-transfer}/transports-action-store.jsx +35 -32
- package/client/components/{sftp → file-transfer}/transports-ui-store.jsx +2 -2
- package/client/components/main/main.jsx +25 -18
- package/client/components/main/wrapper.styl +16 -0
- package/client/components/profile/profile-list.jsx +1 -1
- package/client/components/quick-commands/qm.styl +4 -1
- package/client/components/quick-commands/quick-commands-list.jsx +16 -4
- package/client/components/setting-panel/list.jsx +1 -1
- package/client/components/setting-panel/setting-common.jsx +25 -23
- package/client/components/setting-panel/setting-terminal.jsx +2 -1
- package/client/components/setting-panel/terminal-bg-config.jsx +15 -2
- package/client/components/sftp/file-info-modal.jsx +3 -0
- package/client/components/sftp/file-item.jsx +25 -23
- package/client/components/sftp/file-read.js +1 -27
- package/client/components/sftp/list-table-ui.jsx +2 -2
- package/client/components/sidebar/transfer-history-modal.jsx +1 -1
- package/client/components/sidebar/transfer-list-control.jsx +1 -1
- package/client/components/sidebar/transport-ui.jsx +16 -9
- package/client/components/terminal/terminal.jsx +23 -1
- package/client/components/text-editor/simple-editor.jsx +164 -0
- package/client/components/text-editor/text-editor-form.jsx +6 -9
- package/client/css/includes/box.styl +2 -2
- package/client/store/tab.js +5 -1
- package/client/store/transfer-list.js +10 -51
- package/package.json +1 -1
- package/client/components/main/css-overwrite.jsx +0 -91
- package/client/components/sftp/transfer-conflict-store.jsx +0 -284
- package/client/components/sftp/transport-action-store.jsx +0 -422
- package/client/components/sftp/zip.js +0 -42
- /package/client/components/{main → bg}/custom-css.jsx +0 -0
- /package/client/components/{sftp → file-transfer}/transfer-speed-format.js +0 -0
- /package/client/components/{sftp → file-transfer}/transfer.styl +0 -0
|
@@ -7,15 +7,15 @@ import SettingModal from '../setting-panel/setting-modal'
|
|
|
7
7
|
import TextEditor from '../text-editor/text-editor'
|
|
8
8
|
import Sidebar from '../sidebar'
|
|
9
9
|
import BatchOp from '../batch-op/batch-op-entry'
|
|
10
|
-
import CssOverwrite from '
|
|
10
|
+
import CssOverwrite from '../bg/css-overwrite'
|
|
11
11
|
import UiTheme from './ui-theme'
|
|
12
|
-
import CustomCss from '
|
|
12
|
+
import CustomCss from '../bg/custom-css.jsx'
|
|
13
13
|
import Resolutions from '../rdp/resolution-edit'
|
|
14
14
|
import TerminalInteractive from '../terminal/terminal-interactive'
|
|
15
|
-
import ConfirmModalStore from '../
|
|
16
|
-
import
|
|
15
|
+
import ConfirmModalStore from '../file-transfer/conflict-resolve.jsx'
|
|
16
|
+
import TransferQueue from '../file-transfer/transfer-queue'
|
|
17
17
|
import TerminalCmdSuggestions from '../terminal/terminal-command-dropdown'
|
|
18
|
-
import TransportsActionStore from '../
|
|
18
|
+
import TransportsActionStore from '../file-transfer/transports-action-store.jsx'
|
|
19
19
|
import classnames from 'classnames'
|
|
20
20
|
import ShortcutControl from '../shortcuts/shortcut-control.jsx'
|
|
21
21
|
import { isMac, isWin } from '../../common/constants'
|
|
@@ -117,16 +117,26 @@ export default auto(function Index (props) {
|
|
|
117
117
|
const ext1 = {
|
|
118
118
|
className: cls
|
|
119
119
|
}
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
120
|
+
const bgTabs = config.terminalBackgroundImagePath === 'index' || config.terminalBackgroundImagePath === 'randomShape'
|
|
121
|
+
? store.getTabs()
|
|
122
|
+
: store.getTabs().filter(tab =>
|
|
123
|
+
tab.terminalBackground?.terminalBackgroundImagePath
|
|
124
|
+
)
|
|
125
|
+
const confsCss = {
|
|
126
|
+
...Object.keys(config)
|
|
127
|
+
.filter(d => d.startsWith('terminalBackground'))
|
|
128
|
+
.reduce((p, k) => ({
|
|
126
129
|
...p,
|
|
127
|
-
[k]:
|
|
130
|
+
[k]: config[k]
|
|
131
|
+
}), {}),
|
|
132
|
+
tabs: bgTabs.map(tab => {
|
|
133
|
+
return {
|
|
134
|
+
tabCount: tab.tabCount,
|
|
135
|
+
terminalBackground: tab.terminalBackground,
|
|
136
|
+
id: tab.id
|
|
128
137
|
}
|
|
129
|
-
}
|
|
138
|
+
})
|
|
139
|
+
}
|
|
130
140
|
const themeProps = {
|
|
131
141
|
themeConfig: store.getUiThemeConfig()
|
|
132
142
|
}
|
|
@@ -246,7 +256,7 @@ export default auto(function Index (props) {
|
|
|
246
256
|
<CustomCss customCss={config.customCss} />
|
|
247
257
|
<TextEditor />
|
|
248
258
|
<UpdateCheck
|
|
249
|
-
skipVersion={
|
|
259
|
+
skipVersion={config.skipVersion}
|
|
250
260
|
upgradeInfo={upgradeInfo}
|
|
251
261
|
installSrc={installSrc}
|
|
252
262
|
/>
|
|
@@ -265,10 +275,6 @@ export default auto(function Index (props) {
|
|
|
265
275
|
<ConfirmModalStore
|
|
266
276
|
transferToConfirm={transferToConfirm}
|
|
267
277
|
/>
|
|
268
|
-
<TransferConflictStore
|
|
269
|
-
{...conflictStoreProps}
|
|
270
|
-
transferToConfirm={transferToConfirm}
|
|
271
|
-
/>
|
|
272
278
|
<TransportsActionStore
|
|
273
279
|
{...conflictStoreProps}
|
|
274
280
|
config={config}
|
|
@@ -286,6 +292,7 @@ export default auto(function Index (props) {
|
|
|
286
292
|
/>
|
|
287
293
|
<ConnectionHoppingWarning {...warningProps} />
|
|
288
294
|
<TerminalCmdSuggestions {...cmdSuggestionsProps} />
|
|
295
|
+
<TransferQueue />
|
|
289
296
|
</div>
|
|
290
297
|
</ConfigProvider>
|
|
291
298
|
)
|
|
@@ -36,3 +36,19 @@
|
|
|
36
36
|
.loading-data
|
|
37
37
|
display none
|
|
38
38
|
|
|
39
|
+
#container
|
|
40
|
+
.session-batch-active
|
|
41
|
+
.xterm-screen
|
|
42
|
+
&::before
|
|
43
|
+
font-size 30vmin
|
|
44
|
+
font-weight bold
|
|
45
|
+
color alpha(text, 0.15)
|
|
46
|
+
display flex
|
|
47
|
+
justify-content center
|
|
48
|
+
align-items center
|
|
49
|
+
position absolute
|
|
50
|
+
top 0
|
|
51
|
+
left 0
|
|
52
|
+
right 0
|
|
53
|
+
bottom 0
|
|
54
|
+
z-index -1
|
|
@@ -38,12 +38,22 @@ export default class QuickCommandsList extends List {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
handleDragStart = e => {
|
|
41
|
-
|
|
41
|
+
const dragElement = e.target.closest('.item-list-unit')
|
|
42
|
+
if (dragElement) {
|
|
43
|
+
e.dataTransfer.setData('idDragged', dragElement.getAttribute('data-id'))
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
handleDragEnter = e => {
|
|
48
|
+
e.target.closest('.item-list-unit').classList.add('dragover')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
handleDragLeave = e => {
|
|
52
|
+
e.target.closest('.item-list-unit').classList.remove('dragover')
|
|
42
53
|
}
|
|
43
54
|
|
|
44
|
-
// adjust window.store.quickCommands array order when drop, so that the dragged item will be placed at the right position, e.target.getAttribute('data-id') would target item id, e.dataTransfer.getData('idDragged') would target dragged item id
|
|
45
55
|
handleDrop = e => {
|
|
46
|
-
onDrop(e)
|
|
56
|
+
onDrop(e, '.item-list-unit')
|
|
47
57
|
}
|
|
48
58
|
|
|
49
59
|
renderItem = (item, i) => {
|
|
@@ -65,7 +75,7 @@ export default class QuickCommandsList extends List {
|
|
|
65
75
|
)
|
|
66
76
|
return (
|
|
67
77
|
<div
|
|
68
|
-
key={
|
|
78
|
+
key={id}
|
|
69
79
|
className={cls}
|
|
70
80
|
onClick={() => this.onClickItem(item)}
|
|
71
81
|
data-id={id}
|
|
@@ -73,6 +83,8 @@ export default class QuickCommandsList extends List {
|
|
|
73
83
|
onDragOver={this.handleDragOver}
|
|
74
84
|
onDragStart={this.handleDragStart}
|
|
75
85
|
onDrop={this.handleDrop}
|
|
86
|
+
onDragEnter={this.handleDragEnter}
|
|
87
|
+
onDragLeave={this.handleDragLeave}
|
|
76
88
|
>
|
|
77
89
|
<div className='elli pd1y pd2x' title={name}>
|
|
78
90
|
{
|
|
@@ -587,30 +587,32 @@ export default class SettingCommon extends Component {
|
|
|
587
587
|
value={theme}
|
|
588
588
|
>
|
|
589
589
|
{
|
|
590
|
-
terminalThemes
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
<
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
590
|
+
terminalThemes
|
|
591
|
+
.filter(d => d.id && d.name && d.uiThemeConfig)
|
|
592
|
+
.map(l => {
|
|
593
|
+
const { id, name, uiThemeConfig } = l
|
|
594
|
+
const { main, text } = uiThemeConfig
|
|
595
|
+
const isDark = isColorDark(main)
|
|
596
|
+
const txt = isDark ? <MoonOutlined /> : <SunOutlined />
|
|
597
|
+
const tag = (
|
|
598
|
+
<Tag
|
|
599
|
+
color={main}
|
|
600
|
+
className='mg1l'
|
|
601
|
+
style={
|
|
602
|
+
{
|
|
603
|
+
color: text
|
|
604
|
+
}
|
|
602
605
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
)
|
|
613
|
-
})
|
|
606
|
+
>
|
|
607
|
+
{txt}
|
|
608
|
+
</Tag>
|
|
609
|
+
)
|
|
610
|
+
return (
|
|
611
|
+
<Option key={id} value={id}>
|
|
612
|
+
{tag} {name}
|
|
613
|
+
</Option>
|
|
614
|
+
)
|
|
615
|
+
})
|
|
614
616
|
}
|
|
615
617
|
</Select>
|
|
616
618
|
</div>
|
|
@@ -485,7 +485,8 @@ export default class SettingTerminal extends Component {
|
|
|
485
485
|
const bgProps = {
|
|
486
486
|
onChangeValue: this.onChangeValue,
|
|
487
487
|
name: 'terminalBackgroundImagePath',
|
|
488
|
-
config: this.props.config
|
|
488
|
+
config: this.props.config,
|
|
489
|
+
isGlobal: true
|
|
489
490
|
}
|
|
490
491
|
const tip = (
|
|
491
492
|
<div>
|
|
@@ -16,7 +16,8 @@ const e = window.translate
|
|
|
16
16
|
export default function TerminalBackgroundConfig ({
|
|
17
17
|
onChangeValue,
|
|
18
18
|
name,
|
|
19
|
-
config
|
|
19
|
+
config,
|
|
20
|
+
isGlobal = false
|
|
20
21
|
}) {
|
|
21
22
|
const value = config[name]
|
|
22
23
|
const defaultValue = defaultSettings[name]
|
|
@@ -42,6 +43,18 @@ export default function TerminalBackgroundConfig ({
|
|
|
42
43
|
desc: e('noTerminalBg')
|
|
43
44
|
}
|
|
44
45
|
]
|
|
46
|
+
if (isGlobal) {
|
|
47
|
+
dataSource.push(
|
|
48
|
+
{
|
|
49
|
+
value: 'index',
|
|
50
|
+
desc: e('index')
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
value: 'randomShape',
|
|
54
|
+
desc: e('randomCats')
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
}
|
|
45
58
|
const numberOpts = { step: 0.05, min: 0, max: 1, cls: 'bg-img-setting' }
|
|
46
59
|
|
|
47
60
|
function renderNumber (name, options, title = '', width = 136) {
|
|
@@ -75,7 +88,7 @@ export default function TerminalBackgroundConfig ({
|
|
|
75
88
|
}
|
|
76
89
|
|
|
77
90
|
const renderFilter = () => {
|
|
78
|
-
if (config[name] === noTerminalBgValue) return
|
|
91
|
+
if (config[name] === noTerminalBgValue || config[name] === 'index') return
|
|
79
92
|
|
|
80
93
|
return (
|
|
81
94
|
<div>
|
|
@@ -22,11 +22,12 @@ import wait from '../../common/wait'
|
|
|
22
22
|
import {
|
|
23
23
|
fileOperationsMap,
|
|
24
24
|
isWin, transferTypeMap, typeMap,
|
|
25
|
+
paneMap,
|
|
25
26
|
isMac, maxEditFileSize, ctrlOrCmd
|
|
26
27
|
} from '../../common/constants'
|
|
27
28
|
import findParent from '../../common/find-parent'
|
|
28
29
|
import sorter from '../../common/index-sorter'
|
|
29
|
-
import { getFolderFromFilePath, getLocalFileInfo
|
|
30
|
+
import { getFolderFromFilePath, getLocalFileInfo } from './file-read'
|
|
30
31
|
import { readClipboard, copy as copyToClipboard, hasFileInClipboardText } from '../../common/clipboard'
|
|
31
32
|
import fs from '../../common/fs'
|
|
32
33
|
import time from '../../common/time'
|
|
@@ -51,15 +52,15 @@ export default class FileSection extends React.Component {
|
|
|
51
52
|
super(props)
|
|
52
53
|
this.state = {
|
|
53
54
|
file: copy(props.file),
|
|
54
|
-
overwriteStrategy: ''
|
|
55
|
+
overwriteStrategy: '',
|
|
56
|
+
dropdownOpen: false
|
|
55
57
|
}
|
|
56
58
|
// Create ref
|
|
57
59
|
this.domRef = React.createRef()
|
|
60
|
+
this.id = 'file-' + this.props.file.id
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
componentDidMount () {
|
|
61
|
-
this.id = 'file-' + (this.props.file?.id || generate())
|
|
62
|
-
refs.add(this.id, this)
|
|
63
64
|
this.applyStyle()
|
|
64
65
|
}
|
|
65
66
|
|
|
@@ -73,7 +74,6 @@ export default class FileSection extends React.Component {
|
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
componentWillUnmount () {
|
|
76
|
-
refsStatic.remove(this.id)
|
|
77
77
|
clearTimeout(this.timer)
|
|
78
78
|
this.timer = null
|
|
79
79
|
this.domRef = null
|
|
@@ -81,10 +81,20 @@ export default class FileSection extends React.Component {
|
|
|
81
81
|
this.removeFileEditEvent()
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
clearRef = () => {
|
|
85
|
+
refs.remove(this.id)
|
|
86
|
+
}
|
|
87
|
+
|
|
84
88
|
get editor () {
|
|
85
89
|
return refsStatic.get('text-editor')
|
|
86
90
|
}
|
|
87
91
|
|
|
92
|
+
handleDropdownOpenChange = (open) => {
|
|
93
|
+
if (open) {
|
|
94
|
+
this.forceUpdate()
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
88
98
|
applyStyle = () => {
|
|
89
99
|
if (!this.domRef) {
|
|
90
100
|
return
|
|
@@ -511,6 +521,7 @@ export default class FileSection extends React.Component {
|
|
|
511
521
|
}
|
|
512
522
|
|
|
513
523
|
changeFileMode = async (file) => {
|
|
524
|
+
this.clearRef()
|
|
514
525
|
const { permission, type, path, name } = file
|
|
515
526
|
const func = type === typeMap.local
|
|
516
527
|
? fs.chmod
|
|
@@ -522,6 +533,7 @@ export default class FileSection extends React.Component {
|
|
|
522
533
|
|
|
523
534
|
openFileModeModal = () => {
|
|
524
535
|
const { type } = this.props
|
|
536
|
+
refs.add(this.id, this)
|
|
525
537
|
refsStatic.get('file-modal')?.showFileModeModal(
|
|
526
538
|
{
|
|
527
539
|
tab: this.props.tab,
|
|
@@ -611,6 +623,7 @@ export default class FileSection extends React.Component {
|
|
|
611
623
|
}
|
|
612
624
|
|
|
613
625
|
removeFileEditEvent = () => {
|
|
626
|
+
this.clearRef()
|
|
614
627
|
if (this.watchingFile) {
|
|
615
628
|
window.pre.ipcOffEvent('file-change', this.onFileChange)
|
|
616
629
|
window.pre.runGlobalAsync('unwatchFile', this.watchingFile)
|
|
@@ -659,15 +672,8 @@ export default class FileSection extends React.Component {
|
|
|
659
672
|
path, name
|
|
660
673
|
} = this.state.file
|
|
661
674
|
const rp = resolve(path, name)
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
document.querySelector('.session-current .term-sftp-tabs .type-tab.ssh')
|
|
665
|
-
).click()
|
|
666
|
-
this.timer = setTimeout(() => {
|
|
667
|
-
window.store.runQuickCommand(
|
|
668
|
-
`cd "${rp}"`
|
|
669
|
-
)
|
|
670
|
-
}, 500)
|
|
675
|
+
this.props.tab.pane = paneMap.terminal
|
|
676
|
+
refs.get('term-' + this.props.tab.id)?.cd(rp)
|
|
671
677
|
}
|
|
672
678
|
|
|
673
679
|
fetchEditorText = async (path, type) => {
|
|
@@ -698,6 +704,7 @@ export default class FileSection extends React.Component {
|
|
|
698
704
|
data.file = null
|
|
699
705
|
data.text = ''
|
|
700
706
|
}
|
|
707
|
+
this.clearRef()
|
|
701
708
|
this.editor?.setState(data)
|
|
702
709
|
if (r && !noClose) {
|
|
703
710
|
this.props[`${type}List`]()
|
|
@@ -705,6 +712,7 @@ export default class FileSection extends React.Component {
|
|
|
705
712
|
}
|
|
706
713
|
|
|
707
714
|
editFile = () => {
|
|
715
|
+
refs.add(this.id, this)
|
|
708
716
|
this.editor?.openEditor({
|
|
709
717
|
id: this.id,
|
|
710
718
|
file: this.state.file
|
|
@@ -741,7 +749,7 @@ export default class FileSection extends React.Component {
|
|
|
741
749
|
_typeTo,
|
|
742
750
|
operation
|
|
743
751
|
) => {
|
|
744
|
-
const { name, path, type
|
|
752
|
+
const { name, path, type } = file
|
|
745
753
|
const isLocal = type === typeMap.local
|
|
746
754
|
let typeTo = isLocal
|
|
747
755
|
? typeMap.remote
|
|
@@ -766,13 +774,6 @@ export default class FileSection extends React.Component {
|
|
|
766
774
|
...createTransferProps(this.props),
|
|
767
775
|
operation
|
|
768
776
|
}
|
|
769
|
-
if (isDirectory) {
|
|
770
|
-
const zip = await checkFolderSize(this.props, file)
|
|
771
|
-
Object.assign(obj, {
|
|
772
|
-
zip,
|
|
773
|
-
skipExpand: zip
|
|
774
|
-
})
|
|
775
|
-
}
|
|
776
777
|
return [obj]
|
|
777
778
|
}
|
|
778
779
|
|
|
@@ -1198,7 +1199,8 @@ export default class FileSection extends React.Component {
|
|
|
1198
1199
|
items: this.renderContextMenu(),
|
|
1199
1200
|
onClick: this.onContextMenu
|
|
1200
1201
|
},
|
|
1201
|
-
trigger: ['contextMenu']
|
|
1202
|
+
trigger: ['contextMenu'],
|
|
1203
|
+
onOpenChange: this.handleDropdownOpenChange
|
|
1202
1204
|
}
|
|
1203
1205
|
return (
|
|
1204
1206
|
<Dropdown {...ddProps}>
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import generate from '../../common/uid'
|
|
6
6
|
import fs from '../../common/fs'
|
|
7
|
-
import { isWin
|
|
8
|
-
import resolve from '../../common/resolve'
|
|
7
|
+
import { isWin } from '../../common/constants'
|
|
9
8
|
|
|
10
9
|
export const getFileExt = fileName => {
|
|
11
10
|
const sep = '.'
|
|
@@ -75,28 +74,3 @@ export const getRemoteFileInfo = async (sftp, filePath) => {
|
|
|
75
74
|
isDirectory: stat.isDirectory
|
|
76
75
|
}
|
|
77
76
|
}
|
|
78
|
-
|
|
79
|
-
export async function checkFolderSize (props, f) {
|
|
80
|
-
const pth = resolve(f.path, f.name)
|
|
81
|
-
const func = f.type === typeMap.remote
|
|
82
|
-
? props.sftp
|
|
83
|
-
: window.fs
|
|
84
|
-
const {
|
|
85
|
-
size,
|
|
86
|
-
count
|
|
87
|
-
} = await func.getFolderSize(pth)
|
|
88
|
-
.catch(err => {
|
|
89
|
-
console.log('get folder size fail', err)
|
|
90
|
-
return { size: 0, count: 0 }
|
|
91
|
-
})
|
|
92
|
-
if (count === 0) {
|
|
93
|
-
return true
|
|
94
|
-
}
|
|
95
|
-
if (size >= 600) {
|
|
96
|
-
return false
|
|
97
|
-
}
|
|
98
|
-
if (size / count >= 100) {
|
|
99
|
-
return false
|
|
100
|
-
}
|
|
101
|
-
return true
|
|
102
|
-
}
|
|
@@ -250,10 +250,10 @@ export default class FileListTable extends Component {
|
|
|
250
250
|
this.setState(this.initFromProps())
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
-
renderItem = (item
|
|
253
|
+
renderItem = (item) => {
|
|
254
254
|
const { type } = this.props
|
|
255
255
|
const cls = item.isParent ? 'parent-file-item' : 'real-file-item'
|
|
256
|
-
const key =
|
|
256
|
+
const key = item.id
|
|
257
257
|
return (
|
|
258
258
|
<FileSection
|
|
259
259
|
{...this.props.getFileProps(item, type)}
|
|
@@ -28,7 +28,7 @@ export default memo(function TransferHistoryModal (props) {
|
|
|
28
28
|
const {
|
|
29
29
|
clearTransferHistory
|
|
30
30
|
} = window.store
|
|
31
|
-
const transferHistory = props.transferHistory
|
|
31
|
+
const transferHistory = props.transferHistory
|
|
32
32
|
const columns = [{
|
|
33
33
|
title: e('startTime'),
|
|
34
34
|
dataIndex: 'startTime',
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from '@ant-design/icons'
|
|
13
13
|
import { action } from 'manate'
|
|
14
14
|
import { addClass, removeClass } from '../../common/class'
|
|
15
|
+
import { refsStatic } from '../common/ref'
|
|
15
16
|
import './transfer.styl'
|
|
16
17
|
|
|
17
18
|
const e = window.translate
|
|
@@ -38,19 +39,25 @@ export default function Transporter (props) {
|
|
|
38
39
|
const onDragCls = 'ondrag-tr'
|
|
39
40
|
const onDragOverCls = 'dragover-tr'
|
|
40
41
|
function moveToTop () {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
arr.unshift(item)
|
|
46
|
-
}
|
|
47
|
-
})()
|
|
42
|
+
refsStatic.get('transfer-queue')?.addToQueue(
|
|
43
|
+
'moveTop',
|
|
44
|
+
id
|
|
45
|
+
)
|
|
48
46
|
}
|
|
49
47
|
function cancel () {
|
|
50
|
-
|
|
48
|
+
refsStatic.get('transfer-queue')?.addToQueue(
|
|
49
|
+
'delete',
|
|
50
|
+
id
|
|
51
|
+
)
|
|
51
52
|
}
|
|
52
53
|
function handlePauseOrResume () {
|
|
53
|
-
|
|
54
|
+
refsStatic.get('transfer-queue')?.addToQueue(
|
|
55
|
+
'update',
|
|
56
|
+
id,
|
|
57
|
+
{
|
|
58
|
+
pausing: !pausing
|
|
59
|
+
}
|
|
60
|
+
)
|
|
54
61
|
}
|
|
55
62
|
|
|
56
63
|
function clearCls () {
|
|
@@ -11,7 +11,8 @@ import {
|
|
|
11
11
|
notification,
|
|
12
12
|
Spin,
|
|
13
13
|
Button,
|
|
14
|
-
Dropdown
|
|
14
|
+
Dropdown,
|
|
15
|
+
message
|
|
15
16
|
} from 'antd'
|
|
16
17
|
import classnames from 'classnames'
|
|
17
18
|
import './terminal.styl'
|
|
@@ -314,15 +315,31 @@ clear\r`
|
|
|
314
315
|
this.term.focus()
|
|
315
316
|
}
|
|
316
317
|
|
|
318
|
+
isUnsafeFilename = (filename) => {
|
|
319
|
+
return /["'\n\r]/.test(filename)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
cd = (p) => {
|
|
323
|
+
if (this.isUnsafeFilename(p)) {
|
|
324
|
+
return message.error('File name contains unsafe characters')
|
|
325
|
+
}
|
|
326
|
+
this.runQuickCommand(`cd "${p}"`)
|
|
327
|
+
}
|
|
328
|
+
|
|
317
329
|
onDrop = e => {
|
|
318
330
|
const dt = e.dataTransfer
|
|
319
331
|
const fromFile = dt.getData('fromFile')
|
|
332
|
+
const notSafeMsg = 'File name contains unsafe characters'
|
|
320
333
|
|
|
321
334
|
if (fromFile) {
|
|
322
335
|
// Handle SFTP file drop
|
|
323
336
|
try {
|
|
324
337
|
const fileData = JSON.parse(fromFile)
|
|
325
338
|
const filePath = resolve(fileData.path, fileData.name)
|
|
339
|
+
if (this.isUnsafeFilename(filePath)) {
|
|
340
|
+
message.error(notSafeMsg)
|
|
341
|
+
return
|
|
342
|
+
}
|
|
326
343
|
this.attachAddon._sendData(`"${filePath}" `)
|
|
327
344
|
return
|
|
328
345
|
} catch (e) {
|
|
@@ -333,6 +350,11 @@ clear\r`
|
|
|
333
350
|
// Handle regular file drop
|
|
334
351
|
const files = dt.files
|
|
335
352
|
if (files && files.length) {
|
|
353
|
+
const filesAll = Array.from(files).map(f => `"${f.path}"`).join(' ')
|
|
354
|
+
if (this.isUnsafeFilename(filesAll)) {
|
|
355
|
+
message.error(notSafeMsg)
|
|
356
|
+
return
|
|
357
|
+
}
|
|
336
358
|
this.attachAddon._sendData(
|
|
337
359
|
Array.from(files).map(f => `"${f.path}"`).join(' ')
|
|
338
360
|
)
|