@electerm/electerm-react 1.38.83 → 1.39.2

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 (31) hide show
  1. package/client/common/constants.js +4 -1
  2. package/client/common/default-setting.js +1 -0
  3. package/client/components/bookmark-form/bookmark-form.styl +8 -3
  4. package/client/components/bookmark-form/form-ssh-common.jsx +23 -13
  5. package/client/components/bookmark-form/index.jsx +6 -2
  6. package/client/components/bookmark-form/rdp-form-ui.jsx +140 -0
  7. package/client/components/bookmark-form/rdp-form.jsx +16 -0
  8. package/client/components/bookmark-form/ssh-form.jsx +5 -8
  9. package/client/components/bookmark-form/web-form-ui.jsx +1 -1
  10. package/client/components/footer/footer-entry.jsx +7 -1
  11. package/client/components/main/main.jsx +3 -0
  12. package/client/components/session/code-scan.js +155 -0
  13. package/client/components/session/rdp-session.jsx +434 -0
  14. package/client/components/session/resolution-edit.jsx +63 -0
  15. package/client/components/session/resolution-form.jsx +134 -0
  16. package/client/components/session/resolutions.js +110 -0
  17. package/client/components/session/session.jsx +40 -5
  18. package/client/components/session/session.styl +4 -1
  19. package/client/components/session/sessions.jsx +1 -0
  20. package/client/components/setting-panel/setting-common.jsx +1 -0
  21. package/client/components/sftp/file-props-modal.jsx +1 -1
  22. package/client/components/sftp/sftp-entry.jsx +2 -1
  23. package/client/entry/rle.js +2 -0
  24. package/client/entry/rle.wasm +0 -0
  25. package/client/store/common.js +5 -0
  26. package/client/store/index.js +2 -1
  27. package/client/store/init-state.js +4 -1
  28. package/client/store/load-data.js +1 -1
  29. package/client/store/watch.js +6 -0
  30. package/client/views/index.pug +4 -0
  31. package/package.json +1 -1
@@ -67,7 +67,8 @@ export const connectionMap = buildConst([
67
67
  'telnet',
68
68
  'serial',
69
69
  'local',
70
- 'web'
70
+ 'web',
71
+ 'rdp'
71
72
  ])
72
73
 
