@electerm/electerm-react 5.1.21 → 5.1.25

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.
@@ -43,9 +43,10 @@ export default auto(function Layout (props) {
43
43
  rightPanelWidth,
44
44
  resizeTrigger,
45
45
  inActiveTerminal,
46
- shortcutBarVisible
46
+ shortcutBarVisible,
47
+ shortcutBarKbOffset
47
48
  } = props.store
48
- const h = height - footerHeight - (inActiveTerminal && pinnedQuickCommandBar ? quickCommandBoxHeight : 0) - (shortcutBarVisible ? shortcutBarHeight : 0) + resizeTrigger
49
+ const h = height - footerHeight - (inActiveTerminal && pinnedQuickCommandBar ? quickCommandBoxHeight : 0) - (shortcutBarVisible ? shortcutBarHeight + shortcutBarKbOffset : 0) + resizeTrigger
49
50
  const l = pinned ? leftSideBarWidth + leftSidePanelWidth : leftSideBarWidth
50
51
  const r = rightPanelVisible && rightPanelPinned ? rightPanelWidth : 0
51
52
  return {
@@ -68,14 +69,15 @@ export default auto(function Layout (props) {
68
69
  rightPanelPinned,
69
70
  rightPanelWidth,
70
71
  pinned,
71
- shortcutBarVisible
72
+ shortcutBarVisible,
73
+ shortcutBarKbOffset
72
74
  } = props.store
73
75
  const l = pinned ? leftSidePanelWidth : 0
74
76
  const r = rightPanelPinned && rightPanelVisible ? rightPanelWidth : 0
75
77
  // account for the far-left icon bar (sidebarWidth - 1px border on desktop;
76
78
  // 0 when the bar is hidden on mobile)
77
79
  const w = width - l - r - (leftSideBarWidth > 0 ? leftSideBarWidth - 1 : 0)
78
- const h = height - footerHeight - (pinnedQuickCommandBar ? quickCommandBoxHeight : 0) - (shortcutBarVisible ? shortcutBarHeight : 0)
80
+ const h = height - footerHeight - (pinnedQuickCommandBar ? quickCommandBoxHeight : 0) - (shortcutBarVisible ? shortcutBarHeight + shortcutBarKbOffset : 0)
79
81
  return layoutAlg(layout, w, h)
80
82
  }
81
83
  const layoutSize = calcLayoutStyle()
@@ -116,6 +116,9 @@ export default auto(function Index (props) {
116
116
  'not-win': !isWin,
117
117
  'qm-pinned': pinnedQuickCommandBar,
118
118
  fullscreen,
119
+ // terminal fullscreen keeps the footer visible (rdp/vnc/spice fullscreen
120
+ // does not — the footer would be an empty bar there)
121
+ 'fs-with-footer': fullscreen && store.inActiveTerminal,
119
122
  'is-main': !isSecondInstance,
120
123
  'is-mobile': store.isMobile,
121
124
  'is-desktop': !store.isMobile
@@ -36,15 +36,27 @@
36
36
  right 10px !important
37
37
  bottom 10px !important
38
38
 
39
- // while the touch shortcut bar (portaled to body, z-index 800 — see
40
- // shortcut-bar.styl) is shown, shrink the fullscreen session by the bar
41
- // height so the terminal is not covered. body.shortcut-bar-on is toggled by
42
- // shortcut-bar.jsx; the extra body class gives this rule higher specificity
43
- // (0,4,0) than the .fullscreen rules above, so it wins the !important battle.
44
- body.shortcut-bar-on
45
- .fullscreen
39
+ // Terminal fullscreen keeps the footer (and the quick-command popup above it)
40
+ // visible; the session shrinks to sit on top of the footer. RDP/VNC/Spice
41
+ // fullscreen stays footer-less — inActiveTerminal is false for those tabs, so
42
+ // the fs-with-footer class is absent there.
43
+ // 36px matches footerHeight / the .main-footer height in footer.styl.
44
+ .fullscreen.fs-with-footer
45
+ .main-footer
46
+ display block
47
+ left 0 !important
48
+ .qm-wrap-tooltip
49
+ display block
50
+ left 0 !important
51
+ // sidebar is hidden in fullscreen; hide the footer control that opens it
52
+ .terminal-footer-show-sidebar
53
+ display none
54
+ .session-wrap.session-current
55
+ .term-wrap
56
+ height calc(100% - 36px - var(--shortcut-bar-h, 0px)) !important
57
+ // pinned quick-command bar (180px, same as quickCommandBoxHeight) sits
58
+ // between terminal and footer — reserve its space too
59
+ &.qm-pinned
46
60
  .session-wrap.session-current
47
- bottom var(--shortcut-bar-h, 44px) !important
48
- height auto !important
49
61
  .term-wrap
50
- height calc(100% - var(--shortcut-bar-h, 44px)) !important
62
+ height calc(100% - 36px - 180px - var(--shortcut-bar-h, 0px)) !important
@@ -31,7 +31,9 @@ const ShortcutBar = lazy(() => import('./shortcut-bar'))
31
31
  // minimum height (px) the visual viewport must lose for us to treat it as
32
32
  // "the soft keyboard is now covering part of the screen". A soft keyboard is
33
33
  // typically ≥150px; a browser address-bar show/hide is well under this.
34
- const KEYBOARD_HEIGHT = 120
34
+ // Shared with shortcut-bar.jsx, which uses it to decide how far to lift the
35
+ // bar above a keyboard that overlays the page (iOS / HarmonyOS).
36
+ export const KEYBOARD_MIN = 120
35
37
 
36
38
  // kept as a coarse capability fallback for engines without visualViewport.
37
39
  // Modern Chromium (Electron) always exposes window.visualViewport, so this is
@@ -87,7 +89,7 @@ export default function ShortcutBarEntry (props) {
87
89
  // ignore viewport changes that also changed width (rotation / split) —
88
90
  // a keyboard changes height only.
89
91
  const sameWidth = Math.abs(vv.width - baseline.width) < 20
90
- if (sameWidth && baseline.height - vv.height > KEYBOARD_HEIGHT) {
92
+ if (sameWidth && baseline.height - vv.height > KEYBOARD_MIN) {
91
93
  setKeyboardSeen(true)
92
94
  // The user is focused in a terminal with the keyboard up — they need
93
95
  // the bar right now. Set visibility here rather than waiting for the
@@ -10,18 +10,22 @@
10
10
  * - first (fixed) button collapses the bar
11
11
  * - second (fixed) button opens the edit modal (shortcut-bar-edit.jsx)
12
12
  * - tapping a shortcut sends it to the active terminal via runQuickCommand
13
+ * - while the system input panel overlays the page without resizing the
14
+ * layout viewport (iOS / HarmonyOS do this, Android resizes instead), the
15
+ * bar lifts itself above the panel — see the visualViewport effect below
13
16
  *
14
17
  * Only loaded on touch devices — see shortcut-bar-entry.jsx.
15
18
  * Data + persistence live in shortcut-bar-defs.js.
16
19
  */
17
20
 
18
21
  import { auto } from 'manate/react'
19
- import { useEffect, useState } from 'react'
22
+ import { useEffect, useRef, useState } from 'react'
20
23
  import { createPortal } from 'react-dom'
21
24
  import { DownOutlined, EditOutlined } from '@ant-design/icons'
22
25
  import { refs } from '../common/ref'
23
26
  import { shortcutBarHeight } from '../../common/constants'
24
27
  import ShortcutBarEdit from './shortcut-bar-edit'
28
+ import { KEYBOARD_MIN } from './shortcut-bar-entry'
25
29
  import { candidates, loadActive, saveActive, ESC } from './shortcut-bar-defs'
26
30
  import './shortcut-bar.styl'
27
31
 
@@ -89,6 +93,55 @@ function ShortcutBar (props) {
89
93
  }
90
94
  }, [])
91
95
 
96
+ // On Android the soft keyboard resizes the layout viewport, so a
97
+ // `position: fixed; bottom: 0` bar is pushed up automatically. iOS and
98
+ // HarmonyOS instead keep the layout viewport full-size and let the keyboard
99
+ // overlay it — there the bar sits underneath the keyboard. visualViewport
100
+ // always tracks the *visible* area on every platform, so the gap between it
101
+ // and the layout viewport is exactly the covered height: lift the bar by
102
+ // that much so it rides just above the keyboard.
103
+ const [kbOffset, setKbOffset] = useState(0)
104
+ const kbBaselineRef = useRef({ height: 0, width: 0 })
105
+
106
+ useEffect(() => {
107
+ const vv = window.visualViewport
108
+ if (!vv) {
109
+ return
110
+ }
111
+ // while no keyboard is up, layout viewport == visual viewport (offsetTop
112
+ // 0); keep refreshing the baseline so a later comparison is accurate.
113
+ function sync () {
114
+ if (vv.offsetTop <= 1) {
115
+ kbBaselineRef.current = { height: window.innerHeight, width: vv.width }
116
+ }
117
+ const { height, width } = kbBaselineRef.current
118
+ // a keyboard changes height only — ignore rotation / pinch-zoom, which
119
+ // change width too.
120
+ const sameWidth = Math.abs(vv.width - width) < 20
121
+ const covered = sameWidth ? height - vv.height - vv.offsetTop : 0
122
+ setKbOffset(covered > KEYBOARD_MIN ? Math.ceil(covered) : 0)
123
+ }
124
+ sync()
125
+ vv.addEventListener('resize', sync)
126
+ vv.addEventListener('scroll', sync)
127
+ window.addEventListener('resize', sync)
128
+ return () => {
129
+ vv.removeEventListener('resize', sync)
130
+ vv.removeEventListener('scroll', sync)
131
+ window.removeEventListener('resize', sync)
132
+ }
133
+ }, [])
134
+
135
+ // keep the offset in a CSS var consumed by shortcut-bar.styl, and expose the
136
+ // lifted height so layout.jsx can shrink the terminal accordingly.
137
+ useEffect(() => {
138
+ document.documentElement.style.setProperty(
139
+ '--shortcut-bar-kb-offset',
140
+ kbOffset ? kbOffset + 'px' : '0px'
141
+ )
142
+ store.shortcutBarKbOffset = kbOffset
143
+ }, [kbOffset])
144
+
92
145
  // reserve layout space + lift the footer while the bar is shown.
93
146
  // expose the bar height as a CSS var so the .styl + footer-lift rule stay
94
147
  // in sync with the shortcutBarHeight constant consumed by layout.jsx.
@@ -135,7 +188,11 @@ function ShortcutBar (props) {
135
188
  }
136
189
 
137
190
  return createPortal(
138
- <div className='shortcut-bar' role='toolbar'>
191
+ <div
192
+ className='shortcut-bar'
193
+ role='toolbar'
194
+ style={kbOffset ? { bottom: kbOffset + 'px' } : undefined}
195
+ >
139
196
  <div className='shortcut-bar-fixed'>
140
197
  <button
141
198
  type='button'
@@ -9,7 +9,7 @@
9
9
  right 0
10
10
  bottom 0
11
11
  height var(--shortcut-bar-h, 44px)
12
- z-index 800
12
+ z-index 400
13
13
  display flex
14
14
  align-items stretch
15
15
  background var(--main)
@@ -73,10 +73,12 @@
73
73
  color var(--text-light)
74
74
 
75
75
  // while the bar is visible, lift the footer + reserve space so nothing is
76
- // covered (terminal area is shrunk by layout.jsx via store.shortcutBarVisible)
76
+ // covered (terminal area is shrunk by layout.jsx via store.shortcutBarVisible;
77
+ // --shortcut-bar-kb-offset raises both bar + footer above a page-overlaying
78
+ // system input panel on iOS / HarmonyOS)
77
79
  .shortcut-bar-on
78
80
  .main-footer
79
- bottom var(--shortcut-bar-h, 44px)
81
+ bottom calc(var(--shortcut-bar-h, 44px) + var(--shortcut-bar-kb-offset, 0px))
80
82
 
81
83
  // --- edit modal -----------------------------------------------------------
82
84
 
@@ -169,6 +169,9 @@ export default () => {
169
169
 
170
170
  // touch-only shortcut bar (see components/terminal/shortcut-bar-entry.jsx)
171
171
  shortcutBarVisible: false,
172
+ // px the bar is lifted above a page-overlaying system input panel
173
+ // (iOS / HarmonyOS) — see shortcut-bar.jsx
174
+ shortcutBarKbOffset: 0,
172
175
 
173
176
  // sidebar
174
177
  openedSideBar: ls.getItem(openedSidebarKey) || '',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "5.1.21",
3
+ "version": "5.1.25",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",