diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..f2999ed --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ + + +[workspace] +resolver = "3" +members = ["rusty_hub_egui", "unity_hub_lib"] + +[profile.release] +opt-level = 'z' +panic = 'abort' +lto = true + +[profile.dev.package."*"] +opt-level = 2 diff --git a/rusty_hub_egui/Cargo.toml b/rusty_hub_egui/Cargo.toml index 8892513..57ae21f 100644 --- a/rusty_hub_egui/Cargo.toml +++ b/rusty_hub_egui/Cargo.toml @@ -5,24 +5,24 @@ edition = "2021" homepage = "https://github.com/Leinnan/rusty_hub" build = "build.rs" -[profile.release] -opt-level = 'z' -panic = 'abort' -lto = true - -[profile.dev.package."*"] -opt-level = 2 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] confy = "0.6" -eframe = "0.29" -egui_extras = "0.29" +eframe = { version = "0.32", default-features = false, features = [ + #"accesskit", # Make egui comptaible with screen readers. NOTE: adds a lot of dependencies. + "default_fonts", # Embed the default egui fonts. + "glow", # Use the glow rendering backend. Alternative: "wgpu". + "persistence", # Enable restoring app state when restarting the app. + "wayland", # To support Linux (and CI) +] } +egui = "0.32" +egui_extras = "0.32" unity_hub_lib = { path="../unity_hub_lib" } rfd = "0.15" inline_tweak = "1" -poll-promise = "0.3" +anyhow = "1" [target.'cfg(windows)'.build-dependencies] winres = "0.1" diff --git a/rusty_hub_egui/src/hub_client.rs b/rusty_hub_egui/src/hub_client.rs index 0bf5390..72b05a2 100644 --- a/rusty_hub_egui/src/hub_client.rs +++ b/rusty_hub_egui/src/hub_client.rs @@ -22,39 +22,68 @@ pub struct HubClient { fn setup_custom_fonts(ctx: &egui::Context) { // Start with the default fonts (we will be adding to them rather than replacing them). let mut fonts = egui::FontDefinitions::default(); + if let Ok((regular, semibold)) = get_fonts() { + fonts.font_data.insert( + "regular".to_owned(), + egui::FontData::from_owned(regular).into(), + ); + fonts.font_data.insert( + "semibold".to_owned(), + egui::FontData::from_owned(semibold).into(), + ); - // Install my own font (maybe supporting non-latin characters). - // .ttf and .otf files supported. - fonts.font_data.insert( - "regular".to_owned(), - egui::FontData::from_static(include_bytes!("../static/Inter-Regular.ttf")), - ); - fonts.font_data.insert( - "semibold".to_owned(), - egui::FontData::from_static(include_bytes!("../static/Inter-SemiBold.ttf")), - ); + // Put my font first (highest priority) for proportional text: + fonts + .families + .entry(egui::FontFamily::Proportional) + .or_default() + .insert(0, "regular".to_owned()); + fonts + .families + .entry(egui::FontFamily::Name("semibold".into())) + .or_default() + .insert(0, "semibold".to_owned()); - // Put my font first (highest priority) for proportional text: - fonts - .families - .entry(egui::FontFamily::Proportional) - .or_default() - .insert(0, "regular".to_owned()); - fonts - .families - .entry(egui::FontFamily::Name("semibold".into())) - .or_default() - .insert(0, "semibold".to_owned()); + // Put my font as last fallback for monospace: + fonts + .families + .entry(egui::FontFamily::Monospace) + .or_default() + .push("regular".to_owned()); - // Put my font as last fallback for monospace: - fonts - .families - .entry(egui::FontFamily::Monospace) - .or_default() - .push("regular".to_owned()); + // Tell egui to use these fonts: + ctx.set_fonts(fonts); + } - // Tell egui to use these fonts: - ctx.set_fonts(fonts); + ctx.style_mut(|style| { + for font_id in style.text_styles.values_mut() { + font_id.size *= 1.4; + } + }); +} + +#[cfg(not(windows))] +fn get_fonts() -> anyhow::Result<(Vec, Vec)> { + use std::fs; + + let font_path = std::path::Path::new("/System/Library/Fonts"); + + let regular = fs::read(font_path.join("SFNSRounded.ttf"))?; + let semibold = fs::read(font_path.join("SFCompact.ttf"))?; + + Ok((regular, semibold)) +} + +#[cfg(windows)] +fn get_fonts() -> anyhow::Result<(Vec, Vec)> { + use std::fs; + let app_data = std::env::var("APPDATA")?; + let font_path = std::path::Path::new(&app_data); + + let regular = fs::read(font_path.join("../Local/Microsoft/Windows/Fonts/aptos.ttf"))?; + let semibold = fs::read(font_path.join("../Local/Microsoft/Windows/Fonts/aptos-semibold.ttf"))?; + + Ok((regular, semibold)) } impl HubClient { @@ -167,7 +196,7 @@ impl HubClient { .arg(&editor.base_path) .spawn() .unwrap(); - ui.close_menu(); + ui.close(); } }); }, @@ -189,7 +218,7 @@ impl HubClient { } else { egui::Color32::TRANSPARENT }; - egui::Frame::none().fill(color).show(ui, |ui| { + egui::Frame::NONE.fill(color).show(ui, |ui| { ui.add_sized( [text_height, text_height], egui::Button::new("⚙").frame(false), @@ -215,7 +244,7 @@ impl HubClient { } if ui.button(text).clicked() { Hub::run_project(editor, project); - ui.close_menu(); + ui.close(); } } }); @@ -226,7 +255,7 @@ impl HubClient { .arg(&project.path) .spawn() .unwrap(); - ui.close_menu(); + ui.close(); } }); ui.label(egui::RichText::new(project.title.to_string()).heading()) @@ -329,9 +358,7 @@ impl HubClient { .set_level(rfd::MessageLevel::Warning) } 1 => message = message.set_description("Project founded!"), - _ => { - message = message.set_description(format!("Founded {} projects.", amount)) - } + _ => message = message.set_description(format!("Founded {} projects.", amount)), } message.show(); self.save_config(true); @@ -354,7 +381,8 @@ impl HubClient { let response = ui.add_sized( button_size, - egui::Label::new(rich_text).selectable(false) + egui::Label::new(rich_text) + .selectable(false) .sense(egui::Sense::click()), ); if response.hovered() { @@ -409,7 +437,7 @@ impl eframe::App for HubClient { }); egui::TopBottomPanel::bottom("bottomPanel").show(ctx, |ui| { ui.with_layout(Layout::right_to_left(eframe::emath::Align::Center), |ui| { - egui::widgets::global_dark_light_mode_switch(ui); + egui::widgets::global_theme_preference_switch(ui); ui.hyperlink_to( format!("{} v {}", egui::special_emojis::GITHUB, VERSION), HOMEPAGE, diff --git a/rusty_hub_egui/src/main.rs b/rusty_hub_egui/src/main.rs index e1946c1..5f00ce8 100644 --- a/rusty_hub_egui/src/main.rs +++ b/rusty_hub_egui/src/main.rs @@ -17,19 +17,14 @@ fn main() -> eframe::Result<()> { eframe::icon_data::from_png_bytes(&include_bytes!("../static/hub.png")[..]) .expect("Failed to load icon"), ), - // always_on_top: false, - // maximized: false, - // decorated: true, - // fullscreen: false, - // drag_and_drop_support: false, - // initial_window_size: Some(egui::vec2(850.0, 400.0)), - // min_window_size: Some(egui::vec2(850.0, 400.0)), - // icon_data: Some(icon), ..Default::default() }; eframe::run_native( &format!("{} v {}", APP_NAME, VERSION), options, - Box::new(|cc| Ok(Box::new(crate::hub_client::HubClient::new(cc)))), + Box::new(|cc| { + egui_extras::install_image_loaders(&cc.egui_ctx); + Ok(Box::new(crate::hub_client::HubClient::new(cc))) + }), ) } diff --git a/unity_hub_lib/Cargo.toml b/unity_hub_lib/Cargo.toml index 98e2c2c..cad1dc4 100644 --- a/unity_hub_lib/Cargo.toml +++ b/unity_hub_lib/Cargo.toml @@ -3,20 +3,9 @@ name = "unity_hub_lib" version = "0.2.0" edition = "2021" -[profile.release] -opt-level = 'z' -panic = 'abort' -lto = true - -[profile.dev.package."*"] -opt-level = 2 - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] -serde = "1" -serde_derive = "1" +serde = { version = "1", features = ["derive"] } walkdir = "2" exe = "0.5" -registry = "1.2" +registry = "1.3" dpc-pariter = "0.5.1" diff --git a/unity_hub_lib/src/config.rs b/unity_hub_lib/src/config.rs index 7233b43..21fd612 100644 --- a/unity_hub_lib/src/config.rs +++ b/unity_hub_lib/src/config.rs @@ -1,5 +1,6 @@ use crate::{consts, unity_editor::UnityEditor}; use dpc_pariter::IteratorExt; +use serde::{Deserialize, Serialize}; use std::collections::HashSet; use walkdir::{DirEntry, WalkDir}; diff --git a/unity_hub_lib/src/hub.rs b/unity_hub_lib/src/hub.rs index 98b5e19..935432a 100644 --- a/unity_hub_lib/src/hub.rs +++ b/unity_hub_lib/src/hub.rs @@ -1,5 +1,6 @@ use crate::{config::Configuration, unity_editor::UnityEditor, unity_project::UnityProject}; use dpc_pariter::IteratorExt; +use serde::{Deserialize, Serialize}; use std::collections::HashSet; use std::{path::PathBuf, process::Command}; use walkdir::WalkDir; diff --git a/unity_hub_lib/src/lib.rs b/unity_hub_lib/src/lib.rs index fc59fb2..23e7009 100644 --- a/unity_hub_lib/src/lib.rs +++ b/unity_hub_lib/src/lib.rs @@ -1,6 +1,3 @@ -#[macro_use] -extern crate serde_derive; - pub mod config; pub mod consts; pub mod hub; diff --git a/unity_hub_lib/src/project_template.rs b/unity_hub_lib/src/project_template.rs index ab41928..60d2bae 100644 --- a/unity_hub_lib/src/project_template.rs +++ b/unity_hub_lib/src/project_template.rs @@ -1,4 +1,5 @@ use dpc_pariter::IteratorExt; +use serde::{Deserialize, Serialize}; use std::path::Path; #[derive(Debug, Serialize, Deserialize, Clone, Eq, Hash)] diff --git a/unity_hub_lib/src/unity_editor.rs b/unity_hub_lib/src/unity_editor.rs index 3ac8853..37980a8 100644 --- a/unity_hub_lib/src/unity_editor.rs +++ b/unity_hub_lib/src/unity_editor.rs @@ -1,5 +1,6 @@ use crate::consts; use crate::project_template::ProjectTemplate; +use serde::{Deserialize, Serialize}; use std::borrow::Borrow; use std::collections::HashMap; use std::hash::Hash; @@ -25,7 +26,7 @@ impl UnityEditor { let base_path = Path::new(path); let exe_path = base_path.join(consts::UNITY_EXE_NAME); let meta = std::fs::metadata(&exe_path); - if !meta.is_ok() || !meta.unwrap().is_file() { + if !meta.is_ok_and(|meta| meta.is_file()) { return None; } @@ -91,7 +92,7 @@ impl UnityEditor { let mut platforms = Vec::new(); let base_path = Path::new(unity_folder).join("Data").join("PlaybackEngines"); - if !std::fs::metadata(&base_path).is_ok() { + if std::fs::metadata(&base_path).is_err() { return platforms; } let dir = std::fs::read_dir(base_path); diff --git a/unity_hub_lib/src/unity_project.rs b/unity_hub_lib/src/unity_project.rs index bc469d0..bee767e 100644 --- a/unity_hub_lib/src/unity_project.rs +++ b/unity_hub_lib/src/unity_project.rs @@ -1,3 +1,4 @@ +use serde::{Deserialize, Serialize}; use std::{ops::Sub, path::Path, str}; use crate::consts; @@ -76,20 +77,20 @@ impl UnityProject { iter.next(); let project_version = iter.next().unwrap().to_string(); - return Some(project_version); + Some(project_version) } pub fn try_get_project_at_path(path: &str) -> Option { #[cfg(windows)] let path = path.trim_matches(char::from(0)).replace("/", "\\"); - #[cfg(unix)] - let path = path.trim_matches(char::from(0)); + #[cfg(not(windows))] + let path = path.trim_matches(char::from(0)).to_string(); if !UnityProject::is_project_at_path(&path) { return None; } let mut project = UnityProject { - path: path.to_string(), + path: path.clone(), title: path.split(consts::SLASH).last().unwrap().to_string(), branch: String::new(), version: String::new(),