Skip to content

Commit ea36294

Browse files
authored
feat(core): allow changing or disabling the input accessory view on iOS (#13208)
* feat(core): allow changing or disabling the input accessory view on iOS needs tauri-apps/wry#1544 * remove unused code * fix imports * lint * fix features * wry 0.51.2
1 parent 0d39ff6 commit ea36294

18 files changed

Lines changed: 230 additions & 23 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@tauri-apps/api": minor:feat
3+
"tauri-utils": minor:feat
4+
---
5+
6+
Added `disableInputAccessoryView: bool` config for iOS.
7+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri-runtime": minor:feat
3+
"tauri-runtime-wry": minor:feat
4+
---
5+
6+
Added `WebviewAttributes::input_accessory_view_builder` on iOS.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": minor:feat
3+
---
4+
5+
Added `WebviewWindowBuilder::with_input_accessory_view_builder` and `WebviewBuilder::with_input_accessory_view_builder` on iOS.

Cargo.lock

Lines changed: 5 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/tauri-cli/config.schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,11 @@
561561
"description": "on macOS and iOS there is a link preview on long pressing links, this is enabled by default.\n see https://docs.rs/objc2-web-kit/latest/objc2_web_kit/struct.WKWebView.html#method.allowsLinkPreview",
562562
"default": true,
563563
"type": "boolean"
564+
},
565+
"disableInputAccessoryView": {
566+
"description": "Allows disabling the input accessory view on iOS.\n\n The accessory view is the view that appears above the keyboard when a text input element is focused.\n It usually displays a view with \"Done\", \"Next\" buttons.",
567+
"default": false,
568+
"type": "boolean"
564569
}
565570
},
566571
"additionalProperties": false

crates/tauri-runtime-wry/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ rustc-args = ["--cfg", "docsrs"]
1717
rustdoc-args = ["--cfg", "docsrs"]
1818

