ferridriver_script/bindings/
keyboard.rs1use std::sync::Arc;
8
9use ferridriver::Page;
10use rquickjs::JsLifetime;
11use rquickjs::class::Trace;
12
13use rquickjs::function::Opt;
14use serde::Deserialize;
15
16use crate::bindings::convert::{FerriResultExt, serde_from_js};
17
18#[derive(Debug, Default, Deserialize)]
19#[serde(default)]
20struct JsKeyDelay {
21 delay: Option<u64>,
22}
23
24#[derive(Debug, Default, Deserialize)]
25#[serde(default, rename_all = "camelCase")]
26struct JsKeyType {
27 delay: Option<u64>,
28 named_keys: Option<bool>,
29}
30
31fn parse_delay<'js>(ctx: &rquickjs::Ctx<'js>, v: Opt<rquickjs::Value<'js>>) -> rquickjs::Result<Option<u64>> {
32 match v.0 {
33 Some(val) if !val.is_undefined() && !val.is_null() => Ok(serde_from_js::<JsKeyDelay>(ctx, val)?.delay),
34 _ => Ok(None),
35 }
36}
37
38fn parse_type_options<'js>(
39 ctx: &rquickjs::Ctx<'js>,
40 v: Opt<rquickjs::Value<'js>>,
41) -> rquickjs::Result<Option<ferridriver::page::KeyboardTypeOptions>> {
42 match v.0 {
43 Some(val) if !val.is_undefined() && !val.is_null() => {
44 let parsed = serde_from_js::<JsKeyType>(ctx, val)?;
45 Ok(Some(ferridriver::page::KeyboardTypeOptions {
46 delay: parsed.delay,
47 named_keys: parsed.named_keys,
48 }))
49 },
50 _ => Ok(None),
51 }
52}
53
54#[derive(JsLifetime, Trace)]
55#[rquickjs::class(rename = "Keyboard")]
56pub struct KeyboardJs {
57 #[qjs(skip_trace)]
58 page: Arc<Page>,
59}
60
61impl KeyboardJs {
62 #[must_use]
63 pub fn new(page: Arc<Page>) -> Self {
64 Self { page }
65 }
66}
67
68#[rquickjs::methods]
69impl KeyboardJs {
70 #[qjs(rename = "down")]
72 pub async fn down(&self, key: String) -> rquickjs::Result<()> {
73 self.page.keyboard().down(&key).await.into_js()
74 }
75
76 #[qjs(rename = "up")]
78 pub async fn up(&self, key: String) -> rquickjs::Result<()> {
79 self.page.keyboard().up(&key).await.into_js()
80 }
81
82 #[qjs(rename = "press")]
84 pub async fn press<'js>(
85 &self,
86 ctx: rquickjs::Ctx<'js>,
87 key: String,
88 options: Opt<rquickjs::Value<'js>>,
89 ) -> rquickjs::Result<()> {
90 let delay = parse_delay(&ctx, options)?;
91 let opts = delay.map(|d| ferridriver::page::KeyboardPressOptions { delay: Some(d) });
92 self.page.keyboard().press(&key, opts).await.into_js()
93 }
94
95 #[qjs(rename = "type")]
97 pub async fn type_<'js>(
98 &self,
99 ctx: rquickjs::Ctx<'js>,
100 text: String,
101 options: Opt<rquickjs::Value<'js>>,
102 ) -> rquickjs::Result<()> {
103 let opts = parse_type_options(&ctx, options)?;
104 self.page.keyboard().r#type(&text, opts).await.into_js()
105 }
106
107 #[qjs(rename = "insertText")]
109 pub async fn insert_text(&self, text: String) -> rquickjs::Result<()> {
110 self.page.keyboard().insert_text(&text).await.into_js()
111 }
112}