From 5293ed52ffd8a3cbcdefabdaffc789f47225cbab Mon Sep 17 00:00:00 2001 From: Ivan Li Date: Thu, 12 Jan 2023 13:44:54 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E5=AE=9E=E6=97=B6?= =?UTF-8?q?=E4=BF=9D=E5=AD=98=E9=85=8D=E7=BD=AE=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/core/core.rs | 2 +- src-tauri/src/main.rs | 27 +++++++++++++----- src-tauri/src/picker/config/manger.rs | 31 +++++++++++--------- src-tauri/src/picker/manager.rs | 28 +++++++++++------- src-tauri/tauri.conf.json | 2 +- src/configurator/configurator.tsx | 41 ++++++++++++++++++++------- 6 files changed, 87 insertions(+), 44 deletions(-) diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs index ef5c2d1..b33abcd 100644 --- a/src-tauri/src/core/core.rs +++ b/src-tauri/src/core/core.rs @@ -95,7 +95,7 @@ impl CoreManager { let mut futs = vec![]; if let AmbientLightMode::Follow = *lock { drop(lock); - let configs = Picker::global().display_configs.lock().await; + let configs = Picker::global().await.display_configs.lock().await; let (tx, mut rx) = mpsc::channel(10); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index c7ed0b1..165aac2 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -18,7 +18,7 @@ use std::vec; #[tauri::command] async fn take_snapshot() -> Vec { - let manager = Picker::global(); + let manager = Picker::global().await; let start = time::Instant::now(); let base64_bitmap_list = match manager.list_displays().await { @@ -42,12 +42,10 @@ async fn get_screenshot_by_config(config: DisplayConfig) -> Result { - Ok(screenshot_dto) - } + Ok(screenshot_dto) => Ok(screenshot_dto), Err(error) => { error!("get_screenshot_by_config failed. {}", error); Err(format!("get_screenshot_by_config failed. {}", error)) @@ -56,11 +54,25 @@ async fn get_screenshot_by_config(config: DisplayConfig) -> Result picker::config::Configuration { - let configuration = picker::config::Manager::global().get_config(); +async fn get_picker_config() -> picker::config::Configuration { + let configuration = picker::config::Manager::global().get_config().await; info!("configuration: {:?}", configuration); configuration } +#[tauri::command] +async fn write_picker_config(config: picker::config::Configuration) -> Result<(), String> { + let manager = picker::config::Manager::global(); + let path = picker::config::Manager::get_config_file_path(); + info!("log save in {:?}", path.to_str()); + manager.set_config(&config).await; + match picker::config::Manager::write_config_to_disk(path, &config) { + Ok(_) => Ok(()), + Err(err) => { + error!("can not write picker config. {:?}", err); + Err(format!("can not write picker config. {:?}", err)) + } + } +} #[tauri::command] async fn play_mode(target_mode: AmbientLightMode) { @@ -78,6 +90,7 @@ async fn main() { play_mode, get_picker_config, get_screenshot_by_config, + write_picker_config, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src-tauri/src/picker/config/manger.rs b/src-tauri/src/picker/config/manger.rs index d21b704..d8751da 100644 --- a/src-tauri/src/picker/config/manger.rs +++ b/src-tauri/src/picker/config/manger.rs @@ -2,12 +2,13 @@ use std::{ env::current_dir, fs::{self, File}, io::Read, - path::PathBuf, + path::PathBuf, sync::Arc, }; use once_cell::sync::OnceCell; +use paris::info; use serde::{Deserialize, Serialize}; -use tauri::api::path::config_dir; +use tauri::{api::path::config_dir, async_runtime::Mutex}; use super::DisplayConfig; @@ -26,9 +27,8 @@ impl Configuration { } } -#[derive(Serialize, Deserialize)] pub struct Manager { - config: Configuration, + config: Arc>, } impl Manager { @@ -43,7 +43,7 @@ impl Manager { } pub fn new(config: Configuration) -> Self { - Self { config } + Self { config: Arc::new(Mutex::new(config)) } } pub fn get_config_file_path() -> PathBuf { @@ -70,16 +70,21 @@ impl Manager { .map_err(|error| anyhow::anyhow!("can not parse config file contents. {}", error)) } - pub fn write_config_to_disk(&self, config_file_path: PathBuf) -> anyhow::Result<()> { - let contents = serde_json::to_string(&self.config) + pub fn write_config_to_disk(config_file_path: PathBuf, config: &Configuration) -> anyhow::Result<()> { + let contents = serde_json::to_string(config) .map_err(|error| anyhow::anyhow!("can not serialize config. {}", error))?; + info!("contents: {}", contents); fs::write(config_file_path, contents.as_bytes()) .map_err(|error| anyhow::anyhow!("can not write config file. {}", error))?; Ok(()) } - pub fn get_config(&self) -> Configuration { - self.config.clone() + pub async fn get_config(&self) -> Configuration { + self.config.lock().await.clone() + } + pub async fn set_config(&self, new_config: &Configuration) { + let mut config = self.config.lock().await; + *config = new_config.clone(); } } @@ -93,13 +98,13 @@ mod tests { use crate::picker::config::Configuration; - #[test] - fn write_config_to_disk_should_be_successful() { + #[tokio::test] + async fn write_config_to_disk_should_be_successful() { let temp = TestDir::temp().create("config_dir", test_dir::FileType::Dir); let config_file_path = temp.path("config_dir").join("picker.config.json"); let manager = crate::picker::config::manger::Manager::default(); - manager - .write_config_to_disk(config_file_path.clone()) + crate::picker::config::manger::Manager + ::write_config_to_disk(config_file_path.clone(), &Configuration::default()) .unwrap(); let contents = fs::read_to_string(config_file_path.clone()).unwrap(); diff --git a/src-tauri/src/picker/manager.rs b/src-tauri/src/picker/manager.rs index 0cfb114..75c9726 100644 --- a/src-tauri/src/picker/manager.rs +++ b/src-tauri/src/picker/manager.rs @@ -1,9 +1,11 @@ use futures::{stream::FuturesUnordered, StreamExt}; -use once_cell::sync::OnceCell; use paris::info; use scrap::Display; use std::sync::Arc; -use tokio::{sync::Mutex, task}; +use tokio::{ + sync::{Mutex, OnceCell}, + task, +}; use crate::picker::{config, screen::Screen}; @@ -20,16 +22,20 @@ pub struct Picker { } impl Picker { - pub fn global() -> &'static Picker { - static SCREEN_COLOR_PICKER: OnceCell = OnceCell::new(); + pub async fn global() -> &'static Picker { + static SCREEN_COLOR_PICKER: OnceCell = OnceCell::const_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, - )), - }) + 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> { diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index aaa7344..3e8cdea 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -28,7 +28,7 @@ "icons/icon.icns", "icons/icon.ico" ], - "identifier": "com.tauri.dev", + "identifier": "cc.ivanli.ambient", "longDescription": "", "macOS": { "entitlements": null, diff --git a/src/configurator/configurator.tsx b/src/configurator/configurator.tsx index ea51bd7..b6b361a 100644 --- a/src/configurator/configurator.tsx +++ b/src/configurator/configurator.tsx @@ -22,6 +22,11 @@ const getScreenshotByConfig = async (config: DisplayConfig) => { config, }); }; +const writePickerConfig = async (config: PickerConfiguration) => { + return await invoke('write_picker_config', { + config, + }); +}; export const Configurator: FC = () => { const { loading: pendingPickerConfig, result: savedPickerConfig } = useAsync( @@ -34,14 +39,25 @@ export const Configurator: FC = () => { const [screenshotOfDisplays, setScreenshotOfDisplays] = useState([]); - const { loading: pendingGetLedColorsByConfig, execute: onPickerChange } = + const { loading: pendingGetLedColorsByConfig, execute: onDisplayConfigChange } = useAsyncCallback(async (value: DisplayConfig) => { - console.log(value); + console.log('onDisplayConfigChange', value); const screenshot = await getScreenshotByConfig(value); setScreenshotOfDisplays((old) => { const index = old.findIndex((it) => it.config.id === screenshot.config.id); - console.log({ old, n: update(index, screenshot, old) }); - return update(index, screenshot, old); + const newValue = update(index, screenshot, old); + console.log({ old, n: newValue }); + savedPickerConfig && + writePickerConfig({ + ...savedPickerConfig, + display_configs: newValue.map((it) => it.config), + }).then(() => { + console.log('writing config is successful.', { + ...savedPickerConfig, + display_configs: newValue.map((it) => it.config), + }); + }); + return newValue; }); console.log('screenshot', screenshot); @@ -51,15 +67,18 @@ export const Configurator: FC = () => { useEffect(() => { const displayConfigs = savedPickerConfig?.display_configs; - if (displayConfigs) { + console.log('displayConfigs change', displayConfigs); + if (displayConfigs && defaultScreenshotOfDisplays) { setDisplayConfigs(displayConfigs); - } - }, [savedPickerConfig]); - useEffect(() => { - if (defaultScreenshotOfDisplays) { setScreenshotOfDisplays(defaultScreenshotOfDisplays); + (async () => { + for (const config of displayConfigs) { + await onDisplayConfigChange(config); + } + })().then(); } - }, [defaultScreenshotOfDisplays]); + }, [savedPickerConfig, onDisplayConfigChange, defaultScreenshotOfDisplays]); + useEffect(() => {}, [defaultScreenshotOfDisplays]); const displays = useMemo(() => { if (screenshotOfDisplays) { @@ -69,7 +88,7 @@ export const Configurator: FC = () => { key={index} config={screenshot.config} screenshot={screenshot} - onChange={(value) => onPickerChange(value)} + onChange={(value) => onDisplayConfigChange(value)} /> )); }