1919
[dependencies]
20-
wry = { version = "0.51", default-features = false, features = [
20+
wry = { version = "0.51.2", default-features = false, features = [
2121
"drag-drop",
2222
"protocol",
2323
"os-webview",

crates/tauri-runtime-wry/src/lib.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use tauri_runtime::{
3030
UserAttentionType, UserEvent, WebviewDispatch, WebviewEventId, WindowDispatch, WindowEventId,
3131
};
3232

33-
#[cfg(any(target_os = "macos", target_os = "ios"))]
33+
#[cfg(target_vendor = "apple")]
3434
use objc2::rc::Retained;
3535
#[cfg(target_os = "macos")]
3636
use tao::platform::macos::{EventLoopWindowTargetExtMacOS, WindowBuilderExtMacOS};
@@ -42,9 +42,11 @@ use tao::platform::windows::{WindowBuilderExtWindows, WindowExtWindows};
4242
use webview2_com::FocusChangedEventHandler;
4343
#[cfg(windows)]
4444
use windows::Win32::Foundation::HWND;
45+
#[cfg(target_os = "ios")]
46+
use wry::WebViewBuilderExtIos;
4547
#[cfg(windows)]
4648
use wry::WebViewBuilderExtWindows;
47-
#[cfg(any(target_os = "macos", target_os = "ios"))]
49+
#[cfg(target_vendor = "apple")]
4850
use wry::{WebViewBuilderExtDarwin, WebViewExtDarwin};
4951

5052
use tao::{
@@ -2987,7 +2989,7 @@ impl<T: UserEvent> Runtime<T> for Wry<T> {
29872989
}
29882990

29892991
#[cfg(target_os = "ios")]
2990-
fn run_return<F: FnMut(RunEvent<T>) + 'static>(mut self, callback: F) -> i32 {
2992+
fn run_return<F: FnMut(RunEvent<T>) + 'static>(self, callback: F) -> i32 {
29912993
self.run(callback);
29922994
0
29932995
}
@@ -4627,9 +4629,16 @@ fn create_webview<T: UserEvent>(
46274629
webview_builder.with_allow_link_preview(webview_attributes.allow_link_preview);
46284630
}
46294631

4632+
#[cfg(target_os = "ios")]
4633+
{
4634+
if let Some(input_accessory_view_builder) = webview_attributes.input_accessory_view_builder {
4635+
webview_builder = webview_builder
4636+
.with_input_accessory_view_builder(move |webview| input_accessory_view_builder.0(webview));
4637+
}
4638+
}
4639+
46304640
#[cfg(target_os = "macos")]
46314641
{
4632-
use wry::WebViewBuilderExtDarwin;
46334642
if let Some(position) = &webview_attributes.traffic_light_position {
46344643
webview_builder = webview_builder.with_traffic_light_inset(*position);
46354644
}

crates/tauri-runtime/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ gtk = { version = "0.18", features = ["v3_24"] }
4747
[target."cfg(target_os = \"android\")".dependencies]
4848
jni = "0.21"
4949

50+
[target.'cfg(all(target_vendor = "apple", not(target_os = "macos")))'.dependencies]
51+
objc2 = "0.6"
52+
objc2-ui-kit = { version = "0.3.0", default-features = false, features = [
53+
"UIView",
54+
"UIResponder",
55+
] }
56+
5057
[target."cfg(target_os = \"macos\")".dependencies]
5158
url = "2"
5259

crates/tauri-runtime/src/webview.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ type OnPageLoadHandler = dyn Fn(Url, PageLoadEvent) + Send;
3434

3535
type DownloadHandler = dyn Fn(DownloadEvent) -> bool + Send + Sync;
3636

37+
#[cfg(target_os = "ios")]
38+
type InputAccessoryViewBuilderFn = dyn Fn(&objc2_ui_kit::UIView) -> Option<objc2::rc::Retained<objc2_ui_kit::UIView>>
39+
+ Send
40+
+ Sync
41+
+ 'static;
42+
3743
/// Download event.
3844
pub enum DownloadEvent<'a> {
3945
/// Download requested.
@@ -193,7 +199,7 @@ impl<T: UserEvent, R: Runtime<T>> PartialEq for DetachedWebview<T, R> {
193199
}
194200

195201
/// The attributes used to create an webview.
196-
#[derive(Debug, Clone)]
202+
#[derive(Debug)]
197203
pub struct WebviewAttributes {
198204
pub url: WebviewUrl,
199205
pub user_agent: Option<String>,
@@ -236,6 +242,37 @@ pub struct WebviewAttributes {
236242
/// on macOS and iOS there is a link preview on long pressing links, this is enabled by default.
237243
/// see https://docs.rs/objc2-web-kit/latest/objc2_web_kit/struct.WKWebView.html#method.allowsLinkPreview
238244
pub allow_link_preview: bool,
245+
/// Allows overriding the the keyboard accessory view on iOS.
246+
/// Returning `None` effectively removes the view.
247+
///
248+
/// The closure parameter is the webview instance.
249+
///
250+
/// The accessory view is the view that appears above the keyboard when a text input element is focused.
251+
/// It usually displays a view with "Done", "Next" buttons.
252+
///
253+
/// # Stability
254+
///
255+
/// This relies on [`objc2_ui_kit`] which does not provide a stable API yet, so it can receive breaking changes in minor releases.
256+
#[cfg(target_os = "ios")]
257+
pub input_accessory_view_builder: Option<InputAccessoryViewBuilder>,
258+
}
259+
260+
#[cfg(target_os = "ios")]
261+
#[non_exhaustive]
262+
pub struct InputAccessoryViewBuilder(pub Box<InputAccessoryViewBuilderFn>);
263+
264+
#[cfg(target_os = "ios")]
265+
impl std::fmt::Debug for InputAccessoryViewBuilder {
266+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
267+
f.debug_struct("InputAccessoryViewBuilder").finish()
268+
}
269+
}
270+
271+
#[cfg(target_os = "ios")]
272+
impl InputAccessoryViewBuilder {
273+
pub fn new(builder: Box<InputAccessoryViewBuilderFn>) -> Self {
274+
Self(builder)
275+
}
239276
}
240277

241278
impl From<&WindowConfig> for WebviewAttributes {
@@ -281,6 +318,12 @@ impl From<&WindowConfig> for WebviewAttributes {
281318
}
282319
builder.javascript_disabled = config.javascript_disabled;
283320
builder.allow_link_preview = config.allow_link_preview;
321+
#[cfg(target_os = "ios")]
322+
if config.disable_input_accessory_view {
323+
builder
324+
.input_accessory_view_builder
325+
.replace(InputAccessoryViewBuilder::new(Box::new(|_webview| None)));
326+
}
284327
builder
285328
}
286329
}
@@ -315,6 +358,8 @@ impl WebviewAttributes {
315358
background_throttling: None,
316359
javascript_disabled: false,
317360
allow_link_preview: true,
361+
#[cfg(target_os = "ios")]
362+
input_accessory_view_builder: None,
318363
}
319364
}
320365

crates/tauri-schema-generator/schemas/config.schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,11 @@
561561
"description": "on macOS and iOS there is a link preview on long pressing links, this is enabled by default.\n see https://docs.rs/objc2-web-kit/latest/objc2_web_kit/struct.WKWebView.html#method.allowsLinkPreview",
562562
"default": true,
563563
"type": "boolean"
564+
},
565+
"disableInputAccessoryView": {
566+
"description": "Allows disabling the input accessory view on iOS.\n\n The accessory view is the view that appears above the keyboard when a text input element is focused.\n It usually displays a view with \"Done\", \"Next\" buttons.",
567+
"default": false,
568+
"type": "boolean"
564569
}
565570
},
566571
"additionalProperties": false

0 commit comments

Comments
 (0)