rust_droid/action/
touch.rs

1use crate::common::relative_rect::RelativeRect;
2use crate::{Droid, Result, Target};
3use std::time::Duration;
4
5/// Builds and executes a "touch" action.
6///
7/// A touch can be a simple tap or a long press, depending on the `duration`.
8/// This struct is created by the `Droid::touch()` method.
9pub struct TouchBuilder<'a> {
10    droid: &'a mut Droid,
11    target: Target,
12    duration: Duration,
13    times: u32,
14    threshold: Option<f32>,
15    search_rect: Option<RelativeRect>,
16}
17
18impl<'a> TouchBuilder<'a> {
19    pub fn new(droid: &'a mut Droid, target: Target) -> Self {
20        Self {
21            droid,
22            target,
23            duration: Duration::from_millis(100),
24            times: 1,
25            threshold: None,
26            search_rect: None,
27        }
28    }
29
30    /// Sets the number of times to perform the touch action.
31    ///
32    /// Default is `1`.
33    pub fn times(mut self, count: u32) -> Self {
34        self.times = count;
35        self
36    }
37
38    /// Sets the duration of the touch.
39    ///
40    /// A short duration (e.g., < 200ms) is a tap.
41    /// A longer duration is a long press.
42    ///
43    /// Default is `100ms`.
44    pub fn duration(mut self, duration: Duration) -> Self {
45        self.duration = duration;
46        self
47    }
48
49    /// Sets the confidence threshold for image matching.
50    ///
51    /// This only applies if the `target` is an `Image`.
52    /// The value should be between `0.0` and `1.0`.
53    /// If not set, the default confidence from `DroidConfig` is used.
54    pub fn threshold(mut self, value: f32) -> Self {
55        self.threshold = Some(value);
56        self
57    }
58
59    /// Restricts the image search to a specific region of the screen.
60    ///
61    /// This only applies if the `target` is an `Image`.
62    /// The `rect` is defined using relative coordinates (0.0 to 1.0).
63    pub fn search_in(mut self, rect: RelativeRect) -> Self {
64        self.search_rect = Some(rect);
65        self
66    }
67
68    /// Executes the configured touch action.
69    ///
70    /// It resolves the `target` to a screen coordinate and then performs
71    /// the tap or long press.
72    ///
73    /// # Errors
74    ///
75    /// Returns an error if the target cannot be found (for image targets) or
76    /// if the underlying ADB command fails.
77    pub fn execute(self) -> Result<()> {
78        let threshold = self
79            .threshold
80            .unwrap_or(self.droid.config.default_confidence);
81        let point = self
82            .droid
83            .resolve_target(&self.target, threshold, self.search_rect)?;
84        log::info!(
85            "Executing touch action at {:?} for {} times",
86            point,
87            self.times
88        );
89
90        for i in 0..self.times {
91            if self.duration <= Duration::from_millis(200) {
92                self.droid.controller.tap(point)?;
93            } else {
94                self.droid.controller.swipe(point, point, self.duration)?;
95            }
96
97            if self.times > 1 && i < self.times - 1 {
98                std::thread::sleep(Duration::from_millis(50));
99            }
100        }
101        Ok(())
102    }
103}