@electerm/electerm-react 1.38.86 → 1.39.5

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 (34) hide show
  1. package/client/common/constants.js +6 -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 +175 -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 +32 -2
  10. package/client/components/footer/footer-entry.jsx +7 -1
  11. package/client/components/main/main.jsx +3 -0
  12. package/client/components/rdp/code-scan.js +155 -0
  13. package/client/components/rdp/rdp-session.jsx +439 -0
  14. package/client/components/rdp/resolution-edit.jsx +63 -0
  15. package/client/components/rdp/resolution-form.jsx +134 -0
  16. package/client/components/rdp/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 +2 -1
  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/components/terminal/index.jsx +7 -0
  24. package/client/components/terminal/term-search.jsx +12 -0
  25. package/client/entry/rle.js +2 -0
  26. package/client/entry/rle.wasm +0 -0
  27. package/client/store/common.js +5 -0
  28. package/client/store/index.js +2 -1
  29. package/client/store/init-state.js +4 -1
  30. package/client/store/load-data.js +1 -1
  31. package/client/store/watch.js +6 -0
  32. package/client/views/index.pug +4 -0
  33. package/package.json +1 -1
  34. /package/client/components/{session → web}/web-session.jsx +0 -0
@@ -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'
@@ -236,6 +238,7 @@ export const terminalActions = {
236
238
  openTerminalSearch: 'open-terminal-search',
237
239
  doSearchNext: 'do-search-next',
238
240
  doSearchPrev: 'do-search-prev',
241
+ clearSearch: 'clear-search',
239
242
  zoom: 'zoom-terminal'
240
243
  }
