@electerm/electerm-react 1.37.93 → 1.37.106

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.
@@ -37,7 +37,6 @@ export const contextMenuWidth = 280
37
37
  export const contextMenuPaddingTop = 10
38
38
  export const sftpControlHeight = 28 + 42 + 33 + 46
39
39
  export const sidebarWidth = 43
40
- export const sidebarPanelWidth = 300
41
40
  export const maxHistory = 50
42
41
  export const maxTransport = 5
43
42
  export const maxSftpHistory = 20
@@ -306,6 +305,7 @@ export const expandedKeysLsKey = 'expanded-keys'
306
305
  export const checkedKeysLsKey = 'checked-keys'
307
306
  export const quickCommandLabelsLsKey = 'quick-command-labels'
308
307
  export const localAddrBookmarkLsKey = 'local-addr-bookmark-keys'
308
+ export const dismissDelKeyTipLsKey = 'dismiss-del-key-tip'
309
309
  export const sshTunnelHelpLink = 'https://github.com/electerm/electerm/wiki/How-to-use-ssh-tunnel'
310
310
  export const batchOpHelpLink = 'https://github.com/electerm/electerm/wiki/batch-operation'
311
311
  export const proxyHelpLink = 'https://github.com/electerm/electerm/wiki/proxy-format'