73
74
  export const authTypeMap = buildConst([
@@ -133,6 +134,7 @@ export const terminalSplitDirectionMap = buildConst([
133
134
 
134
135
  export const terminalSshConfigType = 'ssh-config'
135
136
  export const terminalWebType = 'web'
137
+ export const terminalRdpType = 'rdp'
136
138
  export const terminalSerialType = 'serial'
137
139
  export const terminalTelnetType = 'telnet'
138
140
  export const terminalLocalType = 'local'
@@ -306,6 +308,7 @@ export const mirrors = {
306
308
  }
307
309
  export const downloadUpgradeTimeout = 20000
308
310
  export const expandedKeysLsKey = 'expanded-keys'
311
+ export const resolutionsLsKey = 'custom-resolution-key'
309
312
  export const checkedKeysLsKey = 'checked-keys'
310
313
  export const quickCommandLabelsLsKey = 'quick-command-labels'
311
314
  export const localAddrBookmarkLsKey = 'local-addr-bookmark-keys'
@@ -44,6 +44,7 @@ export default {
44
44
  sftpPathFollowSsh: false,
45
45
  keepaliveInterval: 0,
46
46
  backspaceMode: '^?',
47
+ showHiddenFilesOnSftpStart: true,
47
48
  terminalInfos: [
48
49
  'uptime',
49
50
  'cpu',
@@ -1,5 +1,3 @@
1
- .dns-section
2
- line-height 34px
3
1
  .mg24b
4
2
  margin-bottom 24px
5
3
  .mg60b
@@ -7,4 +5,11 @@
7
5
  .compact-input input
8
6
  width 80px !important
9
7
  .ssh-tunnels-host
10
- margin-bottom 0
8
+ margin-bottom 0
9
+ .ip-item
10
+ line-height 34px
11
+ .item-item-use
12
+ display none
13
+ .ip-item:hover
14
+ .item-item-use
15
+ display inline-block
@@ -37,11 +37,31 @@ export default function renderCommon (props) {
37
37
  const {
38
38
  autofocustrigger,
39
39
  bookmarkGroups = [],
40
- dns,
40
+ ips,
41
41
  form,
42
42
  onChangeAuthType
43
43
  } = props
44
44
  const tree = formatBookmarkGroups(bookmarkGroups)
45
+
46
+ // ips is ipaddress string[]
47
+ function renderIps () {
48
+ return ips.map(ip => {
49
+ return (
50
+ <div
51
+ key={ip}
52
+ className='iblock mg2r pointer ip-item'
53
+ onClick={() => props.useIp(form, ip)}
54
+ >
55
+ <b>{ip}</b>
56
+ <span
57
+ className='mg1l item-item-use'
58
+ >
59
+ {e('use')}
60
+ </span>
61
+ </div>
62
+ )
63
+ })
64
+ }
45
65
  return (
46
66
  <div>
47
67
  <FormItem
@@ -56,18 +76,8 @@ export default function renderCommon (props) {
56
76
  normalize={props.trim}
57
77
  >
58
78
  {
59
- dns
60
- ? (
61
- <div className='dns-section'>
62
- ip: {dns}
63
- <span
64
- className='color-blue pointer mg1l'
65
- onClick={() => props.useIp(form)}
66
- >
67
- {e('use')}
68
- </span>
69
- </div>
70
- )
79
+ ips.length
80
+ ? renderIps()
71
81
  : (
72
82
  <div className='dns-section'>
73
83
  hostname or ip
@@ -10,6 +10,7 @@ import {
10
10
  connectionMap,
11
11
  terminalSerialType,
12
12
  terminalWebType,
13
+ terminalRdpType,
13
14
  terminalLocalType,
14
15
  terminalTelnetType,
15
16
  newBookmarkIdPrefix
@@ -19,6 +20,7 @@ import SerialForm from './serial-form'
19
20
  import LocalForm from './local-form'
20
21
  import TelnetForm from './telnet-form'
21
22
  import WebForm from './web-form'
23
+ import RdpForm from './rdp-form'
22
24
  import { createTitleWithTag } from '../../common/create-title'
23
25
  import {
24
26
  LoadingOutlined,
@@ -40,7 +42,8 @@ export default class BookmarkIndex extends Component {
40
42
  terminalTelnetType,
41
43
  terminalWebType,
42
44
  terminalLocalType,
43
- terminalSerialType
45
+ terminalSerialType,
46
+ terminalRdpType
44
47
  ].includes(initType)
45
48
  ) {
46
49
  initType = connectionMap.ssh
@@ -68,7 +71,8 @@ export default class BookmarkIndex extends Component {
68
71
  [connectionMap.telnet]: TelnetForm,
69
72
  [connectionMap.serial]: SerialForm,
70
73
  [connectionMap.local]: LocalForm,
71
- [connectionMap.web]: WebForm
74
+ [connectionMap.web]: WebForm,
75
+ [connectionMap.rdp]: RdpForm
72
76
  }
73
77
 
74
78
  handleChange = (e) => {
@@ -0,0 +1,140 @@
1
+ /**
2
+ * web form
3
+ */
4
+
5
+ import { useEffect } from 'react'
6
+ import {
7
+ Input,
8
+ Form,
9
+ InputNumber
10
+ } from 'antd'
11
+ import { formItemLayout } from '../../common/form-layout'
12
+ import {
13
+ newBookmarkIdPrefix,
14
+ terminalRdpType
15
+ } from '../../common/constants'
16
+ import useSubmit from './use-submit'
17
+ import copy from 'json-deep-copy'
18
+ import { defaults } from 'lodash-es'
19
+ import { ColorPickerItem } from './color-picker-item.jsx'
20
+ import { getRandomDefaultColor } from '../../common/rand-hex-color.js'
21
+
22
+ const FormItem = Form.Item
23
+ const { prefix } = window
24
+ const e = prefix('form')
25
+
26
+ export default function LocalFormUi (props) {
27
+ const [
28
+ form,
29
+ handleFinish,
30
+ submitUi
31
+ ] = useSubmit(props)
32
+ useEffect(() => {
33
+ if (props.formData.id.startsWith(newBookmarkIdPrefix)) {
34
+ form.setFieldsValue({
35
+ category: props.currentBookmarkGroupId
36
+ })
37
+ }
38
+ }, [props.currentBookmarkGroupId])
39
+ let initialValues = copy(props.formData)
40
+ const defaultValues = {
41
+ type: terminalRdpType,
42
+ port: 3389,
43
+ color: getRandomDefaultColor()
44
+ }
45
+ initialValues = defaults(initialValues, defaultValues)
46
+ function renderCommon () {
47
+ return (
48
+ <div className='pd1x'>
49
+ <FormItem
50
+ {...formItemLayout}
51
+ label={e('title')}
52
+ hasFeedback
53
+ >
54
+ <FormItem noStyle name='title'>
55
+ <Input addonBefore={<ColorPickerItem />} />
56
+ </FormItem>
57
+ </FormItem>
58
+ <FormItem
59
+ {...formItemLayout}
60
+ label={e('host')}
61
+ hasFeedback
62
+ name='host'
63
+ required
64
+ >
65
+ <Input />
66
+ </FormItem>
67
+ <FormItem
68
+ {...formItemLayout}
69
+ label={e('port')}
70
+ hasFeedback
71
+ name='port'
72
+ rules={[{
73
+ required: true, message: 'port required'
74
+ }]}
75
+ >
76
+ <InputNumber
77
+ placeholder={e('port')}
78
+ min={1}
79
+ max={65535}
80
+ step={1}
81
+ />
82
+ </FormItem>
83
+ <FormItem
84
+ {...formItemLayout}
85
+ label={e('username')}
86
+ hasFeedback
87
+ name='username'
88
+ required
89
+ >
90
+ <Input />
91
+ </FormItem>
92
+ <FormItem
93
+ {...formItemLayout}
94
+ label={e('password')}
95
+ hasFeedback
96
+ name='password'
97
+ required
98
+ >
99
+ <Input.Password />
100
+ </FormItem>
101
+ <FormItem
102
+ {...formItemLayout}
103
+ label={e('description')}
104
+ name='description'
105
+ hasFeedback
106
+ >
107
+ <Input.TextArea rows={1} />
108
+ </FormItem>
109
+ <FormItem
110
+ {...formItemLayout}
111
+ label={e('domain')}
112
+ hasFeedback
113
+ name='domain'
114
+ >
115
+ <Input />
116
+ </FormItem>
117
+ <FormItem
118
+ {...formItemLayout}
119
+ label='type'
120
+ name='type'
121
+ className='hide'
122
+ >
123
+ <Input />
124
+ </FormItem>
125
+ </div>
126
+ )
127
+ }
128
+
129
+ return (
130
+ <Form
131
+ form={form}
132
+ onFinish={handleFinish}
133
+ initialValues={initialValues}
134
+ name='rdp-form'
135
+ >
136
+ {renderCommon()}
137
+ {submitUi}
138
+ </Form>
139
+ )
140
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * bookmark form
3
+ */
4
+ import BookmarkForm from './ssh-form'
5
+ import RdpFormUi from './rdp-form-ui'
6
+
7
+ export default class WebForm extends BookmarkForm {
8
+ render () {
9
+ return (
10
+ <RdpFormUi
11
+ {...this.props}
12
+ {...this.getProps()}
13
+ />
14
+ )
15
+ }
16
+ }
@@ -24,19 +24,16 @@ import newTerm from '../../common/new-terminal'
24
24
  export default class BookmarkForm extends PureComponent {
25
25
  state = {
26
26
  testing: false,
27
- dns: ''
27
+ ips: []
28
28
  }
29
29
 
30
30
  trim = (v) => {
31
31
  return (v || '').replace(/^\s+|\s+$/g, '')
32
32
  }
33
33
 
34
- useIp = (form) => {
34
+ useIp = (form, ip) => {
35
35
  form.setFieldsValue({
36
- host: this.state.dns
37
- })
38
- this.setState({
39
- dns: ''
36
+ host: ip
40
37
  })
41
38
  }
42
39
 
@@ -76,12 +73,12 @@ export default class BookmarkForm extends PureComponent {
76
73
  ) {
77
74
  return
78
75
  }
79
- const ip = await window.pre.runGlobalAsync('lookup', value)
76
+ const ips = await window.pre.runGlobalAsync('lookup', value)
80
77
  .catch(err => {
81
78
  log.debug(err)
82
79
  })
83
80
  this.setState({
84
- dns: ip || ''
81
+ ips: ips || []
85
82
  })
86
83
  }
87
84
 
@@ -87,7 +87,7 @@ export default function LocalFormUi (props) {
87
87
  form={form}
88
88
  onFinish={handleFinish}
89
89
  initialValues={initialValues}
90
- name='local-form'
90
+ name='web-form'
91
91
  >
92
92
  {renderCommon()}
93
93
  {submitUi}
@@ -119,7 +119,13 @@ export default class SystemMenu extends Component {
119
119
  render () {
120
120
  const { tabs, leftSidebarWidth, openedSideBar } = this.props.store
121
121
  const pane = this.props.store.currentTab?.pane
122
- if (pane === paneMap.fileManager || !tabs.length) {
122
+ const type = this.props.store.currentTab?.type
123
+ if (
124
+ type === 'rdp' ||
125
+ type === 'web' ||
126
+ pane === paneMap.fileManager ||
127
+ !tabs.length
128
+ ) {
123
129
  return null
124
130
  }
125
131
  const w = 43 + leftSidebarWidth
@@ -11,6 +11,7 @@ import BatchOp from '../batch-op/batch-op'
11
11
  import CssOverwrite from './css-overwrite'
12
12
  import UiTheme from './ui-theme'
13
13
  import CustomCss from './custom-css.jsx'
14
+ import Resolutions from '../session/resolution-edit'
14
15
  import TerminalInteractive from '../terminal/terminal-interactive'
15
16
  import ConfirmModalStore from '../sftp/confirm-modal-store.jsx'
16
17
  import TransferConflictStore from '../sftp/transfer-conflict-store.jsx'
@@ -61,6 +62,7 @@ export default class Index extends Component {
61
62
  store.isSencondInstance = window.pre.runSync('isSencondInstance')
62
63
  store.initData()
63
64
  store.checkForDbUpgrade()
65
+ window.pre.runGlobalAsync('registerDeepLink')
64
66
  }
65
67
 
66
68
  render () {
@@ -163,6 +165,7 @@ export default class Index extends Component {
163
165
  store={store}
164
166
  _fileTransfers={store._fileTransfers}
165
167
  />
168
+ <Resolutions store={store} />
166
169
  </div>
167
170
  </ConfigProvider>
168
171
  )
@@ -0,0 +1,155 @@
1
+ // from https://raw.githubusercontent.com/citronneur/mstsc.js/client/js/keyboard.js
2
+ const KeyMap = {
3
+ '': 0x0000,
4
+ Escape: 0x0001,
5
+ Digit1: 0x0002,
6
+ Digit2: 0x0003,
7
+ Digit3: 0x0004,
8
+ Digit4: 0x0005,
9
+ Digit5: 0x0006,
10
+ Digit6: 0x0007,
11
+ Digit7: 0x0008,
12
+ Digit8: 0x0009,
13
+ Digit9: 0x000A,
14
+ Digit0: 0x000B,
15
+ Minus: 0x000C,
16
+ Equal: 0x000D,
17
+ Backspace: 0x000E,
18
+ Tab: 0x000F,
19
+ KeyQ: 0x0010,
20
+ KeyW: 0x0011,
21
+ KeyE: 0x0012,
22
+ KeyR: 0x0013,
23
+ KeyT: 0x0014,
24
+ KeyY: 0x0015,
25
+ KeyU: 0x0016,
26
+ KeyI: 0x0017,
27
+ KeyO: 0x0018,
28
+ KeyP: 0x0019,
29
+ BracketLeft: 0x001A,
30
+ BracketRight: 0x001B,
31
+ Enter: 0x001C,
32
+ ControlLeft: 0x001D,
33
+ KeyA: 0x001E,
34
+ KeyS: 0x001F,
35
+ KeyD: 0x0020,
36
+ KeyF: 0x0021,
37
+ KeyG: 0x0022,
38
+ KeyH: 0x0023,
39
+ KeyJ: 0x0024,
40
+ KeyK: 0x0025,
41
+ KeyL: 0x0026,
42
+ Semicolon: 0x0027,
43
+ Quote: 0x0028,
44
+ Backquote: 0x0029,
45
+ ShiftLeft: 0x002A,
46
+ Backslash: 0x002B,
47
+ KeyZ: 0x002C,
48
+ KeyX: 0x002D,
49
+ KeyC: 0x002E,
50
+ KeyV: 0x002F,
51
+ KeyB: 0x0030,
52
+ KeyN: 0x0031,
53
+ KeyM: 0x0032,
54
+ Comma: 0x0033,
55
+ Period: 0x0034,
56
+ Slash: 0x0035,
57
+ ShiftRight: 0x0036,
58
+ NumpadMultiply: 0x0037,
59
+ AltLeft: 0x0038,
60
+ Space: 0x0039,
61
+ CapsLock: 0x003A,
62
+ F1: 0x003B,
63
+ F2: 0x003C,
64
+ F3: 0x003D,
65
+ F4: 0x003E,
66
+ F5: 0x003F,
67
+ F6: 0x0040,
68
+ F7: 0x0041,
69
+ F8: 0x0042,
70
+ F9: 0x0043,
71
+ F10: 0x0044,
72
+ Pause: 0x0045,
73
+ ScrollLock: 0x0046,
74
+ Numpad7: 0x0047,
75
+ Numpad8: 0x0048,
76
+ Numpad9: 0x0049,
77
+ NumpadSubtract: 0x004A,
78
+ Numpad4: 0x004B,
79
+ Numpad5: 0x004C,
80
+ Numpad6: 0x004D,
81
+ NumpadAdd: 0x004E,
82
+ Numpad1: 0x004F,
83
+ Numpad2: 0x0050,
84
+ Numpad3: 0x0051,
85
+ Numpad0: 0x0052,
86
+ NumpadDecimal: 0x0053,
87
+ PrintScreen: 0x0054,
88
+ IntlBackslash: 0x0056,
89
+ F11: 0x0057,
90
+ F12: 0x0058,
91
+ NumpadEqual: 0x0059,
92
+ F13: 0x0064,
93
+ F14: 0x0065,
94
+ F15: 0x0066,
95
+ F16: 0x0067,
96
+ F17: 0x0068,
97
+ F18: 0x0069,
98
+ F19: 0x006A,
99
+ F20: 0x006B,
100
+ F21: 0x006C,
101
+ F22: 0x006D,
102
+ F23: 0x006E,
103
+ KanaMode: 0x0070,
104
+ Lang2: 0x0071,
105
+ Lang1: 0x0072,
106
+ IntlRo: 0x0073,
107
+ F24: 0x0076,
108
+ Convert: 0x0079,
109
+ NonConvert: 0x007B,
110
+ IntlYen: 0x007D,
111
+ NumpadComma: 0x007E,
112
+ MediaTrackPrevious: 0xE010,
113
+ MediaTrackNext: 0xE019,
114
+ NumpadEnter: 0xE01C,
115
+ ControlRight: 0xE01D,
116
+ VolumeMute: 0xE020,
117
+ LaunchApp2: 0xE021,
118
+ MediaPlayPause: 0xE022,
119
+ MediaStop: 0xE024,
120
+ VolumeDown: 0xE02E,
121
+ VolumeUp: 0xE030,
122
+ BrowserHome: 0xE032,
123
+ NumpadDivide: 0xE035,
124
+ // PrintScreen: 0xE037,
125
+ AltRight: 0xE038,
126
+ NumLock: 0xE045,
127
+ // Pause: 0xE046,
128
+ Home: 0xE047,
129
+ ArrowUp: 0xE048,
130
+ PageUp: 0xE049,
131
+ ArrowLeft: 0xE04B,
132
+ ArrowRight: 0xE04D,
133
+ End: 0xE04F,
134
+ ArrowDown: 0xE050,
135
+ PageDown: 0xE051,
136
+ Insert: 0xE052,
137
+ Delete: 0xE053,
138
+ OSLeft: 0xE05B,
139
+ OSRight: 0xE05C,
140
+ ContextMenu: 0xE05D,
141
+ Power: 0xE05E,
142
+ BrowserSearch: 0xE065,
143
+ BrowserFavorites: 0xE066,
144
+ BrowserRefresh: 0xE067,
145
+ BrowserStop: 0xE068,
146
+ BrowserForward: 0xE069,
147
+ BrowserBack: 0xE06A,
148
+ LaunchApp1: 0xE06B,
149
+ LaunchMail: 0xE06C,
150
+ MediaSelect: 0xE06D
151
+ }
152
+
153
+ export default function scancode (e) {
154
+ return KeyMap[e.code]
155
+ }