diff --git a/.github/workflows/tauri-builds.yml b/.github/workflows/tauri-builds.yml index e4433eab..8fd731f2 100644 --- a/.github/workflows/tauri-builds.yml +++ b/.github/workflows/tauri-builds.yml @@ -7,7 +7,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [windows-latest, macos-latest] + platform: [windows-latest, macos-13, macos-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/README.md b/README.md index f09e0295..d3e80a9d 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,11 @@ winget install LazapDevelopment.Lazap - Arch Linux users can directly install from the maintained `lazap-bin` [AUR](https://aur.archlinux.org/packages/lazap-bin). ▸ **MacOS**: -- Download and install the latest `.dmg` file in the [releases](https://github.com/Lazap-Development/lazap/releases) section. +> [!NOTE] +> Most modern MacOS systems are of `aarch64` (also known as ARM) instead of `x64` architecture.
+> Execute the `arch` command in a new terminal to confirm your MacOS architecture. +- Download and install the latest `[x64/aarch64].dmg` file in the [releases](https://github.com/Lazap-Development/lazap/releases) section. + ## 👾 Development diff --git a/src-tauri/build.rs b/src-tauri/build.rs index 795b9b7c..d860e1e6 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -1,3 +1,3 @@ fn main() { - tauri_build::build() + tauri_build::build() } diff --git a/src-tauri/src/addons/ytm.rs b/src-tauri/src/addons/ytm.rs index e69de29b..8b137891 100644 --- a/src-tauri/src/addons/ytm.rs +++ b/src-tauri/src/addons/ytm.rs @@ -0,0 +1 @@ + diff --git a/src-tauri/src/launchers/custom_games.rs b/src-tauri/src/launchers/custom_games.rs index 2a3bf5dd..eb6603e4 100644 --- a/src-tauri/src/launchers/custom_games.rs +++ b/src-tauri/src/launchers/custom_games.rs @@ -6,7 +6,7 @@ use crate::{ }, CONFIG_DIR, }; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] struct GameData { diff --git a/src-tauri/src/launchers/gog.rs b/src-tauri/src/launchers/gog.rs index a7aa6219..ec67de51 100644 --- a/src-tauri/src/launchers/gog.rs +++ b/src-tauri/src/launchers/gog.rs @@ -1,10 +1,7 @@ use crate::{ - launchers::{ - GameObject, - LINE_ENDING, - }, - operations::custom_fs::d_f_exists, + launchers::{GameObject, LINE_ENDING}, modules::banners, + operations::custom_fs::d_f_exists, }; use serde::{Deserialize, Serialize}; use std::{os::windows::process::CommandExt, process::Command, str}; @@ -21,11 +18,13 @@ struct ImageData { pub async fn get_installed_games() -> Vec { let mut gameobjects = vec![]; - if !d_f_exists("C:\\ProgramData\\GOG.com\\Galaxy\\storage").await.expect("Something went wrong") + if !d_f_exists("C:\\ProgramData\\GOG.com\\Galaxy\\storage") + .await + .expect("Something went wrong") { return vec![]; } - + struct InstalledGame { product_id: i32, installation_path: String, @@ -55,15 +54,15 @@ pub async fn get_installed_games() -> Vec { }) .await .unwrap(); - + let games_data = conn - .call(|conn| { - let mut stmt = conn.prepare("SELECT * FROM LimitedDetails")?; - let data = stmt - .query_map([], |row| { - Ok(GameData { - product_id: row.get(1).unwrap_or_default(), - title: row.get(5).unwrap_or_default(), + .call(|conn| { + let mut stmt = conn.prepare("SELECT * FROM LimitedDetails")?; + let data = stmt + .query_map([], |row| { + Ok(GameData { + product_id: row.get(1).unwrap_or_default(), + title: row.get(5).unwrap_or_default(), banner: row.get(7).unwrap_or_default(), }) }) @@ -94,14 +93,13 @@ pub async fn get_installed_games() -> Vec { .to_string() .split(LINE_ENDING) .filter(|x| x.contains("REG_SZ") && x.contains("client")) - .map( - |x| x.split("REG_SZ").collect::>()[1].trim() - ) + .map(|x| x.split("REG_SZ").collect::>()[1].trim()) .collect::>() .into_iter() .rev() - .collect::>().join("\\"); - + .collect::>() + .join("\\"); + for game in games.unwrap() { let product_id = game.product_id; let game_data = games_data @@ -110,12 +108,21 @@ pub async fn get_installed_games() -> Vec { .unwrap(); let img_data: ImageData = serde_json::from_str(&game_data.banner).unwrap(); gameobjects.push(GameObject::new( - banners::get_banner(&game_data.title, &(product_id.to_string()), "GOG", &img_data.icon).await, + banners::get_banner( + &game_data.title, + &(product_id.to_string()), + "GOG", + &img_data.icon, + ) + .await, String::new(), game.installation_path.to_string(), game_data.title.to_string(), product_id.to_string(), - format!("\"{}\"", launcher_location) + " /command=runGame" + &format!(" /gameId={}", game.product_id) + &format!(" /path=\"{}\"", game.installation_path), + format!("\"{}\"", launcher_location) + + " /command=runGame" + + &format!(" /gameId={}", game.product_id) + + &format!(" /path=\"{}\"", game.installation_path), 0, String::new(), "GOG".to_string(), @@ -126,4 +133,4 @@ pub async fn get_installed_games() -> Vec { return gameobjects; } -// "C:\Program Files (x86)\GOG Galaxy\GalaxyClient.exe" /command=runGame /gameId=1810005965 /path="C:\Program Files (x86)\GOG Galaxy\Games\Roboplant Demo" \ No newline at end of file +// "C:\Program Files (x86)\GOG Galaxy\GalaxyClient.exe" /command=runGame /gameId=1810005965 /path="C:\Program Files (x86)\GOG Galaxy\Games\Roboplant Demo" diff --git a/src-tauri/src/launchers/minecraft.rs b/src-tauri/src/launchers/minecraft.rs index 54e2a235..b616dbe5 100644 --- a/src-tauri/src/launchers/minecraft.rs +++ b/src-tauri/src/launchers/minecraft.rs @@ -28,7 +28,7 @@ async fn get_minecraft_launcher() -> Option { // TO-DO: FINISH MACOS #[cfg(target_os = "macos")] { - return None + return None; } #[cfg(target_os = "windows")] diff --git a/src-tauri/src/launchers/mod.rs b/src-tauri/src/launchers/mod.rs index 5ef036fc..dfe34f55 100644 --- a/src-tauri/src/launchers/mod.rs +++ b/src-tauri/src/launchers/mod.rs @@ -1,3 +1,4 @@ +pub mod custom_games; #[cfg(target_os = "windows")] mod epic_games; #[cfg(target_os = "windows")] @@ -12,7 +13,6 @@ mod steam; mod uplay; #[cfg(target_os = "linux")] mod wine_managers; -pub mod custom_games; use serde::{Deserialize, Serialize}; @@ -71,9 +71,7 @@ fn is_installed(native_name: &str, flatpak_name: &str) -> bool { String::default() } } - Err(_e) => { - String::default() - } + Err(_e) => String::default(), }; let native = match std::process::Command::new("which") @@ -87,9 +85,7 @@ fn is_installed(native_name: &str, flatpak_name: &str) -> bool { String::default() } } - Err(_e) => { - String::default() - } + Err(_e) => String::default(), }; if native.starts_with("/") { diff --git a/src-tauri/src/launchers/rockstar_games.rs b/src-tauri/src/launchers/rockstar_games.rs index 865af1d3..2799f8dd 100644 --- a/src-tauri/src/launchers/rockstar_games.rs +++ b/src-tauri/src/launchers/rockstar_games.rs @@ -281,7 +281,8 @@ async fn parse_game_object(path: &str, name: &str) -> Option { } return Some(GameObject::new( - banners::get_banner(&game.friendly_name, &game.banner_id, "RockstarGames", "").await, + banners::get_banner(&game.friendly_name, &game.banner_id, "RockstarGames", "") + .await, executable.to_string(), path.to_string(), game.friendly_name.clone(), diff --git a/src-tauri/src/launchers/steam.rs b/src-tauri/src/launchers/steam.rs index 12653843..cfc9c343 100644 --- a/src-tauri/src/launchers/steam.rs +++ b/src-tauri/src/launchers/steam.rs @@ -130,7 +130,8 @@ pub async fn get_installed_games() -> Vec { #[cfg(target_os = "macos")] temp_all_games.push(GameObject::new( - banners::get_banner(&game_file_parsed.name, &game_file_parsed.appid, "Steam", "").await, + banners::get_banner(&game_file_parsed.name, &game_file_parsed.appid, "Steam", "") + .await, String::new(), game_file_parsed.installdir.to_string(), game_file_parsed.name, @@ -144,7 +145,8 @@ pub async fn get_installed_games() -> Vec { #[cfg(target_os = "windows")] temp_all_games.push(GameObject::new( - banners::get_banner(&game_file_parsed.name, &game_file_parsed.appid, "Steam", "").await, + banners::get_banner(&game_file_parsed.name, &game_file_parsed.appid, "Steam", "") + .await, String::new(), game_file_parsed.launcherpath.to_string(), game_file_parsed.name, @@ -158,7 +160,8 @@ pub async fn get_installed_games() -> Vec { #[cfg(target_os = "linux")] temp_all_games.push(GameObject::new( - banners::get_banner(&game_file_parsed.name, &game_file_parsed.appid, "Steam", "").await, + banners::get_banner(&game_file_parsed.name, &game_file_parsed.appid, "Steam", "") + .await, String::new(), String::new(), game_file_parsed.name, diff --git a/src-tauri/src/launchers/wine_managers.rs b/src-tauri/src/launchers/wine_managers.rs index af7b0c6f..5abc375c 100644 --- a/src-tauri/src/launchers/wine_managers.rs +++ b/src-tauri/src/launchers/wine_managers.rs @@ -1,7 +1,11 @@ use tauri::api::path; use tokio_rusqlite::Connection; -use crate::{launchers::{is_installed, GameObject}, modules::banners, operations::custom_fs::d_f_exists}; +use crate::{ + launchers::{is_installed, GameObject}, + modules::banners, + operations::custom_fs::d_f_exists, +}; pub async fn get_installed_games() -> Vec { let mut all_games: Vec = Vec::new(); diff --git a/src-tauri/src/launchers/xbox_games.rs b/src-tauri/src/launchers/xbox_games.rs index 5314f88e..fa1bb2a8 100644 --- a/src-tauri/src/launchers/xbox_games.rs +++ b/src-tauri/src/launchers/xbox_games.rs @@ -1,8 +1,8 @@ -use std::process::Command; -use serde::{Deserialize, Serialize}; -use crate::{launchers::GameObject, operations::custom_fs::read_file, modules::banners}; +use crate::{launchers::GameObject, modules::banners, operations::custom_fs::read_file}; use reqwest::{Client, Url}; use scraper::{Html, Selector}; +use serde::{Deserialize, Serialize}; +use std::process::Command; #[derive(Serialize, Deserialize)] pub struct XboxGame { @@ -33,66 +33,80 @@ pub async fn get_installed_games() -> Vec { .output() .expect("failed to execute process."); - let games: Vec = parse_raw_to_json( - String::from_utf8_lossy(&output.stdout).to_string() - ) - .await - .into_iter() - .filter( - |x| - x.is_framework != "True" && - x.signature_kind == "Store" && - x.publisher_id != "8wekyb3d8bbwe" && - !x.package_full_name.starts_with("MicrosoftWindows") - ) - .collect::>(); + let games: Vec = + parse_raw_to_json(String::from_utf8_lossy(&output.stdout).to_string()) + .await + .into_iter() + .filter(|x| { + x.is_framework != "True" + && x.signature_kind == "Store" + && x.publisher_id != "8wekyb3d8bbwe" + && !x.package_full_name.starts_with("MicrosoftWindows") + }) + .collect::>(); let verified = verify_games(games).await; - let objs = verified.into_iter().map(|x| parse_game_object(x)).collect::>(); + let objs = verified + .into_iter() + .map(|x| parse_game_object(x)) + .collect::>(); return vec![]; } pub async fn parse_raw_to_json(stdout: String) -> Vec { let mut arr: Vec = vec![]; - const VALUES: [&str;7] = ["Name", "PackageFullName", "InstallLocation", "IsFramework", "PackageFamilyName", "PublisherId", "SignatureKind"]; - - stdout - .split("\r\n\r\n") - .collect::>()[1..] - .iter() - .map( - |x| x - .split("\r\n") - .filter(|y| !y.to_string().ends_with(" ") && VALUES.contains(&y.split(":").collect::>()[0].trim())) - .map( - |y| { - let splited = y.splitn(3, ":").collect::>(); - return splited.iter().enumerate().map( - |(i, z)| { + const VALUES: [&str; 7] = [ + "Name", + "PackageFullName", + "InstallLocation", + "IsFramework", + "PackageFamilyName", + "PublisherId", + "SignatureKind", + ]; + + stdout.split("\r\n\r\n").collect::>()[1..] + .iter() + .map(|x| { + x.split("\r\n") + .filter(|y| { + !y.to_string().ends_with(" ") + && VALUES.contains(&y.split(":").collect::>()[0].trim()) + }) + .map(|y| { + let split = y.splitn(3, ":").collect::>(); + return split + .iter() + .enumerate() + .map(|(i, z)| { let mut val = z.trim().to_owned(); - if splited.len() == 3 && i != 0 { + if split.len() == 3 && i != 0 { if i == 2 { val = format!("{}\"", val); - } - else if i != 2 { + } else if i != 2 { val = format!("\"{}", val); } - } - else { + } else { val = format!("\"{}\"", val); } val - } - ).collect::>().join(":"); - } - ).collect::>().join(",\n").replace("\\", "/") - ) - .filter(|x| x.len() > 20) - .for_each(|x| { - arr.push(serde_json::from_str(&("{".to_string() + &x + &",\n\"banner\":\"\"}".to_string())).unwrap()); - }); + }) + .collect::>() + .join(":"); + }) + .collect::>() + .join(",\n") + .replace("\\", "/") + }) + .filter(|x| x.len() > 20) + .for_each(|x| { + arr.push( + serde_json::from_str(&("{".to_string() + &x + &",\n\"banner\":\"\"}".to_string())) + .unwrap(), + ); + }); return arr; } @@ -104,22 +118,27 @@ pub async fn verify_games(games: Vec) -> Vec { game.name = game.name.split(".").collect::>()[1].to_string(); let client = Client::new(); let response = client - .get( - Url::parse(&format!("https://www.microsoft.com/en-in/search/shop/games?q={}&devicetype=pc", game.name)).unwrap() - ) - .send() - .await - .expect(""); + .get( + Url::parse(&format!( + "https://www.microsoft.com/en-in/search/shop/games?q={}&devicetype=pc", + game.name + )) + .unwrap(), + ) + .send() + .await + .expect(""); let text = &response.text().await.unwrap(); let document = Html::parse_document(text); let selector = Selector::parse(&"div[id=\"shopDetailsWrapper\"]").unwrap(); let selected = document.select(&selector).collect::>()[0]; - let ul_element = selected - .child_elements().collect::>()[0] - .child_elements().collect::>()[2] - .child_elements().collect::>(); + let ul_element = selected.child_elements().collect::>()[0] + .child_elements() + .collect::>()[2] + .child_elements() + .collect::>(); // .child_elements().collect::>(); if ul_element.len() == 0 { @@ -128,29 +147,35 @@ pub async fn verify_games(games: Vec) -> Vec { let li_element; if ul_element[0].first_child().is_some() { - li_element = ul_element[0] - .child_elements().collect::>()[0]; - } - else { + li_element = ul_element[0].child_elements().collect::>()[0]; + } else { continue; } - let title = li_element - .child_elements().collect::>()[0] - .child_elements().collect::>()[0] - .child_elements().collect::>()[1] - .child_elements().collect::>()[0] - .child_elements().collect::>()[0].inner_html(); - - let banner = li_element - .child_elements().collect::>()[0] - .child_elements().collect::>()[0] - .child_elements().collect::>()[0] - .child_elements().collect::>()[0] - .child_elements().collect::>().last() - .unwrap() - .attr("src") - .unwrap(); + let title = li_element.child_elements().collect::>()[0] + .child_elements() + .collect::>()[0] + .child_elements() + .collect::>()[1] + .child_elements() + .collect::>()[0] + .child_elements() + .collect::>()[0] + .inner_html(); + + let banner = li_element.child_elements().collect::>()[0] + .child_elements() + .collect::>()[0] + .child_elements() + .collect::>()[0] + .child_elements() + .collect::>()[0] + .child_elements() + .collect::>() + .last() + .unwrap() + .attr("src") + .unwrap(); game.name = title; game.banner = banner.to_string(); @@ -170,9 +195,9 @@ pub fn parse_game_object(game: XboxGame) -> Option { let location = &game.install_location; let manifeststr = read_file(location.to_string() + "/AppxManifest.xml").unwrap(); let manifest = manifeststr - .split("\r\n") - .find(|x| x.trim().starts_with("]{0,1}/); let executable = manifest.split("\"")[1].to_string(); gameobject = GameObject::new( @@ -188,4 +213,4 @@ pub fn parse_game_object(game: XboxGame) -> Option { vec![], ); return Some(gameobject); -} \ No newline at end of file +} diff --git a/src-tauri/src/modules/gamepad.rs b/src-tauri/src/modules/gamepad.rs index fa9a4a22..83002be3 100644 --- a/src-tauri/src/modules/gamepad.rs +++ b/src-tauri/src/modules/gamepad.rs @@ -13,9 +13,13 @@ pub fn init_gamepad() { println!("{} is {:?}", gamepad.name(), gamepad.power_info()); } - loop { - while let Some(Event { id, event: _, time: _ }) = gilrs.next_event() { + while let Some(Event { + id, + event: _, + time: _, + }) = gilrs.next_event() + { unsafe { ACTIVE_GAMEPAD = Some(id); } @@ -46,4 +50,4 @@ pub async fn catch_gamepad_keys() -> Result<(), Error> { } } } -} \ No newline at end of file +} diff --git a/src-tauri/src/modules/mod.rs b/src-tauri/src/modules/mod.rs index db01d6ae..0ea096c7 100644 --- a/src-tauri/src/modules/mod.rs +++ b/src-tauri/src/modules/mod.rs @@ -1,2 +1,2 @@ +pub mod banners; pub mod storage; -pub mod banners; \ No newline at end of file diff --git a/src-tauri/src/operations/mod.rs b/src-tauri/src/operations/mod.rs index a0e5b9da..787a678a 100644 --- a/src-tauri/src/operations/mod.rs +++ b/src-tauri/src/operations/mod.rs @@ -1,3 +1,3 @@ pub mod custom_fs; pub mod discord_rpc; -pub mod misc; \ No newline at end of file +pub mod misc; diff --git a/src/components/Settings.vue b/src/components/Settings.vue index e8d634b6..77d66f62 100644 --- a/src/components/Settings.vue +++ b/src/components/Settings.vue @@ -4,7 +4,7 @@

Settings

-
+
@@ -684,13 +684,13 @@ export default { margin-left: 20px; } -.choser { +.chooser { display: flex; align-items: center; flex-direction: column; } -.choser button { +.chooser button { font-family: Nunito-Bold !important; color: rgb(201, 201, 201); text-decoration: none; @@ -706,23 +706,23 @@ export default { transition: all 0.15s cubic-bezier(0.165, 0.74, 0.44, 1); } -.choser .active { +.chooser .active { background-color: rgba(var(--accent-color), 0.4); } -.choser button:first-child { +.chooser button:first-child { border-radius: 10px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; } -.choser button:last-child { +.chooser button:last-child { border-radius: 10px; border-top-right-radius: 0px; border-top-left-radius: 0px; } -.choser button:hover { +.chooser button:hover { background-color: rgba(var(--accent-color), 0.4); transition: all 0.15s cubic-bezier(0.165, 0.74, 0.44, 1); } diff --git a/src/js/main.js b/src/js/main.js index b9b6ce94..3128ea2f 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -1,4 +1,4 @@ -import { createApp } from 'vue' -import App from '../App.vue' +import { createApp } from "vue"; +import App from "../App.vue"; -createApp(App).mount('#app') +createApp(App).mount("#app"); diff --git a/src/js/overlay.js b/src/js/overlay.js index 384a098c..f3898560 100644 --- a/src/js/overlay.js +++ b/src/js/overlay.js @@ -1,4 +1,4 @@ -import { createApp } from 'vue' -import AppOverlay from '../AppOverlay.vue' +import { createApp } from "vue"; +import AppOverlay from "../AppOverlay.vue"; -createApp(App).mount('#overlay') +createApp(App).mount("#overlay");