TauriTavern/docs/API/Layout.md
Darkatse ee7f74e93b docs(ios): gather the drawer bar into one section
The drawer bar was described across two iOS bullets, a page bullet
and an upstream-sync entry. MobileStyleAdaptation now gives it one
section: placement, the snapshot as its single source, publishing,
activation and page styling. API/Layout keeps what extension and theme
authors observe, iOSDevelopment keeps the simulator notes, and tt-docs
is regenerated.

Validation: pnpm run check.
2026-10-24 23:41:18 -04:00

67 lines
3.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# `window.__TAURITAVERN__.api.layout` — 内容视口
在移动端,宿主让内容视口只占据可交互区域:系统栏、刘海和停靠键盘已经从视口尺寸中扣除。扩展按普通浏览器规则排版即可,不需要识别宿主或扣除 inset。浮动与分离键盘不缩小视口。
```css
.my-panel {
position: fixed;
inset: 0;
display: flex;
flex-direction: column;
}
.my-panel-content {
flex: 1;
min-height: 0;
overflow: auto;
}
```
`100vh`、`100dvh`、`window.innerHeight`、`position: fixed`、`<dialog>` 和 iframe 都使用各自正常的浏览器坐标系。`--doc-height` 是静态 CSS 别名:支持时为 `100dvh`,否则为 `100vh`。
## 读取与订阅
```js
const layout = window.__TAURITAVERN__.api.layout;
const snapshot = layout.snapshot();
const unsubscribe = await layout.subscribe(snapshot => {
console.log(snapshot.viewport.width, snapshot.viewport.height);
});
await unsubscribe();
```
宿主 `abiVersion: 2`;布局快照 `version: 2`,长度单位为 CSS px:
- `timestampMs`:读取时间。
- `viewport`:visual viewport 的 `{ left, top, width, height, right, bottom }`;没有 VisualViewport API 时读取布局视口。
- `safeFrame`:与 `viewport` 相同。
- `safeInsets`:`{ top: 0, right: 0, bottom: 0, left: 0 }`。
- `ime`:`{ bottom: 0, viewportBottomInset: 0, keyboardOffset: 0 }`。
`safeInsets` 与 `ime` 表示视口内仍需页面自行避让的量,宿主已全部消费,因此为零。订阅立即交付一次快照,之后把 window resize 与 visual viewport resize/scroll 按帧合并交付;最后一个订阅取消时移除监听。
## 系统栏区域
非沉浸模式下,系统栏后面显示宿主绘制的壁纸或主题底色。网页像素(包括遮罩、滤镜和视频)不会延伸到系统栏。
### 原生抽屉栏
iOS 27.1+ 上,系统在内容视口之外给出 bar 区域时(目前为 iPhone Duo),宿主把页面顶层抽屉(`#top-settings-holder > .drawer`)的入口画成原生按钮,页面没有顶栏:
- 扩展加入的顶层抽屉同样出现,使用通用图标,名称取抽屉图标的 `title`。
- 主题对顶栏与抽屉开关的样式不生效。
## 截取
`await layout.capture()` 返回当前内容视口的 `image/png` Blob,属于第一方使用的 Project Contract。图像左上角对应内容视口 `(0, 0)`,宽度对应 `window.innerWidth`;分辨率由平台决定,调用方用图片宽度除以视口宽度换算 CSS 坐标。系统栏不在图中,不滚动页面或拼接视口外内容。
调用方负责等待重绘,原生接口只读取像素。macOS 使用 ScreenCaptureKit 捕获本进程窗口并裁至内容视口,无需屏幕录制授权;iOS 使用 WK snapshot,其他平台使用各自的原生截图接口。失败直接拒绝 Promise,Web Host 以 `Unsupported` 拒绝。
## 旧契约
- `ime.activeSurface` 与 `ime.kind` 已移除。
- `--tt-inset-*` 保留为 `env(safe-area-inset-*, 0px)` 的别名;`--tt-viewport-bottom-inset` 是 `--tt-inset-bottom` 的别名。
- `--tt-ime-bottom` 与 `--tt-base-viewport-height` 已移除。
- `data-tt-mobile-surface` 属性与 `layout-kit.js` 的 `SURFACE`/`applySurface()` 没有布局作用,只为已有调用保留。
- `layout-kit.js` 的 `getLayoutApi()`、`waitForHostReady()`、`subscribeLayout()` 继续可用。
使用旧键盘位移、spacer 或安全区补偿的扩展,删除这些代码,直接按内容视口排版。