From f98cd0f70b96e85849cb62aa7fda1fbbc0b3875c Mon Sep 17 00:00:00 2001 From: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Date: Mon, 28 Sep 2026 21:55:50 +0800 Subject: [PATCH] fix(mobile): count the iOS safe areas once The WKWebView's scroll view inset its content by the safe areas, and the page, laid out with viewport-fit=cover, padded by env(safe-area-inset-*) as well. The viewport came out 778pt tall on an 874pt screen: everything sat a status bar's height too low, with a blank band under it. The scroll view's automatic inset adjustment is now off, so the page runs edge to edge and its CSS alone keeps clear of the status bar and home indicator. Co-Authored-By: Claude --- mobile/src-tauri/Cargo.lock | 1 + mobile/src-tauri/Cargo.toml | 4 ++++ mobile/src-tauri/src/lib.rs | 26 ++++++++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/mobile/src-tauri/Cargo.lock b/mobile/src-tauri/Cargo.lock index 483dd214..da04b7da 100644 --- a/mobile/src-tauri/Cargo.lock +++ b/mobile/src-tauri/Cargo.lock @@ -5469,6 +5469,7 @@ version = "0.1.0" dependencies = [ "anyhow", "iroh", + "objc2", "rustls", "serde", "serde_json", diff --git a/mobile/src-tauri/Cargo.toml b/mobile/src-tauri/Cargo.toml index a0386c7f..fd4db62c 100644 --- a/mobile/src-tauri/Cargo.toml +++ b/mobile/src-tauri/Cargo.toml @@ -34,3 +34,7 @@ tokio = { version = "1", features = ["sync", "time", "macros"] } [target.'cfg(any(target_os = "android", target_os = "ios"))'.dependencies] tauri-plugin-barcode-scanner = "2" + +# Setting one WKWebView property the Tauri API does not reach (`edge_to_edge`). +[target.'cfg(target_os = "ios")'.dependencies] +objc2 = "0.6" diff --git a/mobile/src-tauri/src/lib.rs b/mobile/src-tauri/src/lib.rs index de89092d..f33a82a8 100644 --- a/mobile/src-tauri/src/lib.rs +++ b/mobile/src-tauri/src/lib.rs @@ -405,6 +405,10 @@ pub fn run() { builder .setup(|app| { + #[cfg(target_os = "ios")] + if let Some(window) = app.get_webview_window("main") { + edge_to_edge(&window); + } let dir = app.path().app_data_dir()?; app.manage(Arc::new(AppState { dir, @@ -423,3 +427,25 @@ pub fn run() { .run(tauri::generate_context!()) .expect("error while running tty7"); } + +/// Lets the page run under the status bar and the home indicator, and leaves +/// the safe areas to it (`viewport-fit=cover` and `env(safe-area-inset-*)` in +/// the CSS). By default the WKWebView's scroll view insets its content by the +/// safe areas as well, so each was counted twice: the page sat a status bar's +/// height too low, with a blank band under it. +#[cfg(target_os = "ios")] +fn edge_to_edge(window: &tauri::WebviewWindow) { + use objc2::msg_send; + use objc2::runtime::AnyObject; + /// `UIScrollViewContentInsetAdjustmentBehavior.never`. + const NEVER: isize = 2; + let _ = window.with_webview(|webview| unsafe { + let Some(wk) = (webview.inner() as *const AnyObject).as_ref() else { + return; + }; + let scroll: *const AnyObject = msg_send![wk, scrollView]; + if let Some(scroll) = scroll.as_ref() { + let _: () = msg_send![scroll, setContentInsetAdjustmentBehavior: NEVER]; + } + }); +}