mirror of
https://github.com/an-anime-team/sleepy-launcher.git
synced 2025-03-15 14:38:29 +03:00
Not sure what I wanted to fix initially
but in the end I rewrote tons of code, including total change of strings to PathBuf also I fixed all the warnings generated by clippy
This commit is contained in:
parent
aa6f08f0fd
commit
eaa8379976
35 changed files with 286 additions and 283 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -31,7 +31,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anime-game-core"
|
||||
version = "1.1.8"
|
||||
version = "1.1.9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bzip2",
|
||||
|
@ -56,6 +56,7 @@ version = "1.1.3"
|
|||
dependencies = [
|
||||
"anime-game-core",
|
||||
"anyhow",
|
||||
"cached",
|
||||
"dirs",
|
||||
"gtk4",
|
||||
"lazy_static",
|
||||
|
@ -2303,9 +2304,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|||
|
||||
[[package]]
|
||||
name = "wincompatlib"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fb138cb8c6312731e7385e4500a2491be768ff4c8cfc04544dcc9227533f250"
|
||||
checksum = "34cd4c8511402616780eeb46726ca69ad958c4ba123398389ce306552428b715"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
|
|
@ -21,7 +21,7 @@ adw = { package = "libadwaita", version = "0.2.0-alpha.3", features = ["v1_2"] }
|
|||
rfd = { version = "0.10", features = ["xdg-portal"], default-features = false }
|
||||
|
||||
anime-game-core = { path = "anime-game-core", features = ["all", "static", "genshin"] }
|
||||
wincompatlib = { version = "0.1.0", features = ["dxvk"] }
|
||||
wincompatlib = { version = "0.1.2", features = ["dxvk"] }
|
||||
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
@ -32,3 +32,4 @@ regex = "1.6.0"
|
|||
lazy_static = "1.4.0"
|
||||
anyhow = "1.0"
|
||||
md5 = "0.7"
|
||||
cached = { version = "0.39", features = ["proc_macro"]}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 6230dbf8ca26e3cd34cbe32468df18c823e89158
|
||||
Subproject commit 66b0e5f9c44a7d3247010b9a830f386f715b5ac5
|
48
build.rs
48
build.rs
|
@ -31,42 +31,40 @@ fn blp_process_dir(dir: String) {
|
|||
let dist_dir = format!("assets/ui/.dist/{}", &dir).replace("//", "/");
|
||||
|
||||
if let Ok(entries) = read_dir(&source_dir) {
|
||||
if let Err(_) = read_dir(&dist_dir) {
|
||||
if read_dir(&dist_dir).is_err() {
|
||||
create_dir_all(&dist_dir).expect("UI dist dir couldn't be created");
|
||||
}
|
||||
|
||||
// println!("cargo:rerun-if-changed={}/*.blp", &source_dir);
|
||||
|
||||
for entry in entries {
|
||||
if let Ok(entry) = entry {
|
||||
if let Ok(metadata) = entry.metadata() {
|
||||
let entry_path = entry.path().to_str().unwrap().to_string();
|
||||
let entry_filename = entry.file_name().to_str().unwrap().to_string();
|
||||
for entry in entries.flatten() {
|
||||
if let Ok(metadata) = entry.metadata() {
|
||||
let entry_path = entry.path().to_str().unwrap().to_string();
|
||||
let entry_filename = entry.file_name().to_str().unwrap().to_string();
|
||||
|
||||
if metadata.is_file() {
|
||||
let entry_dist_path = format!("{}/{}.ui", &dist_dir, &entry_filename[..entry_filename.len() - 4]);
|
||||
if metadata.is_file() {
|
||||
let entry_dist_path = format!("{}/{}.ui", &dist_dir, &entry_filename[..entry_filename.len() - 4]);
|
||||
|
||||
match compile_blueprint(&entry_path) {
|
||||
Ok(xml) => {
|
||||
let result = fs::write(entry_dist_path, xml);
|
||||
match compile_blueprint(&entry_path) {
|
||||
Ok(xml) => {
|
||||
let result = fs::write(entry_dist_path, xml);
|
||||
|
||||
if let Err(err) = result {
|
||||
println!("cargo:warning=Couldn't write compiled XML UI: {}", err);
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
if Path::new(&entry_dist_path).exists() {
|
||||
fs::remove_file(entry_dist_path).expect("Couldn't remove broken file");
|
||||
}
|
||||
|
||||
println!("cargo:warning=Couldn't compile {}: {}", entry_path, err);
|
||||
if let Err(err) = result {
|
||||
println!("cargo:warning=Couldn't write compiled XML UI: {}", err);
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
if Path::new(&entry_dist_path).exists() {
|
||||
fs::remove_file(entry_dist_path).expect("Couldn't remove broken file");
|
||||
}
|
||||
|
||||
println!("cargo:warning=Couldn't compile {}: {}", entry_path, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if metadata.is_dir() && &entry_filename[0..1] != "." {
|
||||
blp_process_dir(format!("{}/{}", &dir, &entry_filename));
|
||||
}
|
||||
else if metadata.is_dir() && &entry_filename[0..1] != "." {
|
||||
blp_process_dir(format!("{}/{}", &dir, &entry_filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +74,7 @@ fn blp_process_dir(dir: String) {
|
|||
fn main() {
|
||||
blp_process_dir(String::new());
|
||||
|
||||
if let Ok(_) = read_to_string("assets/resources.xml") {
|
||||
if read_to_string("assets/resources.xml").is_ok() {
|
||||
gtk::gio::compile_resources(
|
||||
"assets",
|
||||
"assets/resources.xml",
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
|
@ -5,7 +7,7 @@ use crate::lib::consts::launcher_dir;
|
|||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Dxvk {
|
||||
pub builds: String
|
||||
pub builds: PathBuf
|
||||
}
|
||||
|
||||
impl Default for Dxvk {
|
||||
|
@ -13,7 +15,7 @@ impl Default for Dxvk {
|
|||
let launcher_dir = launcher_dir().expect("Failed to get launcher dir");
|
||||
|
||||
Self {
|
||||
builds: format!("{launcher_dir}/dxvks")
|
||||
builds: launcher_dir.join("dxvks")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +26,10 @@ impl From<&JsonValue> for Dxvk {
|
|||
|
||||
Self {
|
||||
builds: match value.get("builds") {
|
||||
Some(value) => value.as_str().unwrap_or(&default.builds).to_string(),
|
||||
Some(value) => match value.as_str() {
|
||||
Some(value) => PathBuf::from(value),
|
||||
None => default.builds
|
||||
},
|
||||
None => default.builds
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
|
@ -15,7 +17,7 @@ use prelude::*;
|
|||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct FpsUnlocker {
|
||||
pub path: String,
|
||||
pub path: PathBuf,
|
||||
pub enabled: bool,
|
||||
pub config: Config
|
||||
}
|
||||
|
@ -25,7 +27,7 @@ impl Default for FpsUnlocker {
|
|||
let launcher_dir = launcher_dir().expect("Failed to get launcher dir");
|
||||
|
||||
Self {
|
||||
path: format!("{launcher_dir}/fps-unlocker"),
|
||||
path: launcher_dir.join("fps-unlocker"),
|
||||
enabled: false,
|
||||
config: Config::default()
|
||||
}
|
||||
|
@ -38,7 +40,10 @@ impl From<&JsonValue> for FpsUnlocker {
|
|||
|
||||
Self {
|
||||
path: match value.get("path") {
|
||||
Some(value) => value.as_str().unwrap_or(&default.path).to_string(),
|
||||
Some(value) => match value.as_str() {
|
||||
Some(value) => PathBuf::from(value),
|
||||
None => default.path
|
||||
},
|
||||
None => default.path
|
||||
},
|
||||
|
||||
|
|
|
@ -15,6 +15,6 @@ impl Default for WindowType {
|
|||
|
||||
impl From<&JsonValue> for WindowType {
|
||||
fn from(value: &JsonValue) -> Self {
|
||||
serde_json::from_value(value.clone()).unwrap_or(Self::default())
|
||||
serde_json::from_value(value.clone()).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ impl Default for HUD {
|
|||
|
||||
impl From<&JsonValue> for HUD {
|
||||
fn from(value: &JsonValue) -> Self {
|
||||
serde_json::from_value(value.clone()).unwrap_or(Self::default())
|
||||
serde_json::from_value(value.clone()).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@ impl TryFrom<u32> for HUD {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::from_over_into)]
|
||||
impl Into<u32> for HUD {
|
||||
fn into(self) -> u32 {
|
||||
match self {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
@ -21,7 +22,7 @@ use prelude::*;
|
|||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Game {
|
||||
pub path: String,
|
||||
pub path: PathBuf,
|
||||
pub voices: Vec<String>,
|
||||
pub wine: prelude::Wine,
|
||||
pub dxvk: prelude::Dxvk,
|
||||
|
@ -35,7 +36,7 @@ impl Default for Game {
|
|||
let launcher_dir = launcher_dir().expect("Failed to get launcher dir");
|
||||
|
||||
Self {
|
||||
path: format!("{launcher_dir}/game/drive_c/Program Files/Genshin Impact"),
|
||||
path: launcher_dir.join("game/drive_c/Program Files/Genshin Impact"),
|
||||
voices: vec![
|
||||
String::from("en-us")
|
||||
],
|
||||
|
@ -54,7 +55,10 @@ impl From<&JsonValue> for Game {
|
|||
|
||||
Self {
|
||||
path: match value.get("path") {
|
||||
Some(value) => value.as_str().unwrap_or(&default.path).to_string(),
|
||||
Some(value) => match value.as_str() {
|
||||
Some(value) => PathBuf::from(value),
|
||||
None => default.path
|
||||
},
|
||||
None => default.path
|
||||
},
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
|
@ -18,8 +20,8 @@ use prelude::*;
|
|||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Wine {
|
||||
pub prefix: String,
|
||||
pub builds: String,
|
||||
pub prefix: PathBuf,
|
||||
pub builds: PathBuf,
|
||||
pub selected: Option<String>,
|
||||
pub sync: WineSync,
|
||||
pub language: WineLang,
|
||||
|
@ -32,8 +34,8 @@ impl Default for Wine {
|
|||
let launcher_dir = launcher_dir().expect("Failed to get launcher dir");
|
||||
|
||||
Self {
|
||||
prefix: format!("{launcher_dir}/game"),
|
||||
builds: format!("{launcher_dir}/runners"),
|
||||
prefix: launcher_dir.join("game"),
|
||||
builds: launcher_dir.join("runners"),
|
||||
selected: None,
|
||||
sync: WineSync::default(),
|
||||
language: WineLang::default(),
|
||||
|
@ -49,12 +51,18 @@ impl From<&JsonValue> for Wine {
|
|||
|
||||
Self {
|
||||
prefix: match value.get("prefix") {
|
||||
Some(value) => value.as_str().unwrap_or(&default.prefix).to_string(),
|
||||
Some(value) => match value.as_str() {
|
||||
Some(value) => PathBuf::from(value),
|
||||
None => default.prefix
|
||||
},
|
||||
None => default.prefix
|
||||
},
|
||||
|
||||
builds: match value.get("builds") {
|
||||
Some(value) => value.as_str().unwrap_or(&default.builds).to_string(),
|
||||
Some(value) => match value.as_str() {
|
||||
Some(value) => PathBuf::from(value),
|
||||
None => default.builds
|
||||
},
|
||||
None => default.builds
|
||||
},
|
||||
|
||||
|
|
|
@ -26,10 +26,11 @@ impl Default for WineLang {
|
|||
|
||||
impl From<&JsonValue> for WineLang {
|
||||
fn from(value: &JsonValue) -> Self {
|
||||
serde_json::from_value(value.clone()).unwrap_or(Self::default())
|
||||
serde_json::from_value(value.clone()).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::from_over_into)]
|
||||
impl Into<u32> for WineLang {
|
||||
fn into(self) -> u32 {
|
||||
for (i, lang) in Self::list().into_iter().enumerate() {
|
||||
|
@ -69,10 +70,6 @@ impl WineLang {
|
|||
model
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
|
||||
/// Get environment variables corresponding to used wine language
|
||||
pub fn get_env_vars(&self) -> HashMap<&str, &str> {
|
||||
HashMap::from([("LANG", match self {
|
||||
|
@ -91,3 +88,9 @@ impl WineLang {
|
|||
})])
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for WineLang {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(&format!("{:?}", self))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ impl Default for WineSync {
|
|||
|
||||
impl From<&JsonValue> for WineSync {
|
||||
fn from(value: &JsonValue) -> Self {
|
||||
serde_json::from_value(value.clone()).unwrap_or(Self::default())
|
||||
serde_json::from_value(value.clone()).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@ impl TryFrom<u32> for WineSync {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::from_over_into)]
|
||||
impl Into<u32> for WineSync {
|
||||
fn into(self) -> u32 {
|
||||
match self {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
|
@ -41,11 +43,11 @@ impl Default for GameEdition {
|
|||
}
|
||||
}
|
||||
|
||||
impl Into<CoreGameEdition> for GameEdition {
|
||||
fn into(self) -> CoreGameEdition {
|
||||
match self {
|
||||
Self::Global => CoreGameEdition::Global,
|
||||
Self::China => CoreGameEdition::China
|
||||
impl From<GameEdition> for CoreGameEdition {
|
||||
fn from(edition: GameEdition) -> Self {
|
||||
match edition {
|
||||
GameEdition::Global => CoreGameEdition::Global,
|
||||
GameEdition::China => CoreGameEdition::China
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +64,7 @@ impl From<CoreGameEdition> for GameEdition {
|
|||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Launcher {
|
||||
pub language: String,
|
||||
pub temp: Option<String>,
|
||||
pub temp: Option<PathBuf>,
|
||||
pub speed_limit: u64,
|
||||
pub repairer: Repairer,
|
||||
pub edition: GameEdition
|
||||
|
@ -96,7 +98,7 @@ impl From<&JsonValue> for Launcher {
|
|||
None
|
||||
} else {
|
||||
match value.as_str() {
|
||||
Some(value) => Some(value.to_string()),
|
||||
Some(value) => Some(PathBuf::from(value)),
|
||||
None => default.temp
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::io::Write;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
use wincompatlib::dxvk::Dxvk;
|
||||
|
||||
use crate::lib;
|
||||
use super::consts::*;
|
||||
use super::wine::{
|
||||
|
@ -107,7 +109,7 @@ pub fn update_raw(config: Config) -> anyhow::Result<()> {
|
|||
|
||||
match serde_json::to_string_pretty(&config) {
|
||||
Ok(json) => {
|
||||
file.write_all(&mut json.as_bytes())?;
|
||||
file.write_all(json.as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
},
|
||||
|
@ -141,8 +143,7 @@ impl Config {
|
|||
Some(selected) => {
|
||||
WineList::get().iter()
|
||||
.flat_map(|group| group.versions.clone())
|
||||
.filter(|version| version.name.eq(selected))
|
||||
.next()
|
||||
.find(|version| version.name.eq(selected))
|
||||
},
|
||||
None => None
|
||||
}
|
||||
|
@ -153,12 +154,12 @@ impl Config {
|
|||
/// Returns `Some("wine64")` if:
|
||||
/// 1) `game.wine.selected = None`
|
||||
/// 2) wine64 installed and available in system
|
||||
pub fn try_get_wine_executable(&self) -> Option<String> {
|
||||
pub fn try_get_wine_executable(&self) -> Option<PathBuf> {
|
||||
match self.try_get_selected_wine_info() {
|
||||
Some(selected) => Some(format!("{}/{}/{}", &self.game.wine.builds, selected.name, selected.files.wine64)),
|
||||
Some(selected) => Some(self.game.wine.builds.join(selected.name).join(selected.files.wine64)),
|
||||
None => {
|
||||
if lib::is_available("wine64") {
|
||||
Some(String::from("wine64"))
|
||||
Some(PathBuf::from("wine64"))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -173,34 +174,14 @@ impl Config {
|
|||
/// 2) `Ok(None)` if version wasn't found, so too old or dxvk is not applied
|
||||
/// 3) `Err(..)` if failed to get applied dxvk version, likely because wrong prefix path specified
|
||||
pub fn try_get_selected_dxvk_info(&self) -> std::io::Result<Option<DxvkVersion>> {
|
||||
let (bytes, from, to) = match std::fs::read(format!("{}/drive_c/windows/system32/dxgi.dll", &self.game.wine.prefix)) {
|
||||
Ok(bytes) => (bytes, 1600000, 1700000),
|
||||
Err(_) => {
|
||||
let bytes = std::fs::read(format!("{}/drive_c/windows/system32/d3d11.dll", &self.game.wine.prefix))?;
|
||||
|
||||
(bytes, 2400000, 2500000)
|
||||
}
|
||||
};
|
||||
|
||||
let bytes = if bytes.len() > to {
|
||||
bytes[from..to].to_vec()
|
||||
} else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
Ok({
|
||||
DxvkList::get()
|
||||
.iter()
|
||||
.flat_map(|group| group.versions.clone())
|
||||
.filter(|version| {
|
||||
let version = format!("\0v{}\0", &version.version);
|
||||
let version = version.as_bytes();
|
||||
|
||||
bytes.windows(version.len())
|
||||
.position(|window| window == version)
|
||||
.is_some()
|
||||
})
|
||||
.next()
|
||||
Ok(match Dxvk::get_version(&self.game.wine.prefix)? {
|
||||
Some(version) => {
|
||||
DxvkList::get()
|
||||
.iter()
|
||||
.flat_map(|group| group.versions.clone())
|
||||
.find(move |dxvk| dxvk.version == version)
|
||||
},
|
||||
None => None
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
@ -7,7 +7,7 @@ use crate::lib::consts::launcher_dir;
|
|||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Patch {
|
||||
pub path: String,
|
||||
pub path: PathBuf,
|
||||
pub servers: Vec<String>,
|
||||
pub root: bool
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ impl Default for Patch {
|
|||
let launcher_dir = launcher_dir().expect("Failed to get launcher dir");
|
||||
|
||||
Self {
|
||||
path: format!("{launcher_dir}/patch"),
|
||||
path: launcher_dir.join("patch"),
|
||||
servers: vec![
|
||||
"https://notabug.org/Krock/dawn".to_string(),
|
||||
"https://codespace.gay/Maroxy/dawnin".to_string()
|
||||
|
@ -35,7 +35,10 @@ impl From<&JsonValue> for Patch {
|
|||
|
||||
Self {
|
||||
path: match value.get("path") {
|
||||
Some(value) => value.as_str().unwrap_or(&default.path).to_string(),
|
||||
Some(value) => match value.as_str() {
|
||||
Some(value) => PathBuf::from(value),
|
||||
None => default.path
|
||||
},
|
||||
None => default.path
|
||||
},
|
||||
|
||||
|
|
|
@ -64,10 +64,12 @@ impl Resolution {
|
|||
Self::Custom(w, h) => (*w, *h)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string(&self) -> String {
|
||||
impl std::fmt::Display for Resolution {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let (w, h) = self.get_pair();
|
||||
|
||||
format!("{w}x{h}")
|
||||
f.write_str(&format!("{w}x{h}"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
||||
static mut LAUNCHER_DIR: Option<Option<String>> = None;
|
||||
static mut CONFIG_FILE: Option<Option<String>> = None;
|
||||
use cached::proc_macro::cached;
|
||||
|
||||
/// Timeout used by `anime_game_core::telemetry::is_disabled` to check acessibility of telemetry servers
|
||||
pub const TELEMETRY_CHECK_TIMEOUT: Option<Duration> = Some(Duration::from_secs(3));
|
||||
|
@ -9,38 +9,12 @@ pub const TELEMETRY_CHECK_TIMEOUT: Option<Duration> = Some(Duration::from_secs(3
|
|||
/// Timeout used by `anime_game_core::linux_patch::Patch::try_fetch` to fetch patch info
|
||||
pub const PATCH_FETCHING_TIMEOUT: Option<Duration> = Some(Duration::from_secs(5));
|
||||
|
||||
pub fn launcher_dir() -> Option<String> {
|
||||
unsafe {
|
||||
match &LAUNCHER_DIR {
|
||||
Some(value) => value.clone(),
|
||||
None => {
|
||||
let value = match dirs::data_dir() {
|
||||
Some(dir) => Some(format!("{}/anime-game-launcher", dir.to_string_lossy())),
|
||||
None => None
|
||||
};
|
||||
|
||||
LAUNCHER_DIR = Some(value.clone());
|
||||
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cached]
|
||||
pub fn launcher_dir() -> Option<PathBuf> {
|
||||
dirs::data_dir().map(|dir| dir.join("anime-game-launcher"))
|
||||
}
|
||||
|
||||
pub fn config_file() -> Option<String> {
|
||||
unsafe {
|
||||
match &CONFIG_FILE {
|
||||
Some(value) => value.clone(),
|
||||
None => {
|
||||
let value = match launcher_dir() {
|
||||
Some(dir) => Some(format!("{}/config.json", dir)),
|
||||
None => None
|
||||
};
|
||||
|
||||
CONFIG_FILE = Some(value.clone());
|
||||
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cached]
|
||||
pub fn config_file() -> Option<PathBuf> {
|
||||
launcher_dir().map(|dir| dir.join("config.json"))
|
||||
}
|
||||
|
|
|
@ -33,12 +33,12 @@ impl List {
|
|||
}
|
||||
|
||||
/// List only downloaded DXVK versions in some specific folder
|
||||
pub fn list_downloaded<T: ToString>(folder: T) -> std::io::Result<Vec<Version>> {
|
||||
pub fn list_downloaded<T: Into<PathBuf>>(folder: T) -> std::io::Result<Vec<Version>> {
|
||||
let mut downloaded = Vec::new();
|
||||
|
||||
let list = Self::get();
|
||||
|
||||
for entry in std::fs::read_dir(folder.to_string())? {
|
||||
for entry in std::fs::read_dir(folder.into())? {
|
||||
let name = entry?.file_name();
|
||||
|
||||
for group in &list {
|
||||
|
@ -76,32 +76,34 @@ impl Version {
|
|||
Ok(List::get()[0].versions[0].clone())
|
||||
}
|
||||
|
||||
pub fn is_downloaded_in<T: ToString>(&self, folder: T) -> bool {
|
||||
std::path::Path::new(&format!("{}/{}", folder.to_string(), self.name)).exists()
|
||||
pub fn is_downloaded_in<T: Into<PathBuf>>(&self, folder: T) -> bool {
|
||||
folder.into().join(&self.name).exists()
|
||||
}
|
||||
|
||||
pub fn apply<T: ToString>(&self, dxvks_folder: T, prefix_path: T) -> anyhow::Result<Output> {
|
||||
let apply_path = format!("{}/{}/setup_dxvk.sh", dxvks_folder.to_string(), self.name);
|
||||
pub fn apply<T: Into<PathBuf>>(&self, dxvks_folder: T, prefix_path: T) -> anyhow::Result<Output> {
|
||||
let apply_path = dxvks_folder.into().join(&self.name).join("setup_dxvk.sh");
|
||||
let config = config::get()?;
|
||||
|
||||
let (wine_path, wineserver_path, wineboot_path) = match config.try_get_selected_wine_info() {
|
||||
Some(wine) => {
|
||||
let wine_path = format!("{}/{}/{}", &config.game.wine.builds, wine.name, wine.files.wine64);
|
||||
let wineserver_path = format!("{}/{}/{}", &config.game.wine.builds, wine.name, wine.files.wineserver);
|
||||
let wineboot_path = format!("{}/{}/{}", &config.game.wine.builds, wine.name, wine.files.wineboot);
|
||||
let wine_folder = config.game.wine.builds.join(wine.name);
|
||||
|
||||
let wine_path = wine_folder.join(wine.files.wine64);
|
||||
let wineserver_path = wine_folder.join(wine.files.wineserver);
|
||||
let wineboot_path = wine_folder.join(wine.files.wineboot);
|
||||
|
||||
(wine_path, wineserver_path, wineboot_path)
|
||||
},
|
||||
None => (String::from("wine64"), String::from("wineserver"), String::from("wineboot"))
|
||||
None => (PathBuf::from("wine64"), PathBuf::from("wineserver"), PathBuf::from("wineboot"))
|
||||
};
|
||||
|
||||
let result = Dxvk::install(
|
||||
PathBuf::from(apply_path),
|
||||
PathBuf::from(prefix_path.to_string()),
|
||||
PathBuf::from(&wine_path),
|
||||
PathBuf::from(wine_path),
|
||||
PathBuf::from(wineboot_path),
|
||||
PathBuf::from(wineserver_path)
|
||||
apply_path,
|
||||
prefix_path.into(),
|
||||
wine_path.clone(),
|
||||
wine_path,
|
||||
wineboot_path,
|
||||
wineserver_path
|
||||
);
|
||||
|
||||
match result {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use anime_game_core::installer::downloader::Downloader;
|
||||
|
||||
use crate::lib::config::game::enhancements::fps_unlocker::config::Config as FpsUnlockerConfig;
|
||||
|
@ -11,7 +13,7 @@ const LATEST_INFO: (&str, &str) = (
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct FpsUnlocker {
|
||||
dir: String
|
||||
dir: PathBuf
|
||||
}
|
||||
|
||||
impl FpsUnlocker {
|
||||
|
@ -21,28 +23,32 @@ impl FpsUnlocker {
|
|||
/// - `Err(..)` if failed to read `unlocker.exe` file
|
||||
/// - `Ok(None)` if version is not latest
|
||||
/// - `Ok(..)` if version is latest
|
||||
pub fn from_dir<T: ToString>(dir: T) -> anyhow::Result<Option<Self>> {
|
||||
let hash = format!("{:x}", md5::compute(std::fs::read(format!("{}/unlocker.exe", dir.to_string()))?));
|
||||
pub fn from_dir<T: Into<PathBuf>>(dir: T) -> anyhow::Result<Option<Self>> {
|
||||
let dir = dir.into();
|
||||
|
||||
if hash == LATEST_INFO.0 {
|
||||
Ok(Some(Self { dir: dir.to_string() }))
|
||||
let hash = format!("{:x}", md5::compute(std::fs::read(dir.join("unlocker.exe"))?));
|
||||
|
||||
Ok(if hash == LATEST_INFO.0 {
|
||||
Some(Self { dir })
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
/// Download FPS unlocker to specified directory
|
||||
pub fn download<T: ToString>(dir: T) -> anyhow::Result<Self> {
|
||||
pub fn download<T: Into<PathBuf>>(dir: T) -> anyhow::Result<Self> {
|
||||
let mut downloader = Downloader::new(LATEST_INFO.1)?;
|
||||
|
||||
let dir = dir.into();
|
||||
|
||||
// Create FPS unlocker folder if needed
|
||||
if !std::path::Path::new(&dir.to_string()).exists() {
|
||||
std::fs::create_dir_all(dir.to_string())?;
|
||||
if !dir.exists() {
|
||||
std::fs::create_dir_all(&dir)?;
|
||||
}
|
||||
|
||||
match downloader.download_to(format!("{}/unlocker.exe", dir.to_string()), |_, _| {}) {
|
||||
match downloader.download_to(dir.join("unlocker.exe"), |_, _| {}) {
|
||||
Ok(_) => Ok(Self {
|
||||
dir: dir.to_string()
|
||||
dir
|
||||
}),
|
||||
Err(err) => {
|
||||
let err: std::io::Error = err.into();
|
||||
|
@ -52,16 +58,16 @@ impl FpsUnlocker {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_binary(&self) -> String {
|
||||
pub fn get_binary(&self) -> PathBuf {
|
||||
Self::get_binary_in(&self.dir)
|
||||
}
|
||||
|
||||
pub fn get_binary_in<T: ToString>(dir: T) -> String {
|
||||
format!("{}/unlocker.exe", dir.to_string())
|
||||
pub fn get_binary_in<T: Into<PathBuf>>(dir: T) -> PathBuf {
|
||||
dir.into().join("unlocker.exe")
|
||||
}
|
||||
|
||||
pub fn dir(&self) -> &str {
|
||||
self.dir.as_str()
|
||||
pub fn dir(&self) -> &PathBuf {
|
||||
&self.dir
|
||||
}
|
||||
|
||||
/// Generate and save FPS unlocker config file to the game's directory
|
||||
|
@ -69,7 +75,7 @@ impl FpsUnlocker {
|
|||
let config = config_schema::ConfigSchema::from_config(config);
|
||||
|
||||
Ok(std::fs::write(
|
||||
format!("{}/fps_config.json", self.dir),
|
||||
self.dir.join("fps_config.json"),
|
||||
config.json()?
|
||||
)?)
|
||||
}
|
||||
|
|
|
@ -110,13 +110,13 @@ pub fn run() -> anyhow::Result<()> {
|
|||
return Err(anyhow::anyhow!("Failed to update FPS unlocker config: {err}"));
|
||||
}
|
||||
|
||||
let bat_path = format!("{}/fpsunlocker.bat", config.game.path);
|
||||
let original_bat_path = format!("{}/launcher.bat", config.game.path);
|
||||
let bat_path = config.game.path.join("fpsunlocker.bat");
|
||||
let original_bat_path = config.game.path.join("launcher.bat");
|
||||
|
||||
// Generate fpsunlocker.bat from launcher.bat
|
||||
std::fs::write(bat_path, std::fs::read_to_string(original_bat_path)?
|
||||
.replace("start GenshinImpact.exe %*", &format!("start GenshinImpact.exe %*\n\nZ:\ncd \"{}\"\nstart unlocker.exe", unlocker.dir()))
|
||||
.replace("start YuanShen.exe %*", &format!("start YuanShen.exe %*\n\nZ:\ncd \"{}\"\nstart unlocker.exe", unlocker.dir())))?;
|
||||
.replace("start GenshinImpact.exe %*", &format!("start GenshinImpact.exe %*\n\nZ:\ncd \"{}\"\nstart unlocker.exe", unlocker.dir().to_string_lossy()))
|
||||
.replace("start YuanShen.exe %*", &format!("start YuanShen.exe %*\n\nZ:\ncd \"{}\"\nstart unlocker.exe", unlocker.dir().to_string_lossy())))?;
|
||||
}
|
||||
|
||||
// Prepare bash -c '<command>'
|
||||
|
@ -127,7 +127,7 @@ pub fn run() -> anyhow::Result<()> {
|
|||
bash_chain += "gamemoderun ";
|
||||
}
|
||||
|
||||
bash_chain += &format!("'{wine_executable}' ");
|
||||
bash_chain += &format!("'{}' ", wine_executable.to_string_lossy());
|
||||
|
||||
if let Some(virtual_desktop) = config.game.wine.virtual_desktop.get_command() {
|
||||
bash_chain += &format!("{virtual_desktop} ");
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use anime_game_core::prelude::*;
|
||||
use anime_game_core::genshin::prelude::*;
|
||||
|
||||
|
@ -51,12 +49,12 @@ impl LauncherState {
|
|||
let config = config::get()?;
|
||||
|
||||
// Check wine existence
|
||||
if let None = config.try_get_wine_executable() {
|
||||
if config.try_get_wine_executable().is_none() {
|
||||
return Ok(Self::WineNotInstalled);
|
||||
}
|
||||
|
||||
// Check prefix existence
|
||||
if !PathBuf::from(&config.game.wine.prefix).join("drive_c").exists() {
|
||||
if !config.game.wine.prefix.join("drive_c").exists() {
|
||||
return Ok(Self::PrefixNotExists);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,12 +37,12 @@ impl List {
|
|||
}
|
||||
|
||||
/// List only downloaded wine versions in some specific folder
|
||||
pub fn list_downloaded<T: ToString>(folder: T) -> std::io::Result<Vec<Version>> {
|
||||
pub fn list_downloaded<T: Into<PathBuf>>(folder: T) -> std::io::Result<Vec<Version>> {
|
||||
let mut downloaded = Vec::new();
|
||||
|
||||
let list = Self::get();
|
||||
|
||||
for entry in std::fs::read_dir(folder.to_string())? {
|
||||
for entry in std::fs::read_dir(folder.into())? {
|
||||
let name = entry?.file_name();
|
||||
|
||||
for group in &list {
|
||||
|
|
|
@ -69,9 +69,9 @@ fn main() {
|
|||
// Create default launcher folder if needed
|
||||
let launcher_dir = lib::consts::launcher_dir().expect("Failed to get launcher dir");
|
||||
|
||||
if !Path::new(&launcher_dir).exists() || Path::new(&format!("{}/.first-run", launcher_dir)).exists() {
|
||||
if !launcher_dir.exists() || launcher_dir.join(".first-run").exists() {
|
||||
fs::create_dir_all(&launcher_dir).expect("Failed to create default launcher dir");
|
||||
fs::write(format!("{}/.first-run", launcher_dir), "").expect("Failed to create .first-run file");
|
||||
fs::write(launcher_dir.join(".first-run"), "").expect("Failed to create .first-run file");
|
||||
|
||||
let first_run = FirstRunApp::new(app).expect("Failed to init FirstRunApp");
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use adw::prelude::*;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::lib::dxvk::Group;
|
||||
use super::dxvk_row::DxvkRow;
|
||||
|
||||
|
@ -35,9 +37,11 @@ impl DxvkGroup {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn update_states<T: ToString>(&self, runners_folder: T) {
|
||||
pub fn update_states<T: Into<PathBuf>>(&self, runners_folder: T) {
|
||||
let runners_folder = runners_folder.into();
|
||||
|
||||
for component in &self.version_components {
|
||||
component.update_state(runners_folder.to_string());
|
||||
component.update_state(&runners_folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use gtk::prelude::*;
|
||||
use adw::prelude::*;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::lib::dxvk::Version;
|
||||
use crate::ui::traits::download_component::*;
|
||||
|
||||
|
@ -57,7 +59,7 @@ impl DxvkRow {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn update_state<T: ToString>(&self, dxvks_folder: T) {
|
||||
pub fn update_state<T: Into<PathBuf>>(&self, dxvks_folder: T) {
|
||||
if self.is_downloaded(dxvks_folder) {
|
||||
self.button.set_icon_name("user-trash-symbolic");
|
||||
|
||||
|
@ -71,7 +73,7 @@ impl DxvkRow {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn apply<T: ToString>(&self, dxvks_folder: T, prefix_path: T) -> anyhow::Result<std::process::Output> {
|
||||
pub fn apply<T: Into<PathBuf>>(&self, dxvks_folder: T, prefix_path: T) -> anyhow::Result<std::process::Output> {
|
||||
self.button.set_sensitive(false);
|
||||
self.apply_button.set_sensitive(false);
|
||||
|
||||
|
@ -85,8 +87,8 @@ impl DxvkRow {
|
|||
}
|
||||
|
||||
impl DownloadComponent for DxvkRow {
|
||||
fn get_component_path<T: ToString>(&self, installation_path: T) -> String {
|
||||
format!("{}/{}", installation_path.to_string(), self.version.name)
|
||||
fn get_component_path<T: Into<PathBuf>>(&self, installation_path: T) -> PathBuf {
|
||||
installation_path.into().join(&self.version.name)
|
||||
}
|
||||
|
||||
fn get_downloading_widgets(&self) -> (gtk::ProgressBar, gtk::Button) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use adw::prelude::*;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::lib::wine::Group;
|
||||
use super::wine_row::WineRow;
|
||||
|
||||
|
@ -35,9 +37,11 @@ impl WineGroup {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn update_states<T: ToString>(&self, runners_folder: T) {
|
||||
pub fn update_states<T: Into<PathBuf>>(&self, runners_folder: T) {
|
||||
let runners_folder = runners_folder.into();
|
||||
|
||||
for component in &self.version_components {
|
||||
component.update_state(runners_folder.to_string());
|
||||
component.update_state(&runners_folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use gtk::prelude::*;
|
||||
use adw::prelude::*;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::lib::wine::Version;
|
||||
use crate::ui::traits::download_component::*;
|
||||
|
||||
|
@ -46,7 +48,7 @@ impl WineRow {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn update_state<T: ToString>(&self, runners_folder: T) {
|
||||
pub fn update_state<T: Into<PathBuf>>(&self, runners_folder: T) {
|
||||
if self.is_downloaded(runners_folder) {
|
||||
self.button.set_icon_name("user-trash-symbolic");
|
||||
}
|
||||
|
@ -58,8 +60,8 @@ impl WineRow {
|
|||
}
|
||||
|
||||
impl DownloadComponent for WineRow {
|
||||
fn get_component_path<T: ToString>(&self, installation_path: T) -> String {
|
||||
format!("{}/{}", installation_path.to_string(), self.version.name)
|
||||
fn get_component_path<T: Into<PathBuf>>(&self, installation_path: T) -> PathBuf {
|
||||
installation_path.into().join(&self.version.name)
|
||||
}
|
||||
|
||||
fn get_downloading_widgets(&self) -> (gtk::ProgressBar, gtk::Button) {
|
||||
|
|
|
@ -3,6 +3,8 @@ use adw::prelude::*;
|
|||
use gtk::glib;
|
||||
use gtk::glib::clone;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use wait_not_await::Await;
|
||||
|
||||
use crate::lib::config;
|
||||
|
@ -65,13 +67,13 @@ impl Page {
|
|||
let config = config::get()?;
|
||||
|
||||
// Add paths to subtitles
|
||||
result.runners_folder.set_subtitle(&config.game.wine.builds);
|
||||
result.dxvk_folder.set_subtitle(&config.game.dxvk.builds);
|
||||
result.prefix_folder.set_subtitle(&config.game.wine.prefix);
|
||||
result.game_folder.set_subtitle(&config.game.path);
|
||||
result.patch_folder.set_subtitle(&config.patch.path);
|
||||
result.runners_folder.set_subtitle(config.game.wine.builds.to_str().unwrap());
|
||||
result.dxvk_folder.set_subtitle(config.game.dxvk.builds.to_str().unwrap());
|
||||
result.prefix_folder.set_subtitle(config.game.wine.prefix.to_str().unwrap());
|
||||
result.game_folder.set_subtitle(config.game.path.to_str().unwrap());
|
||||
result.patch_folder.set_subtitle(config.patch.path.to_str().unwrap());
|
||||
result.temp_folder.set_subtitle(&match config.launcher.temp {
|
||||
Some(temp) => temp,
|
||||
Some(temp) => temp.to_string_lossy().to_string(),
|
||||
None => String::from("/tmp")
|
||||
});
|
||||
|
||||
|
@ -107,12 +109,12 @@ impl Page {
|
|||
}
|
||||
|
||||
pub fn update_config(&self, mut config: config::Config) -> config::Config {
|
||||
config.game.wine.builds = self.runners_folder.subtitle().unwrap().to_string();
|
||||
config.game.dxvk.builds = self.dxvk_folder.subtitle().unwrap().to_string();
|
||||
config.game.wine.prefix = self.prefix_folder.subtitle().unwrap().to_string();
|
||||
config.game.path = self.game_folder.subtitle().unwrap().to_string();
|
||||
config.patch.path = self.patch_folder.subtitle().unwrap().to_string();
|
||||
config.launcher.temp = Some(self.temp_folder.subtitle().unwrap().to_string());
|
||||
config.game.wine.builds = PathBuf::from(self.runners_folder.subtitle().unwrap().to_string());
|
||||
config.game.dxvk.builds = PathBuf::from(self.dxvk_folder.subtitle().unwrap().to_string());
|
||||
config.game.wine.prefix = PathBuf::from(self.prefix_folder.subtitle().unwrap().to_string());
|
||||
config.game.path = PathBuf::from(self.game_folder.subtitle().unwrap().to_string());
|
||||
config.patch.path = PathBuf::from(self.patch_folder.subtitle().unwrap().to_string());
|
||||
config.launcher.temp = Some(PathBuf::from(self.temp_folder.subtitle().unwrap().to_string()));
|
||||
|
||||
config
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ use gtk::glib::clone;
|
|||
use std::rc::Rc;
|
||||
use std::cell::Cell;
|
||||
use std::process::Command;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anime_game_core::prelude::*;
|
||||
|
||||
|
@ -248,7 +247,7 @@ impl App {
|
|||
|
||||
let progress_bar = this.widgets.download_components.progress_bar.clone();
|
||||
|
||||
let wine_version = this.widgets.download_components.get_wine_version().clone();
|
||||
let wine_version = this.widgets.download_components.get_wine_version();
|
||||
let dxvk_version = this.widgets.download_components.get_dxvk_version().clone();
|
||||
|
||||
// Prepare wine downloader
|
||||
|
@ -262,7 +261,7 @@ impl App {
|
|||
match Installer::new(&wine_version_copy.uri) {
|
||||
Ok(mut installer) => {
|
||||
if let Some(temp_folder) = config.launcher.temp {
|
||||
installer.temp_folder = PathBuf::from(temp_folder);
|
||||
installer.temp_folder = temp_folder;
|
||||
}
|
||||
|
||||
installer.downloader
|
||||
|
@ -333,7 +332,7 @@ impl App {
|
|||
match Installer::new(&dxvk_version.uri) {
|
||||
Ok(mut installer) => {
|
||||
if let Some(temp_folder) = config.launcher.temp {
|
||||
installer.temp_folder = PathBuf::from(temp_folder);
|
||||
installer.temp_folder = temp_folder;
|
||||
}
|
||||
|
||||
installer.downloader
|
||||
|
@ -393,9 +392,9 @@ impl App {
|
|||
|
||||
// Remove .first-run file
|
||||
let launcher_dir = crate::lib::consts::launcher_dir().unwrap();
|
||||
|
||||
std::fs::remove_file(format!("{}/.first-run", launcher_dir)).unwrap();
|
||||
|
||||
|
||||
std::fs::remove_file(launcher_dir.join(".first-run")).unwrap();
|
||||
|
||||
// Show next page
|
||||
this.update(Actions::DownloadComponentsContinue).unwrap();
|
||||
},
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::rc::Rc;
|
|||
use std::cell::Cell;
|
||||
use std::io::Error;
|
||||
use std::process::{Command, Stdio};
|
||||
use std::path::PathBuf;
|
||||
use std::path::Path;
|
||||
|
||||
use wait_not_await::Await;
|
||||
|
||||
|
@ -68,7 +68,7 @@ impl AppWidgets {
|
|||
|
||||
let result = Self {
|
||||
window: window.clone(),
|
||||
toast_overlay: toast_overlay.clone(),
|
||||
toast_overlay,
|
||||
|
||||
menu: get_object(&builder, "menu")?,
|
||||
about: get_object(&builder, "about")?,
|
||||
|
@ -127,6 +127,7 @@ impl AppWidgets {
|
|||
|
||||
let curl_info = anime_game_core::curl_sys::Version::get();
|
||||
|
||||
#[allow(clippy::or_fun_call)]
|
||||
result.about.set_debug_info(&[
|
||||
format!("Anime Game core library version: {}", anime_game_core::VERSION),
|
||||
format!("Curl version: {}", curl_info.version()),
|
||||
|
@ -162,6 +163,7 @@ pub enum Actions {
|
|||
}
|
||||
|
||||
impl Actions {
|
||||
#[allow(clippy::expect_fun_call, clippy::wrong_self_convention)]
|
||||
pub fn into_fn<T: gtk::glib::IsA<gtk::Widget>>(&self, app: &App) -> Box<dyn Fn(&T)> {
|
||||
Box::new(clone!(@strong self as action, @weak app => move |_| {
|
||||
app.update(action.clone()).expect(&format!("Failed to execute action {:?}", &action));
|
||||
|
@ -443,7 +445,7 @@ impl App {
|
|||
match Installer::new(wine.uri) {
|
||||
Ok(mut installer) => {
|
||||
if let Some(temp_folder) = config.launcher.temp {
|
||||
installer.temp_folder = PathBuf::from(temp_folder);
|
||||
installer.temp_folder = temp_folder;
|
||||
}
|
||||
|
||||
installer.downloader
|
||||
|
@ -750,7 +752,7 @@ impl App {
|
|||
}).unwrap();
|
||||
}
|
||||
|
||||
if broken.len() > 0 {
|
||||
if !broken.is_empty() {
|
||||
this.update(Actions::UpdateProgress {
|
||||
fraction: Rc::new(0.0),
|
||||
title: Rc::new(String::from("Repairing files: 0%"))
|
||||
|
@ -771,7 +773,7 @@ impl App {
|
|||
|
||||
println!("Patch status: {}", is_patch_applied);
|
||||
|
||||
fn should_ignore(path: &PathBuf) -> bool {
|
||||
fn should_ignore(path: &Path) -> bool {
|
||||
for part in ["UnityPlayer.dll", "xlua.dll", "crashreport.exe", "upload_crash.exe", "vulkan-1.dll"] {
|
||||
if path.ends_with(part) {
|
||||
return true;
|
||||
|
@ -890,7 +892,7 @@ impl App {
|
|||
// Calculate size of the update
|
||||
let size =
|
||||
game.size().unwrap_or((0, 0)).0 +
|
||||
voices.into_iter().fold(0, |acc, voice| acc + voice.size().unwrap_or((0, 0)).0);
|
||||
voices.iter().fold(0, |acc, voice| acc + voice.size().unwrap_or((0, 0)).0);
|
||||
|
||||
// Update tooltip
|
||||
self.widgets.predownload_game.set_tooltip_text(Some(&format!("Pre-download {} update ({})", game.latest(), prettify_bytes(size))));
|
||||
|
@ -902,12 +904,10 @@ impl App {
|
|||
|
||||
if let Ok(config) = config::get() {
|
||||
if let Some(temp) = config.launcher.temp {
|
||||
let tmp = PathBuf::from(temp);
|
||||
|
||||
// If all the files were downloaded
|
||||
let downloaded =
|
||||
tmp.join(game.file_name().unwrap()).exists() &&
|
||||
voices.into_iter().fold(true, move |acc, voice| acc && tmp.join(voice.file_name().unwrap()).exists());
|
||||
temp.join(game.file_name().unwrap()).exists() &&
|
||||
voices.iter().all(|voice| temp.join(voice.file_name().unwrap()).exists());
|
||||
|
||||
if downloaded {
|
||||
self.widgets.predownload_game.remove_css_class("warning");
|
||||
|
|
|
@ -146,34 +146,32 @@ impl App {
|
|||
Actions::Add(strs) => {
|
||||
let (name, value) = &*strs;
|
||||
|
||||
if !name.is_empty() && !value.is_empty() {
|
||||
if !values.rows.contains_key(name) {
|
||||
config.game.environment.insert(name.clone(), value.clone());
|
||||
if !name.is_empty() && !value.is_empty() && !values.rows.contains_key(name) {
|
||||
config.game.environment.insert(name.clone(), value.clone());
|
||||
|
||||
let row = adw::ActionRow::new();
|
||||
let row = adw::ActionRow::new();
|
||||
|
||||
row.set_title(name);
|
||||
row.set_subtitle(value);
|
||||
row.set_title(name);
|
||||
row.set_subtitle(value);
|
||||
|
||||
let button = gtk::Button::new();
|
||||
let button = gtk::Button::new();
|
||||
|
||||
button.set_icon_name("user-trash-symbolic");
|
||||
button.set_valign(gtk::Align::Center);
|
||||
button.add_css_class("flat");
|
||||
button.set_icon_name("user-trash-symbolic");
|
||||
button.set_valign(gtk::Align::Center);
|
||||
button.add_css_class("flat");
|
||||
|
||||
button.connect_clicked(clone!(@weak this, @strong name => move |_| {
|
||||
this.update(Actions::Delete(Rc::new(name.clone()))).unwrap();
|
||||
}));
|
||||
button.connect_clicked(clone!(@weak this, @strong name => move |_| {
|
||||
this.update(Actions::Delete(Rc::new(name.clone()))).unwrap();
|
||||
}));
|
||||
|
||||
row.add_suffix(&button);
|
||||
row.add_suffix(&button);
|
||||
|
||||
this.widgets.variables.add(&row);
|
||||
this.widgets.variables.add(&row);
|
||||
|
||||
values.rows.insert(name.clone(), row);
|
||||
values.rows.insert(name.clone(), row);
|
||||
|
||||
this.widgets.name.set_text("");
|
||||
this.widgets.value.set_text("");
|
||||
}
|
||||
this.widgets.name.set_text("");
|
||||
this.widgets.value.set_text("");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -230,7 +228,7 @@ impl App {
|
|||
status_page.set_description(Some("Loading environment..."));
|
||||
|
||||
// Set game command
|
||||
self.widgets.command.set_text(&config.game.command.unwrap_or(String::new()));
|
||||
self.widgets.command.set_text(&config.game.command.unwrap_or_default());
|
||||
|
||||
// Add environment variables
|
||||
for (name, value) in config.game.environment {
|
||||
|
|
|
@ -152,6 +152,7 @@ pub enum Actions {
|
|||
}
|
||||
|
||||
impl Actions {
|
||||
#[allow(clippy::expect_fun_call, clippy::wrong_self_convention)]
|
||||
pub fn into_fn<T: gtk::glib::IsA<gtk::Widget>>(&self, app: &App) -> Box<dyn Fn(&T)> {
|
||||
Box::new(clone!(@strong self as action, @weak app => move |_| {
|
||||
app.update(action.clone()).expect(&format!("Failed to execute action {:?}", &action));
|
||||
|
@ -211,7 +212,7 @@ impl App {
|
|||
self.widgets.repair_game.connect_clicked(Actions::RepairGame.into_fn(&self));
|
||||
|
||||
// Voiceover download/delete button event
|
||||
for (i, row) in (&*self.widgets.voieover_components).into_iter().enumerate() {
|
||||
for (i, row) in (*self.widgets.voieover_components).iter().enumerate() {
|
||||
row.button.connect_clicked(clone!(@weak self as this => move |_| {
|
||||
this.update(Actions::VoiceoverPerformAction(Rc::new(i))).unwrap();
|
||||
}));
|
||||
|
@ -251,8 +252,8 @@ impl App {
|
|||
// Wine install/remove buttons
|
||||
let components = &*self.widgets.wine_components;
|
||||
|
||||
for (i, group) in components.into_iter().enumerate() {
|
||||
for (j, component) in (&group.version_components).into_iter().enumerate() {
|
||||
for (i, group) in components.iter().enumerate() {
|
||||
for (j, component) in group.version_components.iter().enumerate() {
|
||||
component.button.connect_clicked(Actions::WinePerformAction(Rc::new((i, j))).into_fn(&self));
|
||||
}
|
||||
}
|
||||
|
@ -273,8 +274,8 @@ impl App {
|
|||
// DXVK install/remove/apply buttons
|
||||
let components = &*self.widgets.dxvk_components;
|
||||
|
||||
for (i, group) in components.into_iter().enumerate() {
|
||||
for (j, component) in (&group.version_components).into_iter().enumerate() {
|
||||
for (i, group) in components.iter().enumerate() {
|
||||
for (j, component) in group.version_components.iter().enumerate() {
|
||||
component.button.connect_clicked(Actions::DxvkPerformAction(Rc::new((i, j))).into_fn(&self));
|
||||
|
||||
component.apply_button.connect_clicked(clone!(@strong component, @weak self as this => move |_| {
|
||||
|
@ -314,7 +315,7 @@ impl App {
|
|||
|
||||
match action {
|
||||
Actions::RepairGame => {
|
||||
let option = (&*this.app).take();
|
||||
let option = (*this.app).take();
|
||||
this.app.set(option.clone());
|
||||
|
||||
let app = option.unwrap();
|
||||
|
@ -345,7 +346,7 @@ impl App {
|
|||
}
|
||||
|
||||
else {
|
||||
let option = (&*this.app).take();
|
||||
let option = (*this.app).take();
|
||||
this.app.set(option.clone());
|
||||
|
||||
let app = option.unwrap();
|
||||
|
@ -382,23 +383,21 @@ impl App {
|
|||
this.update(Actions::UpdateDxvkComboRow).unwrap();
|
||||
}
|
||||
|
||||
else {
|
||||
if let Ok(awaiter) = component.download(&config.game.dxvk.builds) {
|
||||
awaiter.then(clone!(@strong this => move |_| {
|
||||
match component.apply(&config.game.dxvk.builds, &config.game.wine.prefix) {
|
||||
Ok(output) => println!("{}", String::from_utf8_lossy(&output.stdout)),
|
||||
Err(err) => {
|
||||
this.update(Actions::Toast(Rc::new((
|
||||
String::from("Failed to apply DXVK"), err.to_string()
|
||||
)))).unwrap();
|
||||
}
|
||||
else if let Ok(awaiter) = component.download(&config.game.dxvk.builds) {
|
||||
awaiter.then(clone!(@strong this => move |_| {
|
||||
match component.apply(&config.game.dxvk.builds, &config.game.wine.prefix) {
|
||||
Ok(output) => println!("{}", String::from_utf8_lossy(&output.stdout)),
|
||||
Err(err) => {
|
||||
this.update(Actions::Toast(Rc::new((
|
||||
String::from("Failed to apply DXVK"), err.to_string()
|
||||
)))).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
component.update_state(&config.game.dxvk.builds);
|
||||
component.update_state(&config.game.dxvk.builds);
|
||||
|
||||
this.update(Actions::UpdateDxvkComboRow).unwrap();
|
||||
}));
|
||||
}
|
||||
this.update(Actions::UpdateDxvkComboRow).unwrap();
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,14 +418,12 @@ impl App {
|
|||
this.update(Actions::UpdateWineComboRow).unwrap();
|
||||
}
|
||||
|
||||
else {
|
||||
if let Ok(awaiter) = component.download(&config.game.wine.builds) {
|
||||
awaiter.then(clone!(@strong this => move |_| {
|
||||
component.update_state(&config.game.wine.builds);
|
||||
else if let Ok(awaiter) = component.download(&config.game.wine.builds) {
|
||||
awaiter.then(clone!(@strong this => move |_| {
|
||||
component.update_state(&config.game.wine.builds);
|
||||
|
||||
this.update(Actions::UpdateWineComboRow).unwrap();
|
||||
}));
|
||||
}
|
||||
this.update(Actions::UpdateWineComboRow).unwrap();
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -518,7 +515,7 @@ impl App {
|
|||
|
||||
let mut selected = 0;
|
||||
|
||||
for (i, version) in (&list).into_iter().enumerate() {
|
||||
for (i, version) in list.iter().enumerate() {
|
||||
model.append(version.title.as_str());
|
||||
|
||||
if let Some(curr) = &config.game.wine.selected {
|
||||
|
@ -708,7 +705,7 @@ impl App {
|
|||
|
||||
impl Toast for App {
|
||||
fn get_toast_widgets(&self) -> (adw::ApplicationWindow, adw::ToastOverlay) {
|
||||
let app = (&*self.app).take();
|
||||
let app = (*self.app).take();
|
||||
self.app.set(app.clone());
|
||||
|
||||
app.unwrap().get_toast_widgets()
|
||||
|
|
|
@ -91,7 +91,7 @@ impl PreferencesStack {
|
|||
|
||||
impl Toast for PreferencesStack {
|
||||
fn get_toast_widgets(&self) -> (adw::ApplicationWindow, adw::ToastOverlay) {
|
||||
let app = (&*self.app).take();
|
||||
let app = (*self.app).take();
|
||||
self.app.set(app.clone());
|
||||
|
||||
app.unwrap().get_toast_widgets()
|
||||
|
|
|
@ -17,15 +17,15 @@ pub enum DownloadingResult {
|
|||
}
|
||||
|
||||
pub trait DownloadComponent {
|
||||
fn get_component_path<T: ToString>(&self, installation_path: T) -> String;
|
||||
fn get_component_path<T: Into<PathBuf>>(&self, installation_path: T) -> PathBuf;
|
||||
fn get_downloading_widgets(&self) -> (gtk::ProgressBar, gtk::Button);
|
||||
fn get_download_uri(&self) -> String;
|
||||
|
||||
fn is_downloaded<T: ToString>(&self, installation_path: T) -> bool {
|
||||
fn is_downloaded<T: Into<PathBuf>>(&self, installation_path: T) -> bool {
|
||||
Path::new(&self.get_component_path(installation_path)).exists()
|
||||
}
|
||||
|
||||
fn download<T: ToString>(&self, installation_path: T) -> anyhow::Result<Await<DownloadingResult>> {
|
||||
fn download<T: Into<PathBuf>>(&self, installation_path: T) -> anyhow::Result<Await<DownloadingResult>> {
|
||||
let (sender, receiver) = glib::MainContext::channel::<InstallerUpdate>(glib::PRIORITY_DEFAULT);
|
||||
let (progress_bar, button) = self.get_downloading_widgets();
|
||||
|
||||
|
@ -66,11 +66,11 @@ pub trait DownloadComponent {
|
|||
}
|
||||
|
||||
InstallerUpdate::DownloadingError(err) => {
|
||||
downl_send.send(DownloadingResult::DownloadingError(err.into())).unwrap();
|
||||
downl_send.send(DownloadingResult::DownloadingError(err)).unwrap();
|
||||
}
|
||||
|
||||
InstallerUpdate::UnpackingError(err) => {
|
||||
downl_send.send(DownloadingResult::UnpackingError(err.to_string())).unwrap();
|
||||
downl_send.send(DownloadingResult::UnpackingError(err)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,17 +83,17 @@ pub trait DownloadComponent {
|
|||
let mut installer = Installer::new(self.get_download_uri())?;
|
||||
|
||||
if let Some(temp_folder) = config.launcher.temp {
|
||||
installer.temp_folder = PathBuf::from(temp_folder);
|
||||
installer.temp_folder = temp_folder;
|
||||
}
|
||||
|
||||
installer.downloader
|
||||
.set_downloading_speed(config.launcher.speed_limit)
|
||||
.expect("Failed to set downloading speed limit");
|
||||
|
||||
let installation_path = installation_path.to_string();
|
||||
|
||||
send.send(installer).unwrap();
|
||||
|
||||
let installation_path = installation_path.into();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let mut installer = recv.recv().unwrap();
|
||||
|
||||
|
@ -107,7 +107,7 @@ pub trait DownloadComponent {
|
|||
}))
|
||||
}
|
||||
|
||||
fn delete<T: ToString>(&self, installation_path: T) -> std::io::Result<()> {
|
||||
fn delete<T: Into<PathBuf>>(&self, installation_path: T) -> std::io::Result<()> {
|
||||
std::fs::remove_dir_all(self.get_component_path(installation_path))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ pub trait Toast {
|
|||
|
||||
let message = format!("{}", message);
|
||||
|
||||
if message.len() > 0 {
|
||||
if !message.is_empty() {
|
||||
toast.set_button_label(Some("See message"));
|
||||
toast.set_action_name(Some("see-message.see-message"));
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue