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

3.4 KiB
Raw Permalink Blame History

window.__TAURITAVERN__.api.layout — 内容视口

在移动端,宿主让内容视口只占据可交互区域:系统栏、刘海和停靠键盘已经从视口尺寸中扣除。扩展按普通浏览器规则排版即可,不需要识别宿主或扣除 inset。浮动与分离键盘不缩小视口。

.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。

读取与订阅

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 或安全区补偿的扩展,删除这些代码,直接按内容视口排版。