241
244
  export const fileActions = {
@@ -306,6 +309,7 @@ export const mirrors = {
306
309
  }
307
310
  export const downloadUpgradeTimeout = 20000
308
311
  export const expandedKeysLsKey = 'expanded-keys'
312
+ export const resolutionsLsKey = 'custom-resolution-key'
309
313
  export const checkedKeysLsKey = 'checked-keys'
310
314
  export const quickCommandLabelsLsKey = 'quick-command-labels'
311
315
  export const localAddrBookmarkLsKey = 'local-addr-bookmark-keys'
@@ -314,6 +318,7 @@ export const sshTunnelHelpLink = 'https://github.com/electerm/electerm/wiki/How-
314
318
  export const batchOpHelpLink = 'https://github.com/electerm/electerm/wiki/batch-operation'
315
319
  export const proxyHelpLink = 'https://github.com/electerm/electerm/wiki/proxy-format'
316
320
  export const regexHelpLink = 'https://github.com/electerm/electerm/wiki/Terminal-keywords-highlight-regular-expression-exmaples'
321
+ export const rdpHelpLink = 'https://github.com/electerm/electerm/wiki/RDP-limitation'
317
322
  export const modals = {
318
323
  hide: 0,
319
324
  setting: 1,
@@ -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,175 @@
1
+ /**
2
+ * web form
3
+ */
4
+
5
+ import { useEffect } from 'react'
6
+ import {
7
+ Input,
8
+ Form,
9
+ InputNumber,
10
+ TreeSelect
11
+ } from 'antd'
12
+ import { formItemLayout } from '../../common/form-layout'
13
+ import {
14
+ newBookmarkIdPrefix,
15
+ terminalRdpType,
16
+ rdpHelpLink
17
+ } from '../../common/constants'
18
+ import useSubmit from './use-submit'
19
+ import copy from 'json-deep-copy'
20
+ import Link from '../common/external-link.jsx'
21
+ import { defaults } from 'lodash-es'
22
+ import { ColorPickerItem } from './color-picker-item.jsx'
23
+ import { getRandomDefaultColor } from '../../common/rand-hex-color.js'
24
+ import formatBookmarkGroups from './bookmark-group-tree-format'
25
+ import findBookmarkGroupId from '../../common/find-bookmark-group-id'
26
+
27
+ const FormItem = Form.Item
28
+ const { prefix } = window
29
+ const e = prefix('form')
30
+ const c = prefix('common')
31
+
32
+ export default function LocalFormUi (props) {
33
+ const [
34
+ form,
35
+ handleFinish,
36
+ submitUi
37
+ ] = useSubmit(props)
38
+ useEffect(() => {
39
+ if (props.formData.id.startsWith(newBookmarkIdPrefix)) {
40
+ form.setFieldsValue({
41
+ category: props.currentBookmarkGroupId
42
+ })
43
+ }
44
+ }, [props.currentBookmarkGroupId])
45
+ const {
46
+ id = ''
47
+ } = props.formData
48
+ const {
49
+ bookmarkGroups = [],
50
+ currentBookmarkGroupId
51
+ } = props
52
+ let initialValues = copy(props.formData)
53
+ const initBookmarkGroupId = !id.startsWith(newBookmarkIdPrefix)
54
+ ? findBookmarkGroupId(bookmarkGroups, id)
55
+ : currentBookmarkGroupId
56
+ const defaultValues = {
57
+ type: terminalRdpType,
58
+ port: 3389,
59
+ category: initBookmarkGroupId,
60
+ color: getRandomDefaultColor()
61
+ }
62
+ initialValues = defaults(initialValues, defaultValues)
63
+ function renderCommon () {
64
+ const {
65
+ bookmarkGroups = []
66
+ } = props
67
+ const tree = formatBookmarkGroups(bookmarkGroups)
68
+ return (
69
+ <div className='pd1x'>
70
+ <p className='alignright'>
71
+ <Link to={rdpHelpLink}>Wiki: {rdpHelpLink}</Link>
72
+ </p>
73
+ <FormItem
74
+ {...formItemLayout}
75
+ label={e('title')}
76
+ hasFeedback
77
+ >
78
+ <FormItem noStyle name='title'>
79
+ <Input addonBefore={<ColorPickerItem />} />
80
+ </FormItem>
81
+ </FormItem>
82
+ <FormItem
83
+ {...formItemLayout}
84
+ label={e('host')}
85
+ hasFeedback
86
+ name='host'
87
+ required
88
+ >
89
+ <Input />
90
+ </FormItem>
91
+ <FormItem
92
+ {...formItemLayout}
93
+ label={e('port')}
94
+ hasFeedback
95
+ name='port'
96
+ rules={[{
97
+ required: true, message: 'port required'
98
+ }]}
99
+ >
100
+ <InputNumber
101
+ placeholder={e('port')}
102
+ min={1}
103
+ max={65535}
104
+ step={1}
105
+ />
106
+ </FormItem>
107
+ <FormItem
108
+ {...formItemLayout}
109
+ label={e('username')}
110
+ hasFeedback
111
+ name='username'
112
+ required
113
+ >
114
+ <Input />
115
+ </FormItem>
116
+ <FormItem
117
+ {...formItemLayout}
118
+ label={e('password')}
119
+ hasFeedback
120
+ name='password'
121
+ required
122
+ >
123
+ <Input.Password />
124
+ </FormItem>
125
+ <FormItem
126
+ {...formItemLayout}
127
+ label={e('description')}
128
+ name='description'
129
+ hasFeedback
130
+ >
131
+ <Input.TextArea rows={1} />
132
+ </FormItem>
133
+ <FormItem
134
+ {...formItemLayout}
135
+ label={e('domain')}
136
+ hasFeedback
137
+ name='domain'
138
+ >
139
+ <Input />
140
+ </FormItem>
141
+ <FormItem
142
+ {...formItemLayout}
143
+ label={c('bookmarkCategory')}
144
+ name='category'
145
+ >
146
+ <TreeSelect
147
+ treeData={tree}
148
+ treeDefaultExpandAll
149
+ showSearch
150
+ />
151
+ </FormItem>
152
+ <FormItem
153
+ {...formItemLayout}
154
+ label='type'
155
+ name='type'
156
+ className='hide'
157
+ >
158
+ <Input />
159
+ </FormItem>
160
+ </div>
161
+ )
162
+ }
163
+
164
+ return (
165
+ <Form
166
+ form={form}
167
+ onFinish={handleFinish}
168
+ initialValues={initialValues}
169
+ name='rdp-form'
170
+ >
171
+ {renderCommon()}
172
+ {submitUi}
173
+ </Form>
174
+ )
175
+ }
@@ -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
 
@@ -5,7 +5,8 @@
5
5
  import { useEffect } from 'react'
6
6
  import {
7
7
  Input,
8
- Form
8
+ Form,
9
+ TreeSelect
9
10
  } from 'antd'
10
11
  import { formItemLayout } from '../../common/form-layout'
11
12
  import {
@@ -17,10 +18,13 @@ import copy from 'json-deep-copy'
17
18
  import { defaults } from 'lodash-es'
18
19
  import { ColorPickerItem } from './color-picker-item.jsx'
19
20
  import { getRandomDefaultColor } from '../../common/rand-hex-color.js'
21
+ import formatBookmarkGroups from './bookmark-group-tree-format'
22
+ import findBookmarkGroupId from '../../common/find-bookmark-group-id'
20
23
 
21
24
  const FormItem = Form.Item
22
25
  const { prefix } = window
23
26
  const e = prefix('form')
27
+ const c = prefix('common')
24
28
 
25
29
  export default function LocalFormUi (props) {
26
30
  const [
@@ -35,13 +39,28 @@ export default function LocalFormUi (props) {
35
39
  })
36
40
  }
37
41
  }, [props.currentBookmarkGroupId])
42
+ const {
43
+ id = ''
44
+ } = props.formData
45
+ const {
46
+ bookmarkGroups = [],
47
+ currentBookmarkGroupId
48
+ } = props
49
+ const initBookmarkGroupId = !id.startsWith(newBookmarkIdPrefix)
50
+ ? findBookmarkGroupId(bookmarkGroups, id)
51
+ : currentBookmarkGroupId
38
52
  let initialValues = copy(props.formData)
39
53
  const defaultValues = {
40
54
  type: terminalWebType,
55
+ category: initBookmarkGroupId,
41
56
  color: getRandomDefaultColor()
42
57
  }
43
58
  initialValues = defaults(initialValues, defaultValues)
44
59
  function renderCommon () {
60
+ const {
61
+ bookmarkGroups = []
62
+ } = props
63
+ const tree = formatBookmarkGroups(bookmarkGroups)
45
64
  return (
46
65
  <div className='pd1x'>
47
66
  <FormItem
@@ -70,6 +89,17 @@ export default function LocalFormUi (props) {
70
89
  >
71
90
  <Input.TextArea rows={1} />
72
91
  </FormItem>
92
+ <FormItem
93
+ {...formItemLayout}
94
+ label={c('bookmarkCategory')}
95
+ name='category'
96
+ >
97
+ <TreeSelect
98
+ treeData={tree}
99
+ treeDefaultExpandAll
100
+ showSearch
101
+ />
102
+ </FormItem>
73
103
  <FormItem
74
104
  {...formItemLayout}
75
105
  label='type'
@@ -87,7 +117,7 @@ export default function LocalFormUi (props) {
87
117
  form={form}
88
118
  onFinish={handleFinish}
89
119
  initialValues={initialValues}
90
- name='local-form'
120
+ name='web-form'
91
121
  >
92
122
  {renderCommon()}
93
123
  {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 '../rdp/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
+ }