Render between the system bars deterministically; delete my inset bridge
The app sometimes drew under the status and gesture bars and sometimes between them. Cause: Capacitor 8 ships a SystemBars plugin that already handles insets, from a listener on the decor view, and my MainActivity had installed another one on the WebView. Different views, so they stacked rather than replaced each other and the result depended on which fired last. SystemBars switches on the viewport meta tag. With viewport-fit=cover it passes insets through once onPageCommitVisible has checked the tag, decor padding drops to 0 and the WebView grows 735 -> 820, leaving the page to place itself from injected CSS vars. Without it the plugin pads the decor view and the WebView is laid out between the bars already. So sync-www.sh now strips viewport-fit=cover from the generated www/ (patch 5), MainActivity is an empty BridgeActivity, native.css and native.js no longer touch insets, and bar style moves to capacitor.config.json. No native->web handshake remains, so there is nothing to race and no launch-time layout jump. Verified identical across 3 cold launches, 2 resumes and an in-place reload: h=735 padTop=8px overflowBy=0, panel 485px, pad rows 44.8px. Costs no space: 820-45-114 and 735-8-66 both leave 661px. The bars take the same room either way. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,45 +2,23 @@
|
||||
reference/ is never edited; sync-www.sh injects this as the last stylesheet
|
||||
in <head>, so on equal specificity these rules win. */
|
||||
|
||||
:root{
|
||||
/* Filled in from Android WindowInsets by MainActivity via __applyInsets().
|
||||
The env() defaults keep the page correct in a plain desktop browser, where
|
||||
env() works and the native bridge is absent. */
|
||||
--ins-t: env(safe-area-inset-top, 0px);
|
||||
--ins-b: env(safe-area-inset-bottom, 0px);
|
||||
--ins-l: env(safe-area-inset-left, 0px);
|
||||
--ins-r: env(safe-area-inset-right, 0px);
|
||||
/* No inset handling here on purpose.
|
||||
|
||||
/* The reference derives --sab from env(safe-area-inset-bottom), which is
|
||||
always 0px inside an Android WebView. Re-point it at the real inset.
|
||||
.bnav and .sheet both key off --sab, so they need no further changes. */
|
||||
--sab: var(--ins-b);
|
||||
}
|
||||
sync-www.sh strips viewport-fit=cover from the generated www/, so Capacitor's
|
||||
SystemBars plugin pads the decor view and the WebView is laid out between the
|
||||
status and gesture bars already. env(safe-area-inset-*) is therefore 0, the
|
||||
reference's --sab resolves to 0, and .bnav and .sheet are correct as written.
|
||||
|
||||
An earlier version mapped --sab onto values pushed from MainActivity. That
|
||||
raced with Capacitor's own listener - see CLAUDE.md. */
|
||||
|
||||
@media (max-width:820px){
|
||||
/* The reference sets `padding: 8px 8px calc(var(--nav) + var(--sab) + 8px)`.
|
||||
Bottom already accounts for --sab; add the top and side insets so the unit
|
||||
panel clears the status bar and any display cutout. */
|
||||
.app{
|
||||
padding-top: calc(8px + var(--ins-t));
|
||||
padding-left: calc(8px + var(--ins-l));
|
||||
padding-right: calc(8px + var(--ins-r));
|
||||
}
|
||||
|
||||
/* Bottom nav is position:fixed and spans the full width, so it needs the
|
||||
side insets itself. Its height/padding-bottom already follow --sab. */
|
||||
.bnav{
|
||||
padding-left: var(--ins-l);
|
||||
padding-right: var(--ins-r);
|
||||
}
|
||||
|
||||
/* ---------- strip ergonomics (Phase 1 UI fix) ----------
|
||||
The reference spaces its two chip rows with `#strip .chips + .chips`, but
|
||||
on phones the .lbl heading between them is display:none and still in the
|
||||
DOM, so the adjacent-sibling selector never matches and the rows sit flush
|
||||
(measured: 0px gap). native.js collapses the 7 context chips into the
|
||||
single .ctxbtn below, leaving one chip row with real touch targets.
|
||||
Phase 2 must carry this - see CLAUDE.md. */
|
||||
(measured: 0px gap). native.js collapses both rows into the two pickers
|
||||
below. Phase 2 must carry this - see CLAUDE.md. */
|
||||
|
||||
/* Mode and layer pickers share one row: only one layer is ever active, so
|
||||
neither needs a scrolling row of its own. One 44px row instead of two gives
|
||||
@@ -73,8 +51,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Context picker rows inside the sheet. Uses CTXHINT from the reference, which
|
||||
the phone layout otherwise never shows. */
|
||||
/* Mode and layer rows inside the sheet. The mode rows use CTXHINT from the
|
||||
reference, which the phone layout otherwise never shows. */
|
||||
.ctxopt{
|
||||
display: block; width: 100%; text-align: left; color: inherit;
|
||||
background: var(--card); border: 1px solid var(--line); border-radius: 10px;
|
||||
|
||||
@@ -16,15 +16,10 @@
|
||||
var cap = window.Capacitor;
|
||||
var P = (cap && cap.Plugins) || {};
|
||||
|
||||
/* Called from MainActivity's window-inset listener. Defined unconditionally
|
||||
so the native side never has to feature-detect it. Values arrive in dp. */
|
||||
window.__applyInsets = function (top, right, bottom, left) {
|
||||
var s = document.documentElement.style;
|
||||
s.setProperty("--ins-t", top + "px");
|
||||
s.setProperty("--ins-r", right + "px");
|
||||
s.setProperty("--ins-b", bottom + "px");
|
||||
s.setProperty("--ins-l", left + "px");
|
||||
};
|
||||
/* Insets are deliberately not handled here. sync-www.sh strips
|
||||
viewport-fit=cover, so Capacitor's SystemBars plugin pads the decor view
|
||||
and the WebView is already laid out between the system bars. An earlier
|
||||
__applyInsets bridge raced with that plugin - see CLAUDE.md. */
|
||||
|
||||
if (!(cap && cap.isNativePlatform && cap.isNativePlatform())) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user