refactor(inset): the bottom-inset arithmetic becomes testable, and is tested
The measurement lived inside the view, where the only way to check it was to run Obsidian on a phone. It moves to a pure `insetFor(leaf, bars, visible)` against the numbers a phone reports - including the case the events hid: while the keyboard is up the navbar is behind it, so the deeper of the two is the inset and adding them would push the composer twice as far as it must go.
This commit is contained in:
1 parent
413d68fc87
commit
70cf985aa1
3 files changed
+128
-20
No files matched your search
+14
-20
@@ -1,6 +1,8 @@
|
||||
import type { ViewStateResult, WorkspaceLeaf } from "obsidian";
|
||||
import { ItemView, TFile } from "obsidian";
|
||||
import { mount, unmount } from "svelte";
|
||||
import type { Rect } from "./inset";
|
||||
import { insetFor } from "./inset";
|
||||
import type BeaverPlugin from "./main";
|
||||
import { PanelState } from "./state.svelte";
|
||||
import App from "./ui/app.svelte";
|
||||
@@ -144,34 +146,26 @@ export class PanelView extends ItemView {
|
||||
}
|
||||
|
||||
// Whatever floats over the bottom of this leaf, measured rather than
|
||||
// guessed: the desktop status bar, the phone's navbar (which the workspace
|
||||
// does not subtract from a leaf's height), and the software keyboard, which
|
||||
// shrinks the visual viewport without resizing the layout at all. Returns
|
||||
// the inset it wrote, so the settle loop can tell when it stops changing.
|
||||
// guessed. Returns the inset it wrote, so the settle loop can tell when the
|
||||
// reading stops changing; the arithmetic itself lives in ``inset.ts``.
|
||||
private inset(): number {
|
||||
const box = this.contentEl.getBoundingClientRect();
|
||||
if (box.height <= 0) {
|
||||
return Number.NaN;
|
||||
}
|
||||
let overlap = 0;
|
||||
for (const bar of BOTTOM_BARS) {
|
||||
const node = document.querySelector<HTMLElement>(bar);
|
||||
if (!node || node.offsetParent === null) {
|
||||
continue;
|
||||
}
|
||||
const b = node.getBoundingClientRect();
|
||||
if (b.height > 0 && b.left < box.right && b.right > box.left) {
|
||||
overlap = Math.max(overlap, box.bottom - b.top);
|
||||
const bars: Rect[] = [];
|
||||
for (const selector of BOTTOM_BARS) {
|
||||
const node = document.querySelector<HTMLElement>(selector);
|
||||
if (node && node.offsetParent !== null) {
|
||||
bars.push(node.getBoundingClientRect());
|
||||
}
|
||||
}
|
||||
const vv = window.visualViewport;
|
||||
if (vv) {
|
||||
// The keyboard eats the bottom of the window; anything of this leaf
|
||||
// below that line is unreachable until it goes away.
|
||||
const floor = vv.offsetTop + vv.height;
|
||||
overlap = Math.max(overlap, box.bottom - floor);
|
||||
}
|
||||
const inset = Math.max(0, Math.round(overlap));
|
||||
const inset = insetFor(
|
||||
box,
|
||||
bars,
|
||||
vv ? { height: vv.height, offsetTop: vv.offsetTop } : null
|
||||
);
|
||||
this.contentEl.style.setProperty("--beaver-inset-bottom", `${inset}px`);
|
||||
return inset;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user