use futures::{stream::FuturesUnordered, StreamExt}; use once_cell::sync::OnceCell; use paris::info; use scrap::Display; use std::{borrow::Borrow, sync::Arc}; use tokio::{sync::Mutex, 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 fn global() -> &'static Picker { static SCREEN_COLOR_PICKER: OnceCell = OnceCell::new(); SCREEN_COLOR_PICKER.get_or_init(|| Picker { screens: Arc::new(Mutex::new(vec![])), screenshots: Arc::new(Mutex::new(vec![])), display_configs: Arc::new(Mutex::new( config::Manager::global().get_config().display_configs, )), }) } 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, 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) } }