use std::path::Path;
use std::sync::Arc;
use tracing::{debug, instrument};
use viewpoint_cdp::CdpConnection;
use viewpoint_cdp::protocol::dom::SetFileInputFilesParams;
use crate::error::LocatorError;
#[derive(Debug)]
pub struct FileChooser {
connection: Arc<CdpConnection>,
session_id: String,
frame_id: String,
backend_node_id: Option<i32>,
is_multiple: bool,
}
impl FileChooser {
pub(crate) fn new(
connection: Arc<CdpConnection>,
session_id: String,
frame_id: String,
backend_node_id: Option<i32>,
is_multiple: bool,
) -> Self {
Self {
connection,
session_id,
frame_id,
backend_node_id,
is_multiple,
}
}
pub fn is_multiple(&self) -> bool {
self.is_multiple
}
#[instrument(level = "debug", skip(self, files), fields(file_count = files.len()))]
pub async fn set_files<P: AsRef<Path>>(&self, files: &[P]) -> Result<(), LocatorError> {
if !self.is_multiple && files.len() > 1 {
return Err(LocatorError::EvaluationError(
"Cannot set multiple files on a single file input".to_string(),
));
}
let file_paths: Vec<String> = files
.iter()
.map(|p| p.as_ref().to_string_lossy().into_owned())
.collect();
debug!("Setting {} files on file input", file_paths.len());
self.connection
.send_command::<_, serde_json::Value>(
"DOM.setFileInputFiles",
Some(SetFileInputFilesParams {
files: file_paths,
node_id: None,
backend_node_id: self.backend_node_id,
object_id: None,
}),
Some(&self.session_id),
)
.await?;
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct FilePayload {
pub name: String,
pub mime_type: String,
pub buffer: Vec<u8>,
}
impl FilePayload {
pub fn new(name: impl Into<String>, mime_type: impl Into<String>, buffer: Vec<u8>) -> Self {
Self {
name: name.into(),
mime_type: mime_type.into(),
buffer,
}
}
pub fn from_text(name: impl Into<String>, content: impl Into<String>) -> Self {
Self {
name: name.into(),
mime_type: "text/plain".to_string(),
buffer: content.into().into_bytes(),
}
}
pub fn from_json(name: impl Into<String>, content: impl Into<String>) -> Self {
Self {
name: name.into(),
mime_type: "application/json".to_string(),
buffer: content.into().into_bytes(),
}
}
pub fn from_html(name: impl Into<String>, content: impl Into<String>) -> Self {
Self {
name: name.into(),
mime_type: "text/html".to_string(),
buffer: content.into().into_bytes(),
}
}
}