viewpoint_core/page/keyboard/
builder.rs1use std::time::Duration;
4
5use tracing::{debug, instrument, trace};
6
7use crate::error::LocatorError;
8use crate::wait::NavigationWaiter;
9
10use super::Keyboard;
11
12#[derive(Debug)]
16pub struct KeyboardPressBuilder<'a> {
17 keyboard: &'a Keyboard,
18 key: String,
19 delay: Option<Duration>,
20 no_wait_after: bool,
21}
22
23impl<'a> KeyboardPressBuilder<'a> {
24 pub(crate) fn new(keyboard: &'a Keyboard, key: &str) -> Self {
25 Self {
26 keyboard,
27 key: key.to_string(),
28 delay: None,
29 no_wait_after: false,
30 }
31 }
32
33 #[must_use]
35 pub fn delay(mut self, delay: Duration) -> Self {
36 self.delay = Some(delay);
37 self
38 }
39
40 #[must_use]
45 pub fn no_wait_after(mut self, no_wait_after: bool) -> Self {
46 self.no_wait_after = no_wait_after;
47 self
48 }
49
50 #[instrument(level = "debug", skip(self), fields(key = %self.key))]
52 pub async fn send(self) -> Result<(), LocatorError> {
53 let navigation_waiter = if self.no_wait_after {
55 None
56 } else {
57 Some(NavigationWaiter::new(
58 self.keyboard.connection().subscribe_events(),
59 self.keyboard.session_id().to_string(),
60 self.keyboard.frame_id().to_string(),
61 ))
62 };
63
64 self.keyboard.press_internal(&self.key, self.delay).await?;
66
67 if let Some(waiter) = navigation_waiter {
69 match waiter.wait_for_navigation_if_triggered().await {
70 Ok(navigated) => {
71 if navigated {
72 trace!("Navigation completed after keyboard press");
73 }
74 }
75 Err(e) => {
76 debug!(error = ?e, "Navigation wait failed after keyboard press");
77 return Err(LocatorError::WaitError(e));
78 }
79 }
80 }
81
82 Ok(())
83 }
84}
85
86impl<'a> std::future::IntoFuture for KeyboardPressBuilder<'a> {
87 type Output = Result<(), LocatorError>;
88 type IntoFuture =
89 std::pin::Pin<Box<dyn std::future::Future<Output = Self::Output> + Send + 'a>>;
90
91 fn into_future(self) -> Self::IntoFuture {
92 Box::pin(self.send())
93 }
94}