Compare commits
No commits in common. "4ad78ae5cc9b17a0b3646749305b8e07b091a018" and "1c38fd970e97ca9c54004af70fb9ce58d8f8b083" have entirely different histories.
4ad78ae5cc
...
1c38fd970e
@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
twin: {
|
|
||||||
preset: 'emotion',
|
|
||||||
},
|
|
||||||
};
|
|
@ -10,25 +10,18 @@
|
|||||||
"tauri": "tauri"
|
"tauri": "tauri"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.10.5",
|
|
||||||
"@emotion/styled": "^11.10.5",
|
|
||||||
"@tauri-apps/api": "^1.1.0",
|
"@tauri-apps/api": "^1.1.0",
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-async-hook": "^4.0.0",
|
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/plugin-transform-react-jsx": "^7.19.0",
|
|
||||||
"@emotion/babel-plugin-jsx-pragmatic": "^0.2.0",
|
|
||||||
"@emotion/serialize": "^1.1.1",
|
|
||||||
"@tauri-apps/cli": "^1.1.0",
|
"@tauri-apps/cli": "^1.1.0",
|
||||||
"@types/node": "^18.7.10",
|
"@types/node": "^18.7.10",
|
||||||
"@types/react": "^18.0.15",
|
"@types/react": "^18.0.15",
|
||||||
"@types/react-dom": "^18.0.6",
|
"@types/react-dom": "^18.0.6",
|
||||||
"@vitejs/plugin-react": "^2.0.0",
|
"@vitejs/plugin-react": "^2.0.0",
|
||||||
"autoprefixer": "^10.4.13",
|
"autoprefixer": "^10.4.13",
|
||||||
"babel-plugin-macros": "^3.1.0",
|
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.26.0",
|
||||||
"eslint-plugin-jsx-a11y": "^6.6.1",
|
"eslint-plugin-jsx-a11y": "^6.6.1",
|
||||||
@ -37,7 +30,6 @@
|
|||||||
"postcss": "^8.4.19",
|
"postcss": "^8.4.19",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"tailwindcss": "^3.2.4",
|
"tailwindcss": "^3.2.4",
|
||||||
"twin.macro": "^3.1.0",
|
|
||||||
"typescript": "^4.6.4",
|
"typescript": "^4.6.4",
|
||||||
"vite": "^3.0.2"
|
"vite": "^3.0.2"
|
||||||
}
|
}
|
||||||
|
849
pnpm-lock.yaml
generated
849
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
6
postcss.config.cjs
Normal file
6
postcss.config.cjs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
@ -118,40 +118,38 @@ impl CoreManager {
|
|||||||
let mut global_colors = HashMap::new();
|
let mut global_colors = HashMap::new();
|
||||||
while let Some(screenshot) = rx.recv().await {
|
while let Some(screenshot) = rx.recv().await {
|
||||||
let start_at = Instant::now();
|
let start_at = Instant::now();
|
||||||
let colors = screenshot.get_top_colors();
|
match screenshot.get_top_colors().await {
|
||||||
let start = screenshot
|
Ok(colors) => {
|
||||||
.get_top_of_led_start_at()
|
let start = screenshot.get_top_of_led_start_at().min(screenshot.get_top_of_led_end_at());
|
||||||
.min(screenshot.get_top_of_led_end_at());
|
|
||||||
|
|
||||||
let colors_len = colors.len();
|
let colors_len = colors.len();
|
||||||
for (index, color) in colors.into_iter().enumerate() {
|
for (index, color) in colors.into_iter().enumerate() {
|
||||||
global_colors.insert(index + start, color);
|
global_colors.insert(index + start, color);
|
||||||
}
|
|
||||||
|
|
||||||
info!(
|
|
||||||
"led count: {}, spend: {:?}",
|
|
||||||
global_colors.len(),
|
|
||||||
start_at.elapsed()
|
|
||||||
);
|
|
||||||
|
|
||||||
if global_colors.len() == 60 {
|
|
||||||
let mut colors = vec![];
|
|
||||||
for index in 0..global_colors.len() {
|
|
||||||
colors.push(*global_colors.get(&index).unwrap());
|
|
||||||
}
|
|
||||||
global_colors = HashMap::new();
|
|
||||||
match rpc::manager::Manager::global()
|
|
||||||
.publish_led_colors(&colors)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => {
|
|
||||||
info!("publish successful",);
|
|
||||||
}
|
}
|
||||||
Err(error) => {
|
|
||||||
warn!("publish led colors failed. {}", error);
|
info!("led count: {}, spend: {:?}", global_colors.len(), start_at.elapsed());
|
||||||
|
|
||||||
|
if global_colors.len() == 60 {
|
||||||
|
let mut colors = vec![];
|
||||||
|
for index in 0..global_colors.len() {
|
||||||
|
colors.push(*global_colors.get(&index).unwrap());
|
||||||
|
}
|
||||||
|
global_colors = HashMap::new();
|
||||||
|
match rpc::manager::Manager::global()
|
||||||
|
.publish_led_colors(&colors)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => {
|
||||||
|
info!("publish successful",);
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
warn!("publish led colors failed. {}", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Err(_) => {}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
all(not(debug_assertions), target_os = "windows"),
|
all(not(debug_assertions), target_os = "windows"),
|
||||||
windows_subsystem = "windows"
|
windows_subsystem = "windows"
|
||||||
)]
|
)]
|
||||||
#![feature(bool_to_option)]
|
|
||||||
|
|
||||||
mod core;
|
mod core;
|
||||||
mod picker;
|
mod picker;
|
||||||
@ -11,12 +10,22 @@ mod rpc;
|
|||||||
use crate::core::AmbientLightMode;
|
use crate::core::AmbientLightMode;
|
||||||
use crate::core::CoreManager;
|
use crate::core::CoreManager;
|
||||||
use paris::*;
|
use paris::*;
|
||||||
|
use picker::led_color::LedColor;
|
||||||
use picker::manager::Picker;
|
use picker::manager::Picker;
|
||||||
use picker::screenshot::ScreenshotDto;
|
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn take_snapshot() -> Vec<ScreenshotDto> {
|
async fn refresh_displays() {
|
||||||
|
match Picker::global().refresh_displays().await {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(error) => {
|
||||||
|
error!("{}", error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
async fn take_snapshot() -> Vec<String> {
|
||||||
let manager = Picker::global();
|
let manager = Picker::global();
|
||||||
|
|
||||||
let start = time::Instant::now();
|
let start = time::Instant::now();
|
||||||
@ -31,15 +40,22 @@ async fn take_snapshot() -> Vec<ScreenshotDto> {
|
|||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
info!("截图耗时 {} s", start.elapsed().as_seconds_f32());
|
info!("截图花费 {} s", start.elapsed().as_seconds_f32());
|
||||||
base64_bitmap_list
|
base64_bitmap_list
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn get_picker_config() -> picker::config::Configuration {
|
async fn get_led_strip_colors() -> Result<Vec<LedColor>, String> {
|
||||||
let configuration = picker::config::Manager::global().get_config();
|
let colors = Picker::global().get_led_strip_colors().await;
|
||||||
info!("configuration: {:?}", configuration);
|
match colors {
|
||||||
configuration
|
Ok(colors) => {
|
||||||
|
rpc::manager::Manager::global()
|
||||||
|
.publish_led_colors(&colors.to_vec())
|
||||||
|
.await;
|
||||||
|
Ok(colors)
|
||||||
|
}
|
||||||
|
Err(error) => Err(format!("{}", error)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@ -55,8 +71,9 @@ async fn main() {
|
|||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
take_snapshot,
|
take_snapshot,
|
||||||
|
refresh_displays,
|
||||||
|
get_led_strip_colors,
|
||||||
play_mode,
|
play_mode,
|
||||||
get_picker_config,
|
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
|
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||||
pub struct LedStripConfig {
|
pub struct LedStripConfig {
|
||||||
pub index: usize,
|
pub index: usize,
|
||||||
pub global_start_position: usize,
|
pub global_start_position: usize,
|
||||||
pub global_end_position: usize,
|
pub global_end_position: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
|
#[derive(Clone, Copy, Serialize, Deserialize)]
|
||||||
pub struct DisplayConfig {
|
pub struct DisplayConfig {
|
||||||
pub index_of_display: usize,
|
pub index_of_display: usize,
|
||||||
pub display_width: usize,
|
pub display_width: usize,
|
||||||
pub display_height: usize,
|
pub display_height: usize,
|
||||||
pub top_led_strip: Option<LedStripConfig>,
|
pub top_led_strip: LedStripConfig,
|
||||||
pub bottom_led_strip: Option<LedStripConfig>,
|
pub bottom_led_strip: LedStripConfig,
|
||||||
pub left_led_strip: Option<LedStripConfig>,
|
pub left_led_strip: LedStripConfig,
|
||||||
pub right_led_strip: Option<LedStripConfig>,
|
pub right_led_strip: LedStripConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DisplayConfig {
|
impl DisplayConfig {
|
||||||
@ -24,10 +24,26 @@ impl DisplayConfig {
|
|||||||
index_of_display,
|
index_of_display,
|
||||||
display_width,
|
display_width,
|
||||||
display_height,
|
display_height,
|
||||||
top_led_strip: None,
|
top_led_strip: LedStripConfig {
|
||||||
bottom_led_strip: None,
|
index: 0,
|
||||||
left_led_strip: None,
|
global_start_position: 0,
|
||||||
right_led_strip: None,
|
global_end_position: 0,
|
||||||
|
},
|
||||||
|
bottom_led_strip: LedStripConfig {
|
||||||
|
index: 0,
|
||||||
|
global_start_position: 0,
|
||||||
|
global_end_position: 0,
|
||||||
|
},
|
||||||
|
left_led_strip: LedStripConfig {
|
||||||
|
index: 0,
|
||||||
|
global_start_position: 0,
|
||||||
|
global_end_position: 0,
|
||||||
|
},
|
||||||
|
right_led_strip: LedStripConfig {
|
||||||
|
index: 0,
|
||||||
|
global_start_position: 0,
|
||||||
|
global_end_position: 0,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,10 @@ use tauri::api::path::config_dir;
|
|||||||
|
|
||||||
use super::DisplayConfig;
|
use super::DisplayConfig;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct Configuration {
|
pub struct Configuration {
|
||||||
pub config_version: u8,
|
config_version: u8,
|
||||||
pub display_configs: Vec<DisplayConfig>,
|
display_configs: Vec<DisplayConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Configuration {
|
impl Configuration {
|
||||||
@ -77,10 +77,6 @@ impl Manager {
|
|||||||
.map_err(|error| anyhow::anyhow!("can not write config file. {}", error))?;
|
.map_err(|error| anyhow::anyhow!("can not write config file. {}", error))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_config(&self) -> Configuration {
|
|
||||||
self.config.clone()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -118,8 +114,7 @@ mod tests {
|
|||||||
})
|
})
|
||||||
.to_string()
|
.to_string()
|
||||||
.as_bytes(),
|
.as_bytes(),
|
||||||
)
|
).unwrap();
|
||||||
.unwrap();
|
|
||||||
let _manager =
|
let _manager =
|
||||||
crate::picker::config::manger::Manager::read_config_from_disk(config_file_path.clone())
|
crate::picker::config::manger::Manager::read_config_from_disk(config_file_path.clone())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use color_space::{Hsv, Rgb};
|
use color_space::{Hsv, Rgb};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct LedColor {
|
pub struct LedColor {
|
||||||
bits: [u8; 3],
|
bits: [u8; 3],
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,14 @@ use futures::{stream::FuturesUnordered, StreamExt};
|
|||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use paris::info;
|
use paris::info;
|
||||||
use scrap::Display;
|
use scrap::Display;
|
||||||
use std::{borrow::Borrow, sync::Arc};
|
use std::sync::Arc;
|
||||||
use tokio::{sync::Mutex, task};
|
use tokio::{sync::Mutex, task};
|
||||||
|
|
||||||
use crate::picker::{config, screen::Screen};
|
use crate::picker::{config::LedStripConfig, screen::Screen};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
config::DisplayConfig,
|
config::DisplayConfig, display_picker::DisplayPicker, led_color::LedColor,
|
||||||
display_picker::DisplayPicker,
|
screenshot::Screenshot,
|
||||||
screenshot::{Screenshot, ScreenshotDto},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Picker {
|
pub struct Picker {
|
||||||
@ -26,14 +25,64 @@ impl Picker {
|
|||||||
SCREEN_COLOR_PICKER.get_or_init(|| Picker {
|
SCREEN_COLOR_PICKER.get_or_init(|| Picker {
|
||||||
screens: Arc::new(Mutex::new(vec![])),
|
screens: Arc::new(Mutex::new(vec![])),
|
||||||
screenshots: Arc::new(Mutex::new(vec![])),
|
screenshots: Arc::new(Mutex::new(vec![])),
|
||||||
display_configs: Arc::new(Mutex::new(
|
display_configs: Arc::new(Mutex::new(vec![
|
||||||
config::Manager::global().get_config().display_configs,
|
DisplayConfig {
|
||||||
)),
|
index_of_display: 1,
|
||||||
|
display_width: 1920,
|
||||||
|
display_height: 1200,
|
||||||
|
top_led_strip: LedStripConfig {
|
||||||
|
index: 1,
|
||||||
|
global_start_position: 59,
|
||||||
|
global_end_position: 32,
|
||||||
|
},
|
||||||
|
bottom_led_strip: LedStripConfig {
|
||||||
|
index: 0,
|
||||||
|
global_start_position: 0,
|
||||||
|
global_end_position: 0,
|
||||||
|
},
|
||||||
|
left_led_strip: LedStripConfig {
|
||||||
|
index: 0,
|
||||||
|
global_start_position: 0,
|
||||||
|
global_end_position: 0,
|
||||||
|
},
|
||||||
|
right_led_strip: LedStripConfig {
|
||||||
|
index: 0,
|
||||||
|
global_start_position: 0,
|
||||||
|
global_end_position: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
DisplayConfig {
|
||||||
|
index_of_display: 0,
|
||||||
|
display_width: 3008,
|
||||||
|
display_height: 1692,
|
||||||
|
top_led_strip: LedStripConfig {
|
||||||
|
index: 0,
|
||||||
|
global_start_position: 31,
|
||||||
|
global_end_position: 0,
|
||||||
|
},
|
||||||
|
bottom_led_strip: LedStripConfig {
|
||||||
|
index: 0,
|
||||||
|
global_start_position: 0,
|
||||||
|
global_end_position: 0,
|
||||||
|
},
|
||||||
|
left_led_strip: LedStripConfig {
|
||||||
|
index: 0,
|
||||||
|
global_start_position: 0,
|
||||||
|
global_end_position: 0,
|
||||||
|
},
|
||||||
|
right_led_strip: LedStripConfig {
|
||||||
|
index: 0,
|
||||||
|
global_start_position: 0,
|
||||||
|
global_end_position: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_displays(&self) -> anyhow::Result<Vec<ScreenshotDto>> {
|
pub async fn list_displays(&self) -> anyhow::Result<Vec<String>> {
|
||||||
let mut configs = self.display_configs.lock().await;
|
let mut configs = self.display_configs.lock().await;
|
||||||
|
let screenshots = self.screenshots.lock().await;
|
||||||
|
|
||||||
let displays = Display::all()
|
let displays = Display::all()
|
||||||
.map_err(|error| anyhow::anyhow!("Can not get all of displays. {}", error))?;
|
.map_err(|error| anyhow::anyhow!("Can not get all of displays. {}", error))?;
|
||||||
@ -48,9 +97,12 @@ impl Picker {
|
|||||||
configs.push(config);
|
configs.push(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
for config in configs.iter() {
|
for (index, display) in displays.iter().enumerate() {
|
||||||
|
let height = display.height();
|
||||||
|
let width = display.width();
|
||||||
|
let config = configs[index];
|
||||||
futs.push(async move {
|
futs.push(async move {
|
||||||
let join = task::spawn(Self::preview_display_by_config(config.clone()));
|
let join = task::spawn(Self::preview_display_by_config(config));
|
||||||
join.await?
|
join.await?
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -68,12 +120,63 @@ impl Picker {
|
|||||||
Ok(bitmap_string_list)
|
Ok(bitmap_string_list)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn preview_display_by_config(config: DisplayConfig) -> anyhow::Result<ScreenshotDto> {
|
pub async fn preview_display_by_config(config: DisplayConfig) -> anyhow::Result<String> {
|
||||||
let start = time::Instant::now();
|
let start = time::Instant::now();
|
||||||
let mut picker = DisplayPicker::from_config(config)?;
|
let mut picker = DisplayPicker::from_config(config)?;
|
||||||
let screenshot = picker.take_screenshot()?;
|
let screenshot = picker.take_screenshot()?;
|
||||||
info!("Take Screenshot Spend: {}", start.elapsed());
|
info!("Take Screenshot Spend: {}", start.elapsed());
|
||||||
|
|
||||||
anyhow::Ok(screenshot.to_dto().await)
|
anyhow::Ok(screenshot.to_webp_base64().await)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn refresh_displays(&self) -> anyhow::Result<()> {
|
||||||
|
// let displays = Display::all()
|
||||||
|
// .map_err(|error| anyhow::anyhow!("Can not get all of displays. {}", error))?;
|
||||||
|
// let mut screens = self.screens.lock().await;
|
||||||
|
// let mut screenshots = self.screenshots.lock().await;
|
||||||
|
// screens.clear();
|
||||||
|
// info!("number of displays: {}", displays.len());
|
||||||
|
// for display in displays {
|
||||||
|
// let height = display.height();
|
||||||
|
// let width = display.width();
|
||||||
|
// match Capturer::new(display) {
|
||||||
|
// Ok(capturer) => screens.push(Screen::new(capturer, width, height)),
|
||||||
|
// Err(error) => screens.push(Screen::new_failed(
|
||||||
|
// anyhow::anyhow!("{}", error),
|
||||||
|
// width,
|
||||||
|
// height,
|
||||||
|
// )),
|
||||||
|
// };
|
||||||
|
// screenshots.push(Screenshot::new(width, height));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// screens.reverse();
|
||||||
|
// screenshots.reverse();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn take_screenshots_for_all(&self) -> anyhow::Result<Vec<Screenshot>> {
|
||||||
|
let mut screens = self.screens.lock().await;
|
||||||
|
let screenshots = self.screenshots.lock().await;
|
||||||
|
for (index, screen) in screens.iter_mut().enumerate() {
|
||||||
|
let bitmap = screen.take().map_err(|error| {
|
||||||
|
anyhow::anyhow!("take screenshot for display failed. {}", error)
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
Ok(screenshots.to_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_led_strip_colors(&self) -> anyhow::Result<Vec<LedColor>> {
|
||||||
|
let screenshots = self.screenshots.lock().await;
|
||||||
|
let mut colors = Vec::new();
|
||||||
|
for screenshot in screenshots.iter() {
|
||||||
|
let result = screenshot
|
||||||
|
.get_top_colors()
|
||||||
|
.await
|
||||||
|
.map_err(|error| anyhow::anyhow!("get top colors failed. {}", error))?;
|
||||||
|
colors.extend_from_slice(&result);
|
||||||
|
}
|
||||||
|
Ok(colors)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,233 +1,101 @@
|
|||||||
use std::iter;
|
use std::ops::Range;
|
||||||
|
|
||||||
use color_space::{Hsv, Rgb};
|
use color_space::{Hsv, Rgb};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
config::{DisplayConfig, LedStripConfig},
|
config::{DisplayConfig, LedStripConfig},
|
||||||
led_color::LedColor,
|
led_color::LedColor,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Point = (usize, usize);
|
#[derive(Clone)]
|
||||||
type LedSamplePoints = Vec<Point>;
|
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
|
||||||
struct ScreenSamplePoints {
|
|
||||||
pub top: Vec<LedSamplePoints>,
|
|
||||||
pub bottom: Vec<LedSamplePoints>,
|
|
||||||
pub left: Vec<LedSamplePoints>,
|
|
||||||
pub right: Vec<LedSamplePoints>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
|
||||||
pub struct Screenshot {
|
pub struct Screenshot {
|
||||||
bitmap: Vec<u8>,
|
bitmap: Vec<u8>,
|
||||||
config: DisplayConfig,
|
config: DisplayConfig,
|
||||||
sample_points: ScreenSamplePoints,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Screenshot {
|
impl Screenshot {
|
||||||
pub fn new(bitmap: Vec<u8>, config: DisplayConfig) -> Self {
|
pub fn new(bitmap: Vec<u8>, config: DisplayConfig) -> Self {
|
||||||
Self {
|
Self { bitmap, config }
|
||||||
bitmap,
|
|
||||||
config,
|
|
||||||
sample_points: Self::get_sample_points(config),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_sample_points(config: DisplayConfig) -> ScreenSamplePoints {
|
pub async fn get_top_colors(&self) -> anyhow::Result<Vec<LedColor>> {
|
||||||
let top = match config.top_led_strip {
|
self.get_x_colors(XPosition::Top, self.config.top_led_strip)
|
||||||
Some(led_strip_config) => Self::get_one_edge_sample_points(
|
.await
|
||||||
config.display_height / 8,
|
|
||||||
config.display_width,
|
|
||||||
led_strip_config
|
|
||||||
.global_start_position
|
|
||||||
.abs_diff(led_strip_config.global_end_position),
|
|
||||||
5,
|
|
||||||
),
|
|
||||||
None => {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let bottom: Vec<LedSamplePoints> = match config.top_led_strip {
|
|
||||||
Some(led_strip_config) => {
|
|
||||||
let points = Self::get_one_edge_sample_points(
|
|
||||||
config.display_height / 9,
|
|
||||||
config.display_width,
|
|
||||||
led_strip_config
|
|
||||||
.global_start_position
|
|
||||||
.abs_diff(led_strip_config.global_end_position),
|
|
||||||
5,
|
|
||||||
);
|
|
||||||
points
|
|
||||||
.into_iter()
|
|
||||||
.map(|groups| -> Vec<Point> {
|
|
||||||
groups
|
|
||||||
.into_iter()
|
|
||||||
.map(|(x, y)| (x, config.display_height - y))
|
|
||||||
.collect()
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let left: Vec<LedSamplePoints> = match config.top_led_strip {
|
|
||||||
Some(led_strip_config) => {
|
|
||||||
let points = Self::get_one_edge_sample_points(
|
|
||||||
config.display_width / 16,
|
|
||||||
config.display_height,
|
|
||||||
led_strip_config
|
|
||||||
.global_start_position
|
|
||||||
.abs_diff(led_strip_config.global_end_position),
|
|
||||||
5,
|
|
||||||
);
|
|
||||||
points
|
|
||||||
.into_iter()
|
|
||||||
.map(|groups| -> Vec<Point> {
|
|
||||||
groups.into_iter().map(|(x, y)| (y, x)).collect()
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let right: Vec<LedSamplePoints> = match config.top_led_strip {
|
|
||||||
Some(led_strip_config) => {
|
|
||||||
let points = Self::get_one_edge_sample_points(
|
|
||||||
config.display_width / 16,
|
|
||||||
config.display_height,
|
|
||||||
led_strip_config
|
|
||||||
.global_start_position
|
|
||||||
.abs_diff(led_strip_config.global_end_position),
|
|
||||||
5,
|
|
||||||
);
|
|
||||||
points
|
|
||||||
.into_iter()
|
|
||||||
.map(|groups| -> Vec<Point> {
|
|
||||||
groups
|
|
||||||
.into_iter()
|
|
||||||
.map(|(x, y)| (y, config.display_width - x))
|
|
||||||
.collect()
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ScreenSamplePoints {
|
|
||||||
top,
|
|
||||||
bottom,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
pub async fn get_bottom_colors(&self) -> anyhow::Result<Vec<LedColor>> {
|
||||||
fn get_one_edge_sample_points(
|
self.get_x_colors(XPosition::Bottom, self.config.bottom_led_strip)
|
||||||
width: usize,
|
.await
|
||||||
length: usize,
|
|
||||||
leds: usize,
|
|
||||||
single_axis_points: usize,
|
|
||||||
) -> Vec<LedSamplePoints> {
|
|
||||||
let cell_size_x = length as f64 / single_axis_points as f64 / leds as f64;
|
|
||||||
let cell_size_y = width / single_axis_points;
|
|
||||||
|
|
||||||
let point_start_y = cell_size_y / 2;
|
|
||||||
let point_start_x = cell_size_x / 2.0;
|
|
||||||
let point_y_list: Vec<usize> = (point_start_y..width).step_by(cell_size_y).collect();
|
|
||||||
let point_x_list: Vec<usize> = iter::successors(Some(point_start_x), |i| {
|
|
||||||
let next = i + cell_size_x;
|
|
||||||
(next < (width as f64)).then_some(next)
|
|
||||||
})
|
|
||||||
.map(|i| i as usize)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let points: Vec<Point> = point_x_list
|
|
||||||
.into_iter()
|
|
||||||
.zip(point_y_list.into_iter())
|
|
||||||
.collect();
|
|
||||||
points
|
|
||||||
.chunks(single_axis_points * single_axis_points)
|
|
||||||
.into_iter()
|
|
||||||
.map(|points| Vec::from(points))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_colors(&self) -> DisplayColorsOfLedStrips {
|
|
||||||
let top = self
|
|
||||||
.get_one_edge_colors(&self.sample_points.top)
|
|
||||||
.into_iter()
|
|
||||||
.flat_map(|color| color.get_rgb())
|
|
||||||
.collect();
|
|
||||||
let bottom = self
|
|
||||||
.get_one_edge_colors(&self.sample_points.bottom)
|
|
||||||
.into_iter()
|
|
||||||
.flat_map(|color| color.get_rgb())
|
|
||||||
.collect();
|
|
||||||
let left = self
|
|
||||||
.get_one_edge_colors(&self.sample_points.left)
|
|
||||||
.into_iter()
|
|
||||||
.flat_map(|color| color.get_rgb())
|
|
||||||
.collect();
|
|
||||||
let right = self
|
|
||||||
.get_one_edge_colors(&self.sample_points.right)
|
|
||||||
.into_iter()
|
|
||||||
.flat_map(|color| color.get_rgb())
|
|
||||||
.collect();
|
|
||||||
DisplayColorsOfLedStrips {
|
|
||||||
top,
|
|
||||||
bottom,
|
|
||||||
left,
|
|
||||||
right,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_one_edge_colors(
|
|
||||||
&self,
|
|
||||||
sample_points_of_leds: &Vec<LedSamplePoints>,
|
|
||||||
) -> Vec<LedColor> {
|
|
||||||
let mut colors = vec![];
|
|
||||||
for led_points in sample_points_of_leds {
|
|
||||||
let mut r = 0.0;
|
|
||||||
let mut g = 0.0;
|
|
||||||
let mut b = 0.0;
|
|
||||||
let len = led_points.len() as f64;
|
|
||||||
for (x, y) in led_points {
|
|
||||||
let position = (x + y * self.config.display_width) * 4;
|
|
||||||
r += self.bitmap[position + 2] as f64;
|
|
||||||
g += self.bitmap[position + 1] as f64;
|
|
||||||
b += self.bitmap[position] as f64;
|
|
||||||
}
|
|
||||||
let color = LedColor::new((r / len) as u8, (g / len) as u8, (b / len) as u8);
|
|
||||||
// paris::info!("color: {:?}", color.get_rgb());
|
|
||||||
colors.push(color);
|
|
||||||
}
|
|
||||||
colors
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_top_colors(&self) -> Vec<LedColor> {
|
|
||||||
self.get_one_edge_colors(&self.sample_points.top)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_top_of_led_start_at(&self) -> usize {
|
pub fn get_top_of_led_start_at(&self) -> usize {
|
||||||
self.config
|
self.config.top_led_strip.global_start_position
|
||||||
.top_led_strip
|
|
||||||
.and_then(|c| Some(c.global_start_position))
|
|
||||||
.unwrap_or(0)
|
|
||||||
}
|
}
|
||||||
pub fn get_top_of_led_end_at(&self) -> usize {
|
pub fn get_top_of_led_end_at(&self) -> usize {
|
||||||
self.config
|
self.config.top_led_strip.global_end_position
|
||||||
.top_led_strip
|
}
|
||||||
.and_then(|c| Some(c.global_end_position))
|
|
||||||
.unwrap_or(0)
|
async fn get_x_colors(
|
||||||
|
&self,
|
||||||
|
position: XPosition,
|
||||||
|
strip_config: LedStripConfig,
|
||||||
|
) -> anyhow::Result<Vec<LedColor>> {
|
||||||
|
let bitmap = &self.bitmap;
|
||||||
|
let number_of_leds = strip_config
|
||||||
|
.global_start_position
|
||||||
|
.abs_diff(strip_config.global_end_position)
|
||||||
|
+ 1;
|
||||||
|
if number_of_leds == 0 {
|
||||||
|
return Ok(vec![]);
|
||||||
|
}
|
||||||
|
let cell_size_x = self.config.display_width / number_of_leds;
|
||||||
|
let cell_size_y = self.config.display_height / 8;
|
||||||
|
let cell_size = cell_size_x * cell_size_y;
|
||||||
|
let y_range = match position {
|
||||||
|
XPosition::Top => 20..cell_size_y + 20,
|
||||||
|
XPosition::Bottom => {
|
||||||
|
self.config.display_height - 20 - cell_size_y..self.config.display_height - 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.step_by(5);
|
||||||
|
|
||||||
|
let x_range = if strip_config.global_start_position < strip_config.global_end_position {
|
||||||
|
Either::Left(strip_config.global_start_position..=strip_config.global_end_position)
|
||||||
|
} else {
|
||||||
|
Either::Right(
|
||||||
|
(strip_config.global_end_position..=strip_config.global_start_position).rev(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut colors = Vec::new();
|
||||||
|
let stride = bitmap.len() / self.config.display_height;
|
||||||
|
|
||||||
|
for pos in x_range {
|
||||||
|
let mut r = 0.0;
|
||||||
|
let mut g = 0.0;
|
||||||
|
let mut b = 0.0;
|
||||||
|
let mut count = 0;
|
||||||
|
for x in (pos * cell_size_x..(pos + 1) * cell_size_x).step_by(5) {
|
||||||
|
for y in y_range.to_owned() {
|
||||||
|
let i = stride * y + 4 * x;
|
||||||
|
r += bitmap[i + 2] as f64;
|
||||||
|
g += bitmap[i + 1] as f64;
|
||||||
|
b += bitmap[i] as f64;
|
||||||
|
count+=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let rgb = Rgb::new(
|
||||||
|
r / count as f64,
|
||||||
|
g / count as f64,
|
||||||
|
b / count as f64,
|
||||||
|
);
|
||||||
|
let hsv = Hsv::from(rgb);
|
||||||
|
// info!("HSV: {:?}", [hsv.h, hsv.s, hsv.v]);
|
||||||
|
let color = LedColor::from_hsv(hsv.h, hsv.s, hsv.v);
|
||||||
|
// paris::info!("color: {:?}", color.get_rgb());
|
||||||
|
colors.push(color);
|
||||||
|
}
|
||||||
|
return Ok(colors);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn to_webp_base64(&self) -> String {
|
pub async fn to_webp_base64(&self) -> String {
|
||||||
@ -251,30 +119,9 @@ impl Screenshot {
|
|||||||
.encode(100.0);
|
.encode(100.0);
|
||||||
return base64::encode(&*webp_memory);
|
return base64::encode(&*webp_memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn to_dto(&self) -> ScreenshotDto {
|
|
||||||
let encode_image = self.to_webp_base64().await;
|
|
||||||
let config = self.config.clone();
|
|
||||||
let colors = self.get_colors();
|
|
||||||
ScreenshotDto {
|
|
||||||
encode_image,
|
|
||||||
config,
|
|
||||||
colors,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
enum XPosition {
|
||||||
pub struct ScreenshotDto {
|
Top,
|
||||||
pub config: DisplayConfig,
|
Bottom,
|
||||||
pub encode_image: String,
|
|
||||||
pub colors: DisplayColorsOfLedStrips,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
|
||||||
pub struct DisplayColorsOfLedStrips {
|
|
||||||
pub top: Vec<u8>,
|
|
||||||
pub bottom: Vec<u8>,
|
|
||||||
pub left: Vec<u8>,
|
|
||||||
pub right: Vec<u8>,
|
|
||||||
}
|
}
|
||||||
|
13
src/App.tsx
13
src/App.tsx
@ -1,9 +1,8 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
import reactLogo from './assets/react.svg';
|
import reactLogo from './assets/react.svg';
|
||||||
import { invoke } from '@tauri-apps/api/tauri';
|
import { invoke } from '@tauri-apps/api/tauri';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { Configurator } from './configurator/configurator';
|
|
||||||
|
|
||||||
type Mode = 'Flowing' | 'Follow' | null;
|
type Mode = 'Flowing' | 'Follow' | null;
|
||||||
|
|
||||||
@ -18,6 +17,10 @@ function App() {
|
|||||||
setScreenshots(base64TextList.map((text) => `data:image/webp;base64,${text}`));
|
setScreenshots(base64TextList.map((text) => `data:image/webp;base64,${text}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const refreshDisplays = useCallback(async () => {
|
||||||
|
await invoke('refresh_displays');
|
||||||
|
}, []);
|
||||||
|
|
||||||
const getLedStripColors = useCallback(async () => {
|
const getLedStripColors = useCallback(async () => {
|
||||||
setLedStripColors(await invoke('get_led_strip_colors'));
|
setLedStripColors(await invoke('get_led_strip_colors'));
|
||||||
}, []);
|
}, []);
|
||||||
@ -57,7 +60,7 @@ function App() {
|
|||||||
<button
|
<button
|
||||||
className="bg-black bg-opacity-20"
|
className="bg-black bg-opacity-20"
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => readPickerConfig()}
|
onClick={() => refreshDisplays()}
|
||||||
>
|
>
|
||||||
Refresh Displays
|
Refresh Displays
|
||||||
</button>
|
</button>
|
||||||
@ -96,7 +99,9 @@ function App() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex gap-5 justify-center">
|
<div className="flex gap-5 justify-center">
|
||||||
<Configurator />
|
<img src="/vite.svg" className="logo vite" alt="Vite logo" />
|
||||||
|
<img src="/tauri.svg" className="logo tauri" alt="Tauri logo" />
|
||||||
|
<img src={reactLogo} className="logo react" alt="React logo" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
import { HTMLAttributes } from 'react';
|
|
||||||
import { FC } from 'react';
|
|
||||||
import { DisplayConfig } from '../models/display-config';
|
|
||||||
import { LedStrip } from './led-strip';
|
|
||||||
|
|
||||||
export interface DisplayWithLedStripsProps extends HTMLAttributes<HTMLElement> {
|
|
||||||
config: DisplayConfig;
|
|
||||||
screenshot: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DisplayWithLedStrips: FC<DisplayWithLedStripsProps> = ({
|
|
||||||
config,
|
|
||||||
screenshot,
|
|
||||||
...htmlAttrs
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<section className="m-4 grid grid-rows-3 grid-cols-3 gr" {...htmlAttrs}>
|
|
||||||
<img src={screenshot} className="row-start-2 col-start-2" />
|
|
||||||
<LedStrip config={config.top_led_strip} className="row-start-1 col-start-2 h-1" />
|
|
||||||
<LedStrip config={config.left_led_strip} className="row-start-2 col-start-1 w-1" />
|
|
||||||
<LedStrip config={config.right_led_strip} className="row-start-2 col-start-3" />
|
|
||||||
<LedStrip config={config.bottom_led_strip} className="row-start-3 col-start-2" />
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
import { HTMLAttributes } from 'react';
|
|
||||||
import { FC } from 'react';
|
|
||||||
import { LedStripConfig } from '../models/led-strip-config';
|
|
||||||
|
|
||||||
export interface LedStripProps extends HTMLAttributes<HTMLElement> {
|
|
||||||
config: LedStripConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const LedStrip: FC<LedStripProps> = ({ config, ...htmlAttrs }) => {
|
|
||||||
return <section {...htmlAttrs}>...</section>;
|
|
||||||
};
|
|
@ -1,46 +0,0 @@
|
|||||||
import { invoke } from '@tauri-apps/api';
|
|
||||||
import { FC, useMemo } from 'react';
|
|
||||||
import { useAsync } from 'react-async-hook';
|
|
||||||
import { DisplayWithLedStrips } from './components/display-with-led-strips';
|
|
||||||
import { PickerConfiguration } from './models/picker-configuration';
|
|
||||||
|
|
||||||
const getPickerConfig = () => invoke<PickerConfiguration>('get_picker_config');
|
|
||||||
const getScreenshotOfDisplays = () =>
|
|
||||||
invoke<string[]>('take_snapshot').then((items) =>
|
|
||||||
items?.map((it) => `data:image/webp;base64,${it}`),
|
|
||||||
);
|
|
||||||
|
|
||||||
export const Configurator: FC = () => {
|
|
||||||
const { loading: pendingPickerConfig, result: pickerConfig } = useAsync(
|
|
||||||
getPickerConfig,
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const { loading: pendingScreenshotOfDisplays, result: screenshotOfDisplays } = useAsync(
|
|
||||||
getScreenshotOfDisplays,
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const displays = useMemo(() => {
|
|
||||||
if (pickerConfig && screenshotOfDisplays) {
|
|
||||||
return screenshotOfDisplays.map((screenshot, index) => (
|
|
||||||
<DisplayWithLedStrips
|
|
||||||
key={index}
|
|
||||||
config={pickerConfig.display_configs[index] ?? {}}
|
|
||||||
screenshot={screenshot}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}, [pickerConfig, screenshotOfDisplays]);
|
|
||||||
|
|
||||||
if (pendingPickerConfig || pendingScreenshotOfDisplays) {
|
|
||||||
return (
|
|
||||||
<section>
|
|
||||||
等待 {JSON.stringify({ pendingPickerConfig, pendingScreenshotOfDisplays })}
|
|
||||||
{displays}
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <section>{displays}</section>;
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
import { LedStripConfig } from './led-strip-config';
|
|
||||||
|
|
||||||
export class DisplayConfig {
|
|
||||||
index_of_display!: number;
|
|
||||||
display_width!: number;
|
|
||||||
display_height!: number;
|
|
||||||
top_led_strip!: LedStripConfig;
|
|
||||||
bottom_led_strip!: LedStripConfig;
|
|
||||||
left_led_strip!: LedStripConfig;
|
|
||||||
right_led_strip!: LedStripConfig;
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
export class LedStripConfig {
|
|
||||||
index!: number;
|
|
||||||
global_start_position!: number;
|
|
||||||
global_end_position!: number;
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
import { DisplayConfig } from './display-config';
|
|
||||||
|
|
||||||
export class PickerConfiguration {
|
|
||||||
config_version!: number;
|
|
||||||
display_configs!: DisplayConfig[];
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Global, css } from '@emotion/react';
|
|
||||||
import tw, { theme, GlobalStyles as BaseStyles } from 'twin.macro';
|
|
||||||
|
|
||||||
const customStyles = css({
|
|
||||||
body: {
|
|
||||||
WebkitTapHighlightColor: theme`colors.purple.500`,
|
|
||||||
...tw`antialiased dark:bg-dark-800 bg-dark-100`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const GlobalStyles = () => (
|
|
||||||
<>
|
|
||||||
<BaseStyles />
|
|
||||||
<Global styles={customStyles} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default GlobalStyles;
|
|
@ -14,12 +14,8 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx"
|
||||||
"jsxImportSource": "@emotion/react"
|
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src"],
|
||||||
"src",
|
|
||||||
"types"
|
|
||||||
],
|
|
||||||
"references": [{ "path": "./tsconfig.node.json" }]
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
}
|
}
|
||||||
|
18
types/twin.d.ts
vendored
18
types/twin.d.ts
vendored
@ -1,18 +0,0 @@
|
|||||||
import 'twin.macro';
|
|
||||||
import { css as cssImport } from '@emotion/react';
|
|
||||||
import styledImport from '@emotion/styled';
|
|
||||||
import { CSSInterpolation } from '@emotion/serialize';
|
|
||||||
|
|
||||||
declare module 'twin.macro' {
|
|
||||||
// The styled and css imports
|
|
||||||
const styled: typeof styledImport;
|
|
||||||
const css: typeof cssImport;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'react' {
|
|
||||||
// The tw and css prop
|
|
||||||
interface DOMAttributes<T> {
|
|
||||||
tw?: string;
|
|
||||||
css?: CSSInterpolation;
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,29 +3,7 @@ import react from "@vitejs/plugin-react";
|
|||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
optimizeDeps: {
|
plugins: [react()],
|
||||||
esbuildOptions: {
|
|
||||||
target: 'es2020',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
react({
|
|
||||||
babel: {
|
|
||||||
plugins: [
|
|
||||||
'babel-plugin-macros',
|
|
||||||
[
|
|
||||||
'@emotion/babel-plugin-jsx-pragmatic',
|
|
||||||
{
|
|
||||||
export: 'jsx',
|
|
||||||
import: '__cssprop',
|
|
||||||
module: '@emotion/react',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
['@babel/plugin-transform-react-jsx', { pragma: '__cssprop' }, 'twin.macro'],
|
|
||||||
],
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
|
|
||||||
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
|
||||||
// prevent vite from obscuring rust errors
|
// prevent vite from obscuring rust errors
|
||||||
@ -37,12 +15,12 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
// to make use of `TAURI_DEBUG` and other env variables
|
// to make use of `TAURI_DEBUG` and other env variables
|
||||||
// https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
|
// https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
|
||||||
envPrefix: ['VITE_', 'TAURI_'],
|
envPrefix: ["VITE_", "TAURI_"],
|
||||||
build: {
|
build: {
|
||||||
// Tauri supports es2021
|
// Tauri supports es2021
|
||||||
target: ['es2021', 'chrome100', 'safari13'],
|
target: ["es2021", "chrome100", "safari13"],
|
||||||
// don't minify for debug builds
|
// don't minify for debug builds
|
||||||
minify: !process.env.TAURI_DEBUG ? 'esbuild' : false,
|
minify: !process.env.TAURI_DEBUG ? "esbuild" : false,
|
||||||
// produce sourcemaps for debug builds
|
// produce sourcemaps for debug builds
|
||||||
sourcemap: !!process.env.TAURI_DEBUG,
|
sourcemap: !!process.env.TAURI_DEBUG,
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user