use futures::{stream::FuturesUnordered, StreamExt}; use paris::info; use scrap::Display; use std::sync::Arc; use tokio::{ sync::{Mutex, OnceCell}, task, }; use crate::picker::{config, screen::Screen}; use super::{ config::DisplayConfig, display_picker::DisplayPicker, screenshot::{Screenshot, ScreenshotDto}, }; pub struct Picker { pub screens: Arc>>, pub screenshots: Arc>>, pub display_configs: Arc>>, } impl Picker { pub async fn global() -> &'static Picker { static SCREEN_COLOR_PICKER: OnceCell = OnceCell::const_new(); SCREEN_COLOR_PICKER .get_or_init(|| async { Picker { screens: Arc::new(Mutex::new(vec![])), screenshots: Arc::new(Mutex::new(vec![])), display_configs: Arc::new(Mutex::new( config::Manager::global().get_config().await.display_configs, )), } }) .await } pub async fn list_displays(&self) -> anyhow::Result> { let mut configs = self.display_configs.lock().await; let displays = Display::all() .map_err(|error| anyhow::anyhow!("Can not get all of displays. {}", error))?; configs.clear(); let mut futs = FuturesUnordered::new(); for (index, display) in displays.iter().enumerate() { let height = display.height(); let width = display.width(); let config = DisplayConfig::default(index, index, width, height); configs.push(config); } for config in configs.iter() { futs.push(async move { let join = task::spawn(Self::preview_display_by_config(config.clone())); join.await? }); } let mut bitmap_string_list = vec![]; while let Some(bitmap_string) = futs.next().await { match bitmap_string { Ok(bitmap_string) => { bitmap_string_list.push(bitmap_string); } Err(error) => { anyhow::bail!("can not convert to base64 image. {}", error); } } } Ok(bitmap_string_list) } pub async fn preview_display_by_config(config: DisplayConfig) -> anyhow::Result { let start = time::Instant::now(); let mut picker = DisplayPicker::from_config(config)?; let screenshot = picker.take_screenshot()?; info!("Take Screenshot Spend: {}", start.elapsed()); anyhow::Ok(screenshot.to_dto().await) } pub async fn get_screenshot_by_config( &self, config: DisplayConfig, ) -> anyhow::Result { let start = time::Instant::now(); let mut picker = DisplayPicker::from_config(config)?; let screenshot = picker.take_screenshot()?; info!("Take Screenshot Spend: {}", start.elapsed()); anyhow::Ok(screenshot.to_dto().await) } }