@@ -33,6 +33,9 @@ export default function createTitle (res) {
33
33
 
34
34
  export function createTitleTag (obj) {
35
35
  const { color } = obj
36
+ if (!color) {
37
+ return null
38
+ }
36
39
  const styleTag = color
37
40
  ? { color }
38
41
  : {}
@@ -8,7 +8,7 @@ export default {
8
8
  scrollback: 3000,
9
9
  onStartSessions: [],
10
10
  fontSize: 16,
11
- fontFamily: 'mono, courier-new, courier, monospace',
11
+ fontFamily: 'Fira Code, mono, courier-new, courier, monospace',
12
12
  execWindows: 'System32/WindowsPowerShell/v1.0/powershell.exe',
13
13
  execMac: 'zsh',
14
14
  execLinux: 'bash',
@@ -42,5 +42,6 @@ export default {
42
42
  hideSshConfig: false,
43
43
  addTimeStampToTermLog: false,
44
44
  sftpPathFollowSsh: false,
45
- keepaliveInterval: 0
45
+ keepaliveInterval: 0,
46
+ backspaceMode: '^?'
46
47
  }
@@ -10,7 +10,8 @@ import {
10
10
  CloseSquareFilled,
11
11
  SearchOutlined,
12
12
  FullscreenOutlined,
13
- PaperClipOutlined
13
+ PaperClipOutlined,
14
+ CloseOutlined
14
15
  } from '@ant-design/icons'
15
16
  import {
16
17
  Tooltip
@@ -84,6 +85,7 @@ export default class SessionWrapper extends Component {
84
85
  sessionOptions: null,
85
86
  sessionId: generate(),
86
87
  terminals: terminals.slice(0, 1),
88
+ delKeyPressed: false,
87
89
  showInfo: false,
88
90
  infoPanelProps: {}
89
91
  }
@@ -94,6 +96,31 @@ export default class SessionWrapper extends Component {
94
96
  // this.initEvent()
95
97
  }
96
98
 
99
+ componentWillUnmount () {
100
+ clearTimeout(this.backspaceKeyPressedTimer)
101
+ }
102
+
103
+ onDelKeyPressed = () => {
104
+ this.setState({
105
+ delKeyPressed: true
106
+ })
107
+ this.backspaceKeyPressedTimer = setTimeout(() => {
108
+ this.setState({
109
+ delKeyPressed: false
110
+ })
111
+ }, 5000)
112
+ }
113
+
114
+ handleChangeDelMode = (backspaceMode) => {
115
+ this.setState({
116
+ backspaceMode
117
+ })
118
+ }
119
+
120
+ handleDismissDelKeyTip = () => {
121
+ window.store.dismissDelKeyTip()
122
+ }
123
+
97
124
  setCwd = (cwd, tid) => {
98
125
  this.setState(old => {
99
126
  return {
@@ -272,11 +299,10 @@ export default class SessionWrapper extends Component {
272
299
  infoPanelPinned,
273
300
  showInfo
274
301
  } = this.state
275
- if (!infoPanelPinned || !showInfo) {
276
- return this.props.width
277
- }
278
- const { rightSidebarWidth, width } = this.props
279
- return width - rightSidebarWidth
302
+ const { rightSidebarWidth, width, leftSidebarWidth, pinned, openedSideBar } = this.props
303
+ const rt = infoPanelPinned && showInfo ? rightSidebarWidth : 0
304
+ const lt = pinned && openedSideBar ? leftSidebarWidth : 0
305
+ return width - rt - lt - 42
280
306
  }
281
307
 
282
308
  renderTerminals = () => {
@@ -330,7 +356,8 @@ export default class SessionWrapper extends Component {
330
356
  'handleShowInfo',
331
357
  'onChangePane',
332
358
  'hideInfoPanel',
333
- 'setCwd'
359
+ 'setCwd',
360
+ 'onDelKeyPressed'
334
361
  ]),
335
362
  ...this.computePosition(t.position / 10)
336
363
  }
@@ -420,6 +447,21 @@ export default class SessionWrapper extends Component {
420
447
  )
421
448
  }
422
449
 
450
+ renderDelTip = (isSsh) => {
451
+ if (!isSsh || this.props.hideDelKeyTip || !this.state.delKeyPressed) {
452
+ return null
453
+ }
454
+ return (
455
+ <div className='type-tab'>
456
+ <span className='mg1r'>Try <b>Shift + Backspace</b>?</span>
457
+ <CloseOutlined
458
+ onClick={this.handleDismissDelKeyTip}
459
+ className='pointer'
460
+ />
461
+ </div>
462
+ )
463
+ }
464
+
423
465
  renderControl = () => {
424
466
  const { splitDirection, terminals, sftpPathFollowSsh } = this.state
425
467
  const { props } = this
@@ -497,6 +539,9 @@ export default class SessionWrapper extends Component {
497
539
  )
498
540
  : null
499
541
  }
542
+ {
543
+ this.renderDelTip(pane === paneMap.terminal)
544
+ }
500
545
  {
501
546
  pane === paneMap.terminal
502
547
  ? (
@@ -340,6 +340,7 @@ class Sessions extends Component {
340
340
  currentTabId,
341
341
  tab: toSimpleObj(tab),
342
342
  ...pick(store, [
343
+ 'hideDelKeyTip',
343
344
  'fileOperation',
344
345
  'file',
345
346
  'height',
@@ -349,7 +350,10 @@ class Sessions extends Component {
349
350
  'tabsHeight',
350
351
  'appPath',
351
352
  'topMenuHeight',
352
- 'rightSidebarWidth'
353
+ 'rightSidebarWidth',
354
+ 'leftSidebarWidth',
355
+ 'pinned',
356
+ 'openedSideBar'
353
357
  ]),
354
358
  config,
355
359
  ...pick(this, [
@@ -410,7 +414,7 @@ class Sessions extends Component {
410
414
 
411
415
  renderSessionsWrap = () => {
412
416
  const { leftSidebarWidth, openedSideBar } = this.props.store
413
- const w = leftSidebarWidth + 43
417
+ const w = leftSidebarWidth + 42
414
418
  const ptp = openedSideBar
415
419
  ? {
416
420
  className: 'sessions',
@@ -70,6 +70,9 @@ export default class SettingTerminal extends Component {
70
70
  })
71
71
  }
72
72
 
73
+ handleChangeDelMode = v => this.onChangeValue(v, 'backspaceMode')
74
+ handleChangeRenderType = v => this.onChangeValue(v, 'renderType')
75
+
73
76
  handleChangeFont = (values) => {
74
77
  this.onChangeValue(
75
78
  values.join(', '),
@@ -401,6 +404,7 @@ export default class SettingTerminal extends Component {
401
404
  }
402
405
  const {
403
406
  rendererType,
407
+ backspaceMode = '^?',
404
408
  keywords = [{ color: 'red' }]
405
409
  } = this.props.config
406
410
  const {
@@ -436,7 +440,7 @@ export default class SettingTerminal extends Component {
436
440
  <div className='pd2b'>
437
441
  <span className='inline-title mg1r'>{e('rendererType')}</span>
438
442
  <Select
439
- onChange={v => this.onChangeValue(v, 'rendererType')}
443
+ onChange={this.handleChangeRenderType}
440
444
  value={rendererType}
441
445
  popupMatchSelectWidth={false}
442
446
  >
@@ -501,6 +505,20 @@ export default class SettingTerminal extends Component {
501
505
  'ctrlOrMetaOpenTerminalLink'
502
506
  ].map(this.renderToggle)
503
507
  }
508
+ <div className='pd1b'>{e('terminalBackSpaceMode')}</div>
509
+ <Select
510
+ onChange={this.handleChangeDelMode}
511
+ value={backspaceMode}
512
+ popupMatchSelectWidth={false}
513
+ >
514
+ {
515
+ ['^?', '^H'].map(id => {
516
+ return (
517
+ <Option key={id} value={id}>{id}</Option>
518
+ )
519
+ })
520
+ }
521
+ </Select>
504
522
  {this.renderReset()}
505
523
  </div>
506
524
  )
@@ -13,33 +13,33 @@ class ShortcutControl extends React.PureComponent {
13
13
  window.addEventListener('mousewheel', this.handleKeyboardEvent.bind(this))
14
14
  }
15
15
 
16
- prevTabShortcut = (e) => {
16
+ prevTabShortcut = throttle((e) => {
17
17
  e.stopPropagation()
18
18
  window.store.clickPrevTab()
19
- }
19
+ }, 500)
20
20
 
21
- nextTabShortcut = (e) => {
21
+ nextTabShortcut = throttle((e) => {
22
22
  e.stopPropagation()
23
23
  window.store.clickNextTab()
24
- }
24
+ }, 500)
25
25
 
26
- newBookmarkShortcut = (e) => {
26
+ newBookmarkShortcut = throttle((e) => {
27
27
  e.stopPropagation()
28
28
  window.store.onNewSsh()
29
- }
29
+ }, 500)
30
30
 
31
- togglefullscreenShortcut = (e) => {
31
+ togglefullscreenShortcut = throttle((e) => {
32
32
  e.stopPropagation()
33
33
  const x = document.querySelector('.term-fullscreen-control') ||
34
34
  document.querySelector('.session-current .term-fullscreen-control1')
35
35
  x && x.click()
36
- }
36
+ }, 500)
37
37
 
38
- splitShortcut = (e) => {
38
+ splitShortcut = throttle((e) => {
39
39
  e.stopPropagation()
40
40
  const x = document.querySelector('.session-current .icon-split')
41
41
  x && x.click()
42
- }
42
+ }, 1000)
43
43
 
44
44
  zoominShortcut = throttle((e) => {
45
45
  e.stopPropagation()
@@ -3,7 +3,6 @@ import shortcutsDefaultsGen from './shortcuts-defaults.js'
3
3
  import {
4
4
  isMacJs
5
5
  } from '../../common/constants'
6
- import { throttle } from 'lodash-es'
7
6
 
8
7
  function buildConfig (config, filter = d => d) {
9
8
  const defs = shortcutsDefaultsGen().filter(filter)
@@ -46,7 +45,7 @@ function buildConfigForSearch (config) {
46
45
  }
47
46
 
48
47
  export function shortcutExtend (Cls) {
49
- Cls.prototype.handleKeyboardEvent = throttle(function (event) {
48
+ Cls.prototype.handleKeyboardEvent = function (event) {
50
49
  const {
51
50
  code,
52
51
  ctrlKey,
@@ -57,28 +56,24 @@ export function shortcutExtend (Cls) {
57
56
  type,
58
57
  key
59
58
  } = event
60
- if (key === 'Backspace' && this.isTerm && type === 'keydown') {
61
- const now = Date.now()
62
- if (!this.lastTimePressDel) {
63
- this.lastTimePressDel = now
64
- }
65
- const timer = now - this.lastTimePressDel
66
- let count = Math.ceil(timer / 800)
67
- if (count <= 0) {
68
- count = 1
69
- }
70
- let char = String.fromCharCode(
71
- shiftKey ? 127 : 8
72
- )
73
- console.log('char1', JSON.stringify(char), count)
74
- char = new Array(count).fill(char).join('')
75
- console.log('char', JSON.stringify(char))
76
- this.socket.send(
77
- char
78
- )
59
+ if (
60
+ this.term &&
61
+ key === 'Backspace' &&
62
+ type === 'keydown' &&
63
+ !altKey &&
64
+ !ctrlKey
65
+ ) {
66
+ this.props.onDelKeyPressed()
67
+ const delKey = this.props.config.backspaceMode === '^?' ? 8 : 127
68
+ const altDelDelKey = delKey === 8 ? 127 : 8
69
+ const char = String.fromCharCode(shiftKey ? delKey : altDelDelKey)
70
+ this.socket.send(char)
79
71
  return false
80
- } else if (key === 'Backspace' && this.isTerm && type === 'keyup') {
81
- delete this.lastTimePressDel
72
+ } else if (
73
+ this.term &&
74
+ this.term.buffer.active.type === 'alternate'
75
+ ) {
76
+ return true
82
77
  }
83
78
  const codeName = event instanceof window.WheelEvent
84
79
  ? (wheelDeltaY > 0 ? 'mouseWheelUp' : 'mouseWheelDown')
@@ -103,14 +98,15 @@ export function shortcutExtend (Cls) {
103
98
  if (conf.shortcut.split(',').includes(r)) {
104
99
  if (this[funcName]) {
105
100
  return this[funcName](event)
106
- } else if (this.isTerm && conf.readonly) {
101
+ } else if (this.term && conf.readonly) {
107
102
  return true
108
103
  } else {
109
104
  return false
110
105
  }
111
106
  }
112
107
  }
113
- }, 300)
108
+ return !!this.term
109
+ }
114
110
  return Cls
115
111
  }
116
112
 
@@ -19,6 +19,7 @@ export default class SidePanel extends PureComponent {
19
19
  nw = 600
20
20
  }
21
21
  this.props.setLeftSidePanelWidth(nw)
22
+ window.store.onResize()
22
23
  window.removeEventListener('mouseup', this.handleMouseup)
23
24
  window.removeEventListener('mousemove', this.handleMousemove)
24
25
  }
@@ -5,10 +5,11 @@ export default function AppDrag (props) {
5
5
  const {
6
6
  target
7
7
  } = e
8
+ const { classList = [] } = target || {}
8
9
  if (
9
- target instanceof window.SVGElement ||
10
- target.classList.contains('tab-title') ||
11
- target.classList.contains('ant-tooltip-inner')
10
+ !classList.contains('app-drag') &&
11
+ !classList.contains('tabs-inner') &&
12
+ !classList.contains('tabs-wrapper')
12
13
  ) {
13
14
  window.pre.runSync('windowMove', false)
14
15
  return false
@@ -17,6 +18,7 @@ export default function AppDrag (props) {
17
18
  }
18
19
 
19
20
  function onMouseDown (e) {
21
+ e.stopPropagation()
20
22
  if (canOperate(e)) {
21
23
  window.pre.runSync('windowMove', true)
22
24
  }
@@ -27,8 +29,9 @@ export default function AppDrag (props) {
27
29
  }
28
30
 
29
31
  function onDoubleClick (e) {
32
+ e.stopPropagation()
30
33
  if (!canOperate(e)) {
31
- return window.pre.runSync('windowMove', false)
34
+ return
32
35
  }
33
36
  const {
34
37
  isMaximized
@@ -49,6 +52,7 @@ export default function AppDrag (props) {
49
52
  onMouseDown={onMouseDown}
50
53
  onMouseUp={onMouseUp}
51
54
  onDoubleClick={onDoubleClick}
55
+ onMouseLeave={onMouseUp}
52
56
  >
53
57
  {props.children}
54
58
  </div>
@@ -240,7 +240,7 @@ export default class Tabs extends React.Component {
240
240
  ? '100%'
241
241
  : tabsWidthAll
242
242
  const style = {
243
- width: width - windowControlWidth - 86
243
+ width: width - windowControlWidth - 136
244
244
  }
245
245
  return (
246
246
  <div
@@ -76,8 +76,6 @@ class Term extends Component {
76
76
  }
77
77
  }
78
78
 
79
- isTerm = true
80
-
81
79
  componentDidMount () {
82
80
  this.initTerminal()
83
81
  this.initEvt()
@@ -261,16 +259,6 @@ class Term extends Component {
261
259
  this.openNormalBuffer()
262
260
  }
263
261
 
264
- prevTabShortcut = throttle((e) => {
265
- e.stopPropagation()
266
- window.store.clickPrevTab()
267
- }, 300)
268
-
269
- nextTabShortcut = throttle((e) => {
270
- e.stopPropagation()
271
- window.store.clickNextTab()
272
- }, 300)
273
-
274
262
  handleEvent = (e) => {
275
263
  const {
276
264
  keyword,
@@ -748,11 +736,6 @@ class Term extends Component {
748
736
  })
749
737
  }, 1000)
750
738
 
751
- // onSocketData = (a) => {
752
- // console.log('onSocketData', a)
753
- // runIdle(this.notifyOnData)
754
- // }
755
-
756
739
  parse (rawText) {
757
740
  let result = ''
758
741
  const len = rawText.length
@@ -110,7 +110,7 @@ export default class TerminalInfoContent extends PureComponent {
110
110
  draggable: false,
111
111
  style: {
112
112
  width: props.rightSidebarWidth,
113
- top: props.topMenuHeight + props.tabsHeight + termControlHeight - 4
113
+ top: props.topMenuHeight + props.tabsHeight + termControlHeight
114
114
  }
115
115
  }
116
116
  return (
@@ -2,6 +2,7 @@ import { render } from 'react-dom'
2
2
  import 'antd/dist/reset.css'
3
3
  import 'xterm/css/xterm.css'
4
4
  import '../common/trzsz'
5
+ import 'firacode/distr/fira_code.css'
5
6
  import Main from '../components/main/index.jsx'
6
7
  import { notification } from 'antd'
7
8
  notification.config({
@@ -10,7 +10,8 @@ import {
10
10
  tabActions,
11
11
  modals,
12
12
  leftSidebarWidthKey,
13
- rightSidebarWidthKey
13
+ rightSidebarWidthKey,
14
+ dismissDelKeyTipLsKey
14
15
  } from '../common/constants'
15
16
  import * as ls from '../common/safe-local-storage'
16
17
 
@@ -150,4 +151,8 @@ export default Store => {
150
151
  ls.setItem(rightSidebarWidthKey, v)
151
152
  window.store.rightSidebarWidth = v
152
153
  }
154
+ Store.prototype.dismissDelKeyTip = function (v) {
155
+ ls.setItem(dismissDelKeyTipLsKey, 'y')
156
+ window.store.hideDelKeyTip = true
157
+ }
153
158
  }
@@ -31,8 +31,6 @@ import { uniq } from 'lodash-es'
31
31
  import copy from 'json-deep-copy'
32
32
  import {
33
33
  settingMap,
34
- sidebarWidth,
35
- sidebarPanelWidth,
36
34
  paneMap,
37
35
  settingSyncId,
38
36
  settingShortcutsId,
@@ -93,8 +91,7 @@ class Store {
93
91
  }
94
92
 
95
93
  get width () {
96
- return window.store.innerWidth - sidebarWidth -
97
- (window.store.pinned ? sidebarPanelWidth : 0)
94
+ return window.store.innerWidth
98
95
  }
99
96
 
100
97
  get currentQuickCommands () {
@@ -226,7 +223,7 @@ class Store {
226
223
  }
227
224
 
228
225
  get topMenuHeight () {
229
- return window.store.config.useSystemTitleBar ? 0 : 15
226
+ return 0
230
227
  }
231
228
 
232
229
  get tabsHeight () {
@@ -17,14 +17,15 @@ import {
17
17
  checkedKeysLsKey,
18
18
  localAddrBookmarkLsKey,
19
19
  leftSidebarWidthKey,
20
- rightSidebarWidthKey
20
+ rightSidebarWidthKey,
21
+ dismissDelKeyTipLsKey
21
22
  } from '../common/constants'
22
23
  import { buildDefaultThemes, buildNewTheme } from '../common/terminal-theme'
23
24
  import * as ls from '../common/safe-local-storage'
24
25
 
25
26
  const { prefix } = window
26
27
  const t = prefix('terminalThemes')
27
- const e = prefix('control')
28
+ const e = prefix('common')
28
29
  const newQuickCommand = 'newQuickCommand'
29
30
  const q = prefix('quickCommands')
30
31
 
@@ -185,6 +186,7 @@ export default () => {
185
186
  innerWidth: window.innerWidth,
186
187
  height: 500,
187
188
  isMaximized: window.pre.runSync('isMaximized'),
188
- terminalFullScreen: false
189
+ terminalFullScreen: false,
190
+ hideDelKeyTip: ls.getItem(dismissDelKeyTipLsKey) === 'y'
189
191
  }
190
192
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "1.37.93",
3
+ "version": "1.37.106",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",