@electerm/electerm-react 5.1.23 → 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()
|
|
@@ -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
|
-
|
|
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 >
|
|
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
|
|
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'
|
|
@@ -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) || '',
|