@electerm/electerm-react 3.15.186 → 3.15.187

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.
@@ -78,5 +78,6 @@ export default {
78
78
  startDirectoryLocal: '',
79
79
  allowMultiInstance: false,
80
80
  disableDeveloperTool: false,
81
- dragDropBehavior: 'ask'
81
+ dragDropBehavior: 'ask',
82
+ switchTabOnHover: false
82
83
  }
@@ -603,6 +603,7 @@ export default class SettingCommon extends Component {
603
603
  'hideIP',
604
604
  'allowMultiInstance',
605
605
  'disableDeveloperTool',
606
+ 'switchTabOnHover',
606
607
  'debug'
607
608
  ].map(this.renderToggle)
608
609
  }
@@ -121,6 +121,21 @@ class Tab extends Component {
121
121
  window.store.clickTab(this.props.tab.id, this.props.batch)
122
122
  }
123
123
 
124
+ onMouseEnter = () => {
125
+ const {
126
+ tab,
127
+ batch,
128
+ currentBatchTabId
129
+ } = this.props
130
+ if (document.querySelector('.' + onDragCls)) {
131
+ return
132
+ }
133
+ if (tab.id === currentBatchTabId) {
134
+ return
135
+ }
136
+ window.store.clickTab(tab.id, batch)
137
+ }
138
+
124
139
  onDrag = () => {
125
140
  addClass(this.tabRef.current, onDragCls)
126
141
  }
@@ -441,7 +456,8 @@ class Tab extends Component {
441
456
  const {
442
457
  isLast,
443
458
  tab,
444
- currentBatchTabId
459
+ currentBatchTabId,
460
+ config
445
461
  } = this.props
446
462
  const {
447
463
  id,
@@ -499,6 +515,7 @@ class Tab extends Component {
499
515
  data-id={id}
500
516
  {...pick(this, [
501
517
  'onDrag',
518
+ ...(config && config.switchTabOnHover ? ['onMouseEnter'] : []),
502
519
  'onDragEnter',
503
520
  'onDragExit',
504
521
  'onDragLeave',
@@ -668,6 +668,7 @@ class Term extends Component {
668
668
  // long-press detection here.
669
669
  longPressTimer = null
670
670
  touchStartPos = null
671
+ longPressFired = false
671
672
  longPressThreshold = 500 // ms
672
673
  longPressMoveTolerance = 10 // px
673
674
 
@@ -681,6 +682,7 @@ class Term extends Component {
681
682
  clientY: touch.clientY,
682
683
  target: e.currentTarget
683
684
  }
685
+ this.longPressFired = false
684
686
  clearTimeout(this.longPressTimer)
685
687
  this.longPressTimer = setTimeout(() => {
686
688
  this.handleLongPress()
@@ -702,15 +704,27 @@ class Term extends Component {
702
704
  }
703
705
 
704
706
  onTouchEnd = () => {
707
+ const wasTap = this.touchStartPos && !this.longPressFired
705
708
  clearTimeout(this.longPressTimer)
706
709
  this.longPressTimer = null
707
710
  this.touchStartPos = null
711
+ // xterm's own touch (Gesture) handler calls preventDefault()/stopPropagation()
712
+ // on touchstart/touchend, which suppresses the synthesised mousedown xterm
713
+ // relies on to focus its hidden helper textarea. As a result a tap never
714
+ // focuses the terminal on touch devices, so the soft keyboard never opens
715
+ // and you cannot type. Focus explicitly on a clean tap (not a long-press,
716
+ // not a scroll) so mobile input works. The focus() runs synchronously inside
717
+ // this user-gesture handler, so iOS/Android will show the keyboard.
718
+ if (wasTap && this.term) {
719
+ this.term.focus()
720
+ }
708
721
  }
709
722
 
710
723
  handleLongPress = () => {
711
724
  if (!this.touchStartPos || this.state.loading) {
712
725
  return
713
726
  }
727
+ this.longPressFired = true
714
728
  const { clientX, clientY, target } = this.touchStartPos
715
729
 
716
730
  // Select the word at the touch position (same as desktop right-click word
@@ -0,0 +1,45 @@
1
+ /**
2
+ * parse `df` output into disk list
3
+ */
4
+
5
+ export default function formatDisks (str) {
6
+ if (!str) {
7
+ return {
8
+ disks: []
9
+ }
10
+ }
11
+ const r = str.split('\n')
12
+ .slice(1)
13
+ .reduce((acc, s) => {
14
+ if (!s.trim()) {
15
+ return acc
16
+ }
17
+ const arr = s.trim().split(/ +/)
18
+ // df wraps long filesystem names (e.g. nfs "host:/very/long/export/path")
19
+ // onto a second line that starts with spaces and only holds the numeric
20
+ // columns. Merge such continuation lines back into the previous entry, so
21
+ // those disks (commonly nfs) are listed instead of dropped.
22
+ if (/^\s/.test(s) && acc.length) {
23
+ const prev = acc[acc.length - 1]
24
+ prev.size = arr[0]
25
+ prev.used = arr[1]
26
+ prev.avail = arr[2]
27
+ prev.usedPercent = arr[3]
28
+ prev.mount = arr[4]
29
+ return acc
30
+ }
31
+ acc.push({
32
+ filesystem: arr[0],
33
+ size: arr[1],
34
+ used: arr[2],
35
+ avail: arr[3],
36
+ usedPercent: arr[4],
37
+ mount: arr[5]
38
+ })
39
+ return acc
40
+ }, [])
41
+ .filter(d => d.filesystem && d.mount)
42
+ return {
43
+ disks: r
44
+ }
45
+ }
@@ -6,6 +6,7 @@ import { runCmd } from '../terminal/terminal-apis'
6
6
  import { useEffect } from 'react'
7
7
  import wait from '../../common/wait'
8
8
  import parseInt10 from '../../common/parse-int10'
9
+ import formatDisks from './format-disks'
9
10
 
10
11
  function formatActivities (str) {
11
12
  if (!str) {
@@ -31,31 +32,6 @@ function formatActivities (str) {
31
32
  }
32
33
  }
33
34
 
34
- function formatDisks (str) {
35
- if (!str) {
36
- return {
37
- disks: []
38
- }
39
- }
40
- const r = str.split('\n')
41
- .slice(1)
42
- .map(s => {
43
- const arr = s.split(/ +/)
44
- return {
45
- filesystem: arr[0],
46
- size: arr[1],
47
- used: arr[2],
48
- avail: arr[3],
49
- usedPercent: arr[4],
50
- mount: arr[5]
51
- }
52
- })
53
- .filter(d => d.filesystem)
54
- return {
55
- disks: r
56
- }
57
- }
58
-
59
35
  function formatCpu (str) {
60
36
  if (!str) {
61
37
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "3.15.186",
3
+ "version": "3.15.187",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",