@electerm/electerm-react 1.72.6 → 1.72.16

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.
@@ -64,5 +64,6 @@ export default {
64
64
  roleAI: '终端专家,提供不同系统下命令,简要解释用法,用markdown格式',
65
65
  apiPathAI: '/chat/completions',
66
66
  sessionLogPath: '',
67
- sshSftpSplitView: false
67
+ sshSftpSplitView: false,
68
+ showCmdSuggestions: false
68
69
  }
@@ -19,6 +19,15 @@ export default function renderEnableSftp () {
19
19
  >
20
20
  <Switch />
21
21
  </FormItem>,
22
+ <FormItem
23
+ {...formItemLayout}
24
+ label='SFTP'
25
+ name='enableSftp'
26
+ key='sftp'
27
+ valuePropName='checked'
28
+ >
29
+ <Switch />
30
+ </FormItem>,
22
31
  <FormItem
23
32
  {...formItemLayout}
24
33
  label={e('ignoreKeyboardInteractive')}
@@ -65,6 +65,7 @@ export default function BookmarkFormUI (props) {
65
65
  encode: encodes[0],
66
66
  envLang: defaultEnvLang,
67
67
  enableSsh: true,
68
+ enableSftp: true,
68
69
  sshTunnels: [],
69
70
  runScripts: [{}],
70
71
  category: initBookmarkGroupId,
@@ -237,6 +237,9 @@ export default class BookmarkForm extends PureComponent {
237
237
  }
238
238
 
239
239
  handleSubmit = async (evt, res, isTest = false) => {
240
+ if (res.enableSsh === false && res.enableSftp === false) {
241
+ return message.warning('SSH and SFTP all disabled')
242
+ }
240
243
  const obj = {
241
244
  ...this.props.formData,
242
245
  ...res
@@ -3,21 +3,90 @@
3
3
  */
4
4
  import {
5
5
  Switch,
6
- Form
6
+ Form,
7
+ Select
7
8
  } from 'antd'
8
9
  import { formItemLayout } from '../../common/form-layout'
9
10
 
10
11
  const FormItem = Form.Item
12
+ const { Option } = Select
13
+
14
+ // Available cipher options from ssh2-alg.js
15
+ const cipherOptions = [
16
+ 'aes128-ctr',
17
+ 'aes192-ctr',
18
+ 'aes256-ctr',
19
+ 'aes128-gcm',
20
+ 'aes128-gcm@openssh.com',
21
+ 'aes256-gcm',
22
+ 'aes256-gcm@openssh.com',
23
+ 'aes256-cbc',
24
+ 'aes192-cbc',
25
+ 'aes128-cbc',
26
+ 'blowfish-cbc',
27
+ '3des-cbc',
28
+ 'arcfour256',
29
+ 'arcfour128',
30
+ 'cast128-cbc',
31
+ 'arcfour',
32
+ 'chacha20-poly1305@openssh.com',
33
+ 'umac-128-etm@openssh.com',
34
+ 'curve25519-sha256@libssh.org'
35
+ ]
36
+
37
+ // Available serverHostKey options from ssh2-alg.js
38
+ const serverHostKeyOptions = [
39
+ 'ssh-rsa',
40
+ 'ssh-ed25519',
41
+ 'ecdsa-sha2-nistp256',
42
+ 'ecdsa-sha2-nistp384',
43
+ 'ecdsa-sha2-nistp521',
44
+ 'ssh-dss',
45
+ 'rsa-sha2-512',
46
+ 'rsa-sha2-256'
47
+ ]
11
48
 
12
49
  export default function renderX11 () {
13
50
  return (
14
- <FormItem
15
- {...formItemLayout}
16
- label='x11'
17
- name='x11'
18
- valuePropName='checked'
19
- >
20
- <Switch />
21
- </FormItem>
51
+ <>
52
+ <FormItem
53
+ {...formItemLayout}
54
+ label='cipher'
55
+ name='cipher'
56
+ >
57
+ <Select
58
+ mode='multiple'
59
+ >
60
+ {cipherOptions.map(cipher => (
61
+ <Option key={cipher} value={cipher}>
62
+ {cipher}
63
+ </Option>
64
+ ))}
65
+ </Select>
66
+ </FormItem>
67
+ <FormItem
68
+ {...formItemLayout}
69
+ label='serverHostKey'
70
+ name='serverHostKey'
71
+ >
72
+ <Select
73
+ mode='multiple'
74
+ >
75
+ {serverHostKeyOptions.map(key => (
76
+ <Option key={key} value={key}>
77
+ {key}
78
+ </Option>
79
+ ))}
80
+ </Select>
81
+ </FormItem>
82
+ <FormItem
83
+ {...formItemLayout}
84
+ label='x11'
85
+ name='x11'
86
+ valuePropName='checked'
87
+ >
88
+ <Switch />
89
+ </FormItem>
90
+ </>
22
91
  )
23
92
  }
@@ -180,7 +180,8 @@ export default auto(function Layout (props) {
180
180
  'openedSideBar',
181
181
  'config'
182
182
  ]),
183
- tabs: store.tabs
183
+ tabs: store.tabs,
184
+ layout
184
185
  }
185
186
  return [
186
187
  <Layouts {...layoutProps} key='layouts'>
@@ -30,7 +30,8 @@ import {
30
30
  terminalRdpType,
31
31
  terminalVncType,
32
32
  terminalWebType,
33
- terminalTelnetType
33
+ terminalTelnetType,
34
+ splitMap
34
35
  } from '../../common/constants'
35
36
  import { SplitViewIcon } from '../icons/split-view'
36
37
  import { refs } from '../common/ref'
@@ -73,6 +74,19 @@ export default class SessionWrapper extends Component {
73
74
  return this.domRef.current
74
75
  }
75
76
 
77
+ isDisabled = () => {
78
+ const { enableSsh, enableSftp } = this.props.tab
79
+ return enableSsh === false || enableSftp === false
80
+ }
81
+
82
+ isSshDisabled = () => {
83
+ return this.props.tab.enableSsh === false
84
+ }
85
+
86
+ isSftpDisabled = () => {
87
+ return this.props.tab.enableSftp === false
88
+ }
89
+
76
90
  handleSshSftpSplitView = () => {
77
91
  const nv = !this.props.tab.sshSftpSplitView
78
92
  this.editTab({
@@ -84,10 +98,9 @@ export default class SessionWrapper extends Component {
84
98
  canSplitView = () => {
85
99
  const {
86
100
  width,
87
- height,
88
- tab
101
+ height
89
102
  } = this.props
90
- if (tab.enableSsh === false) {
103
+ if (this.isDisabled()) {
91
104
  return false
92
105
  }
93
106
  return width > this.minWithForSplit ||
@@ -419,7 +432,8 @@ export default class SessionWrapper extends Component {
419
432
  } = this.state
420
433
  const { pane, id, sshSftpSplitView } = this.props.tab
421
434
  if (
422
- this.isNotTerminalType()
435
+ this.isNotTerminalType() ||
436
+ this.isSftpDisabled()
423
437
  ) {
424
438
  return null
425
439
  }
@@ -506,6 +520,12 @@ export default class SessionWrapper extends Component {
506
520
  }
507
521
 
508
522
  renderBroadcastIcon = () => {
523
+ if (
524
+ this.props.layout === splitMap.c1 ||
525
+ this.isSshDisabled()
526
+ ) {
527
+ return null
528
+ }
509
529
  const { broadcastInput } = this.state
510
530
  const title = e('broadcastInput')
511
531
  const iconProps = {
@@ -571,6 +591,9 @@ export default class SessionWrapper extends Component {
571
591
  const {
572
592
  sshSftpSplitView
573
593
  } = this.props.tab
594
+ if (this.isDisabled()) {
595
+ return null
596
+ }
574
597
  if (sshSftpSplitView && this.canSplitView()) {
575
598
  return null
576
599
  }
@@ -626,6 +649,9 @@ export default class SessionWrapper extends Component {
626
649
  }
627
650
 
628
651
  renderSftpPathFollowControl = () => {
652
+ if (this.isDisabled()) {
653
+ return null
654
+ }
629
655
  const {
630
656
  sftpPathFollowSsh
631
657
  } = this.state
@@ -62,6 +62,7 @@ export default class Sessions extends Component {
62
62
  }
63
63
  const sessProps = {
64
64
  activeTabId,
65
+ layout: this.props.layout,
65
66
  tab,
66
67
  width,
67
68
  height,
@@ -594,7 +594,8 @@ export default class SettingTerminal extends Component {
594
594
  'copyWhenSelect',
595
595
  'ctrlOrMetaOpenTerminalLink',
596
596
  'sftpPathFollowSsh',
597
- 'sshSftpSplitView'
597
+ 'sshSftpSplitView',
598
+ 'showCmdSuggestions'
598
599
  ].map(d => this.renderToggle(d))
599
600
  }
600
601
  <div className='pd1b'>{e('terminalBackSpaceMode')}</div>
@@ -336,7 +336,7 @@ export default class FileSection extends React.Component {
336
336
  const { name, path } = file
337
337
  const info = await getLocalFileInfo(
338
338
  resolve(path, name)
339
- )
339
+ ).catch(console.log)
340
340
  if (info) {
341
341
  res.push(info)
342
342
  }
@@ -43,25 +43,20 @@ export const getFolderFromFilePath = (filePath, isRemote) => {
43
43
  }
44
44
 
45
45
  export const getLocalFileInfo = async (filePath) => {
46
- try {
47
- const statr = await fs.statAsync(filePath)
48
- const stat = await fs.lstatAsync(filePath)
49
- return {
50
- size: stat.size,
51
- accessTime: stat.atime,
52
- modifyTime: stat.mtime,
53
- mode: stat.mode,
54
- owner: stat.uid,
55
- group: stat.gid,
56
- type: 'local',
57
- ...getFolderFromFilePath(filePath, false),
58
- id: generate(),
59
- isDirectory: statr.isDirectory,
60
- isSymbolicLink: stat.isSymbolicLink
61
- }
62
- } catch (e) {
63
- log.debug(e)
64
- return null
46
+ const statr = await fs.statAsync(filePath)
47
+ const stat = await fs.lstatAsync(filePath)
48
+ return {
49
+ size: stat.size,
50
+ accessTime: stat.atime,
51
+ modifyTime: stat.mtime,
52
+ mode: stat.mode,
53
+ owner: stat.uid,
54
+ group: stat.gid,
55
+ type: 'local',
56
+ ...getFolderFromFilePath(filePath, false),
57
+ id: generate(),
58
+ isDirectory: statr.isDirectory,
59
+ isSymbolicLink: stat.isSymbolicLink
65
60
  }
66
61
  }
67
62
 
@@ -736,7 +736,7 @@ export default class Sftp extends Component {
736
736
  const local = []
737
737
  for (const name of locals) {
738
738
  const p = resolve(localPath, name)
739
- const fileObj = await getLocalFileInfo(p)
739
+ const fileObj = await getLocalFileInfo(p).catch(console.log)
740
740
  if (fileObj) {
741
741
  local.push(fileObj)
742
742
  }
@@ -39,7 +39,7 @@ export default class TransferConflictStore extends PureComponent {
39
39
  }
40
40
 
41
41
  localCheckExist = (path) => {
42
- return getLocalFileInfo(path)
42
+ return getLocalFileInfo(path).catch(console.log)
43
43
  }
44
44
 
45
45
  remoteCheckExist = (path, sessionId) => {
@@ -190,10 +190,10 @@ export default class TerminalCmdSuggestions extends Component {
190
190
  this.closeSuggestions()
191
191
  }
192
192
 
193
- processCommands = (commands, type, uniqueCommands, res) => {
193
+ processCommands = (commands = [], type, uniqueCommands, res) => {
194
194
  const { cmd } = this.state
195
195
  commands
196
- .filter(command => command.startsWith(cmd))
196
+ .filter(command => command && command.startsWith(cmd))
197
197
  .forEach(command => {
198
198
  if (!uniqueCommands.has(command)) {
199
199
  uniqueCommands.add(command)
@@ -75,10 +75,7 @@ class Term extends Component {
75
75
  componentDidMount () {
76
76
  this.initTerminal()
77
77
  if (this.props.tab.enableSsh === false) {
78
- ;(
79
- document.querySelector('.session-current .term-sftp-tabs .type-tab.sftp') ||
80
- document.querySelector('.session-current .term-sftp-tabs .type-tab.fileManager')
81
- ).click()
78
+ this.props.tab.pane = paneMap.fileManager
82
79
  }
83
80
  }
84
81
 
@@ -560,7 +557,7 @@ clear\r`
560
557
  }
561
558
  const r = []
562
559
  for (const filePath of files) {
563
- const stat = await getLocalFileInfo(filePath)
560
+ const stat = await getLocalFileInfo(filePath).catch(console.log)
564
561
  r.push({ ...stat, filePath })
565
562
  }
566
563
  return r
@@ -867,9 +864,11 @@ clear\r`
867
864
  if (!d.includes('\r')) {
868
865
  delete this.userTypeExit
869
866
  const cursorPos = this.getCursorPosition()
870
- refsStatic
871
- .get('terminal-suggestions')
872
- ?.openSuggestions(cursorPos, data)
867
+ if (this.props.config.showCmdSuggestions && data.length > 1) {
868
+ refsStatic
869
+ .get('terminal-suggestions')
870
+ ?.openSuggestions(cursorPos, data)
871
+ }
873
872
  } else {
874
873
  this.closeSuggestions()
875
874
  if (this.term.buffer.active.type !== 'alternate') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "1.72.6",
3
+ "version": "1.72.16",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",