mirror of
https://github.com/an-anime-team/sleepy-launcher.git
synced 2025-02-16 09:49:46 +03:00
feat: initial transition to the new sdk version
This commit is contained in:
parent
35710a83ae
commit
08725de1e0
20 changed files with 67 additions and 655 deletions
20
Cargo.lock
generated
20
Cargo.lock
generated
|
@ -57,8 +57,8 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
|||
|
||||
[[package]]
|
||||
name = "anime-game-core"
|
||||
version = "1.20.2"
|
||||
source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.20.2#3f013bffed78ca9c22db1d8bb10d4ae8ef527c5c"
|
||||
version = "1.21.0"
|
||||
source = "git+https://github.com/an-anime-team/anime-game-core?tag=1.21.0#d4ec0fde4c467f37bf7eaa8332949fd84b3d631a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bzip2",
|
||||
|
@ -82,8 +82,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anime-launcher-sdk"
|
||||
version = "1.15.4"
|
||||
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.15.4#eebd048fb05034959fd06e499fcdfaebbcce1d6c"
|
||||
version = "1.16.0"
|
||||
source = "git+https://github.com/an-anime-team/anime-launcher-sdk?tag=1.16.0#b55ea3f4606dffc3d63760d56a903f99417c673b"
|
||||
dependencies = [
|
||||
"anime-game-core",
|
||||
"anyhow",
|
||||
|
@ -463,9 +463,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cached"
|
||||
version = "0.51.4"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0feb64151eed3da6107fddd2d717a6ca4b9dbd74e43784c55c841d1abfe5a295"
|
||||
checksum = "a8466736fe5dbcaf8b8ee24f9bbefe43c884dc3e9ff7178da70f55bffca1133c"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"cached_proc_macro",
|
||||
|
@ -478,9 +478,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cached_proc_macro"
|
||||
version = "0.21.0"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "771aa57f3b17da6c8bcacb187bb9ec9bc81c8160e72342e67c329e0e1651a669"
|
||||
checksum = "575f32e012222055211b70f5b0601f951f84523410a0e65c81f2744a6042450d"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
|
@ -1901,9 +1901,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
|||
|
||||
[[package]]
|
||||
name = "open"
|
||||
version = "5.1.4"
|
||||
version = "5.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5ca541f22b1c46d4bb9801014f234758ab4297e7870b904b6a8415b980a7388"
|
||||
checksum = "9d2c909a3fce3bd80efef4cd1c6c056bd9376a8fe06fcfdbebaf32cb485a7e37"
|
||||
dependencies = [
|
||||
"is-wsl",
|
||||
"libc",
|
||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -19,8 +19,8 @@ glib-build-tools = "0.19"
|
|||
|
||||
[dependencies.anime-launcher-sdk]
|
||||
git = "https://github.com/an-anime-team/anime-launcher-sdk"
|
||||
tag = "1.15.4"
|
||||
features = ["all", "genshin"]
|
||||
tag = "1.16.0"
|
||||
features = ["all", "zzz"]
|
||||
|
||||
# path = "../anime-launcher-sdk" # ! for dev purposes only
|
||||
|
||||
|
@ -30,13 +30,13 @@ gtk = { package = "gtk4", version = "0.8.1", features = ["v4_12"] }
|
|||
adw = { package = "libadwaita", version = "0.6.0", features = ["v1_4"] }
|
||||
|
||||
rfd = { version = "0.14.1", features = ["xdg-portal", "tokio"], default-features = false }
|
||||
open = "5.0.0"
|
||||
open = "5.2.0"
|
||||
whatadistro = "0.1.0"
|
||||
|
||||
serde_json = "1.0"
|
||||
anyhow = "1.0"
|
||||
lazy_static = "1.4.0"
|
||||
cached = { version = "0.51", features = ["proc_macro"] }
|
||||
lazy_static = "1.5.0"
|
||||
cached = { version = "0.52", features = ["proc_macro"] }
|
||||
md-5 = { version = "0.10", features = ["asm"] }
|
||||
enum-ordinalize = "4.3"
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ in pkgs.mkShell {
|
|||
pkg-config
|
||||
|
||||
xdelta
|
||||
p7zip
|
||||
libwebp
|
||||
];
|
||||
|
||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -4,16 +4,16 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
|||
use relm4::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::config::ConfigExt;
|
||||
use anime_launcher_sdk::genshin::config::{Config, Schema};
|
||||
use anime_launcher_sdk::zzz::config::{Config, Schema};
|
||||
|
||||
use anime_launcher_sdk::genshin::states::LauncherState;
|
||||
use anime_launcher_sdk::genshin::consts::*;
|
||||
use anime_launcher_sdk::zzz::states::LauncherState;
|
||||
use anime_launcher_sdk::zzz::consts::*;
|
||||
|
||||
use anime_launcher_sdk::anime_game_core::prelude::*;
|
||||
use anime_launcher_sdk::anime_game_core::genshin::prelude::*;
|
||||
use anime_launcher_sdk::anime_game_core::zzz::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::sessions::SessionsExt;
|
||||
use anime_launcher_sdk::genshin::sessions::Sessions;
|
||||
use anime_launcher_sdk::zzz::sessions::Sessions;
|
||||
|
||||
use tracing_subscriber::prelude::*;
|
||||
use tracing_subscriber::filter::*;
|
||||
|
@ -233,13 +233,13 @@ fn main() -> anyhow::Result<()> {
|
|||
|
||||
match state {
|
||||
LauncherState::Launch => {
|
||||
anime_launcher_sdk::genshin::game::run().expect("Failed to run the game");
|
||||
anime_launcher_sdk::zzz::game::run().expect("Failed to run the game");
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
LauncherState::PredownloadAvailable { .. } if just_run_game => {
|
||||
anime_launcher_sdk::genshin::game::run().expect("Failed to run the game");
|
||||
anime_launcher_sdk::zzz::game::run().expect("Failed to run the game");
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use relm4::prelude::*;
|
|||
use adw::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::anime_game_core::prelude::*;
|
||||
use anime_launcher_sdk::anime_game_core::genshin::prelude::*;
|
||||
use anime_launcher_sdk::anime_game_core::zzz::prelude::*;
|
||||
|
||||
use crate::*;
|
||||
|
||||
|
|
|
@ -8,10 +8,10 @@ use adw::prelude::*;
|
|||
use gtk::glib::clone;
|
||||
|
||||
use anime_launcher_sdk::anime_game_core::prelude::*;
|
||||
use anime_launcher_sdk::anime_game_core::genshin::prelude::*;
|
||||
use anime_launcher_sdk::anime_game_core::zzz::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::config::ConfigExt;
|
||||
use anime_launcher_sdk::genshin::config::Config;
|
||||
use anime_launcher_sdk::zzz::config::Config;
|
||||
|
||||
use super::ComponentGroupMsg;
|
||||
use super::progress_bar::ProgressBarMsg;
|
||||
|
|
|
@ -21,7 +21,6 @@ pub struct DefaultPathsApp {
|
|||
prefix: PathBuf,
|
||||
game_global: PathBuf,
|
||||
game_china: PathBuf,
|
||||
fps_unlocker: PathBuf,
|
||||
components: PathBuf,
|
||||
temp: PathBuf
|
||||
}
|
||||
|
@ -34,7 +33,6 @@ pub enum Folders {
|
|||
Prefix,
|
||||
GameGlobal,
|
||||
GameChina,
|
||||
FpsUnlocker,
|
||||
Components,
|
||||
Temp
|
||||
}
|
||||
|
@ -186,20 +184,6 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
}
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr!("fps-unlocker-folder"),
|
||||
set_activatable: true,
|
||||
|
||||
#[watch]
|
||||
set_subtitle: model.fps_unlocker.to_str().unwrap(),
|
||||
|
||||
connect_activated => DefaultPathsAppMsg::ChoosePath(Folders::FpsUnlocker),
|
||||
|
||||
add_prefix = >k::Image {
|
||||
set_icon_name: Some("folder-symbolic")
|
||||
}
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr!("components-index"),
|
||||
set_activatable: true,
|
||||
|
@ -308,7 +292,6 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
prefix: CONFIG.game.wine.prefix.clone(),
|
||||
game_global: CONFIG.game.path.global.clone(),
|
||||
game_china: CONFIG.game.path.china.clone(),
|
||||
fps_unlocker: CONFIG.game.enhancements.fps_unlocker.path.clone(),
|
||||
components: CONFIG.components.path.clone(),
|
||||
|
||||
#[allow(clippy::or_fun_call)]
|
||||
|
@ -340,9 +323,8 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
self.runners = result.join("runners");
|
||||
self.dxvks = result.join("dxvks");
|
||||
self.prefix = result.join("prefix");
|
||||
self.game_global = result.join(concat!("Ge", "nshi", "n Imp", "act"));
|
||||
self.game_china = result.join(concat!("Yu", "anS", "hen"));
|
||||
self.fps_unlocker = result.join("fps-unlocker");
|
||||
self.game_global = result.join(concat!("Zen", "less Z", "one Zero"));
|
||||
self.game_china = result.join(concat!("Zen", "less Z", "one Zero"));
|
||||
self.components = result.join("components");
|
||||
|
||||
self.temp.clone_from(&result);
|
||||
|
@ -355,7 +337,6 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
Folders::Prefix => self.prefix = result,
|
||||
Folders::GameGlobal => self.game_global = result,
|
||||
Folders::GameChina => self.game_china = result,
|
||||
Folders::FpsUnlocker => self.fps_unlocker = result,
|
||||
Folders::Components => self.components = result,
|
||||
Folders::Temp => self.temp = result
|
||||
}
|
||||
|
@ -379,9 +360,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
(old_config.game.wine.prefix, &self.prefix),
|
||||
(old_config.game.path.global, &self.game_global),
|
||||
(old_config.game.path.china, &self.game_china),
|
||||
(old_config.components.path, &self.components),
|
||||
|
||||
(old_config.game.enhancements.fps_unlocker.path, &self.fps_unlocker)
|
||||
(old_config.components.path, &self.components)
|
||||
];
|
||||
|
||||
#[allow(clippy::expect_fun_call)]
|
||||
|
@ -405,7 +384,7 @@ impl SimpleAsyncComponent for DefaultPathsApp {
|
|||
}
|
||||
|
||||
else {
|
||||
sender.output(Self::Output::ScrollToSelectVoiceovers);
|
||||
sender.output(Self::Output::ScrollToDownloadComponents);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -442,7 +421,6 @@ impl DefaultPathsApp {
|
|||
config.game.path.global.clone_from(&self.game_global);
|
||||
config.game.path.china.clone_from(&self.game_china);
|
||||
config.components.path.clone_from(&self.components);
|
||||
config.game.enhancements.fps_unlocker.path.clone_from(&self.fps_unlocker);
|
||||
|
||||
config.launcher.temp = Some(self.temp.clone());
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use anime_launcher_sdk::components::*;
|
|||
use anime_launcher_sdk::components::wine::UnifiedWine;
|
||||
|
||||
use anime_launcher_sdk::config::ConfigExt;
|
||||
use anime_launcher_sdk::genshin::config::Config;
|
||||
use anime_launcher_sdk::zzz::config::Config;
|
||||
|
||||
use super::main::FirstRunAppMsg;
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ use crate::*;
|
|||
use super::welcome::*;
|
||||
use super::dependencies::*;
|
||||
use super::default_paths::*;
|
||||
use super::select_voiceovers::*;
|
||||
use super::download_components::*;
|
||||
use super::finish::*;
|
||||
|
||||
|
@ -22,7 +21,6 @@ pub struct FirstRunApp {
|
|||
welcome: AsyncController<WelcomeApp>,
|
||||
dependencies: AsyncController<DependenciesApp>,
|
||||
default_paths: AsyncController<DefaultPathsApp>,
|
||||
select_voiceovers: AsyncController<SelectVoiceoversApp>,
|
||||
download_components: AsyncController<DownloadComponentsApp>,
|
||||
finish: AsyncController<FinishApp>,
|
||||
|
||||
|
@ -39,7 +37,6 @@ pub enum FirstRunAppMsg {
|
|||
|
||||
ScrollToDependencies,
|
||||
ScrollToDefaultPaths,
|
||||
ScrollToSelectVoiceovers,
|
||||
ScrollToDownloadComponents,
|
||||
ScrollToFinish,
|
||||
|
||||
|
@ -98,7 +95,6 @@ impl SimpleComponent for FirstRunApp {
|
|||
append = model.welcome.widget(),
|
||||
append = model.dependencies.widget(),
|
||||
append = model.default_paths.widget(),
|
||||
append = model.select_voiceovers.widget(),
|
||||
append = model.download_components.widget(),
|
||||
append = model.finish.widget(),
|
||||
},
|
||||
|
@ -134,10 +130,6 @@ impl SimpleComponent for FirstRunApp {
|
|||
.launch(false)
|
||||
.forward(sender.input_sender(), std::convert::identity),
|
||||
|
||||
select_voiceovers: SelectVoiceoversApp::builder()
|
||||
.launch(())
|
||||
.forward(sender.input_sender(), std::convert::identity),
|
||||
|
||||
download_components: DownloadComponentsApp::builder()
|
||||
.launch(())
|
||||
.forward(sender.input_sender(), std::convert::identity),
|
||||
|
@ -189,12 +181,6 @@ impl SimpleComponent for FirstRunApp {
|
|||
self.carousel.scroll_to(self.default_paths.widget(), true);
|
||||
}
|
||||
|
||||
FirstRunAppMsg::ScrollToSelectVoiceovers => {
|
||||
self.title = tr!("select-voice-packages");
|
||||
|
||||
self.carousel.scroll_to(self.select_voiceovers.widget(), true);
|
||||
}
|
||||
|
||||
FirstRunAppMsg::ScrollToDownloadComponents => {
|
||||
// Update components index
|
||||
sender.input(FirstRunAppMsg::SetLoadingStatus(Some(Some(tr!("updating-components-index")))));
|
||||
|
|
|
@ -2,6 +2,5 @@ pub mod main;
|
|||
pub mod welcome;
|
||||
pub mod dependencies;
|
||||
pub mod default_paths;
|
||||
pub mod select_voiceovers;
|
||||
pub mod download_components;
|
||||
pub mod finish;
|
||||
|
|
|
@ -1,174 +0,0 @@
|
|||
use relm4::prelude::*;
|
||||
use adw::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::config::ConfigExt;
|
||||
use anime_launcher_sdk::genshin::config::Config;
|
||||
|
||||
use crate::*;
|
||||
|
||||
use super::main::*;
|
||||
|
||||
pub struct SelectVoiceoversApp {
|
||||
english: gtk::Switch,
|
||||
japanese: gtk::Switch,
|
||||
korean: gtk::Switch,
|
||||
chinese: gtk::Switch
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum SelectVoiceoversAppMsg {
|
||||
Continue,
|
||||
Exit
|
||||
}
|
||||
|
||||
#[relm4::component(async, pub)]
|
||||
impl SimpleAsyncComponent for SelectVoiceoversApp {
|
||||
type Init = ();
|
||||
type Input = SelectVoiceoversAppMsg;
|
||||
type Output = FirstRunAppMsg;
|
||||
|
||||
view! {
|
||||
adw::PreferencesPage {
|
||||
set_hexpand: true,
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_valign: gtk::Align::Center,
|
||||
set_vexpand: true,
|
||||
|
||||
gtk::Label {
|
||||
set_label: &tr!("select-voice-packages"),
|
||||
add_css_class: "title-1"
|
||||
}
|
||||
},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_valign: gtk::Align::Center,
|
||||
set_vexpand: true,
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr!("english"),
|
||||
|
||||
#[local_ref]
|
||||
add_suffix = english -> gtk::Switch {
|
||||
set_valign: gtk::Align::Center,
|
||||
set_active: true
|
||||
}
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr!("japanese"),
|
||||
|
||||
#[local_ref]
|
||||
add_suffix = japanese -> gtk::Switch {
|
||||
set_valign: gtk::Align::Center
|
||||
}
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr!("korean"),
|
||||
|
||||
#[local_ref]
|
||||
add_suffix = korean -> gtk::Switch {
|
||||
set_valign: gtk::Align::Center
|
||||
}
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr!("chinese"),
|
||||
|
||||
#[local_ref]
|
||||
add_suffix = chinese -> gtk::Switch {
|
||||
set_valign: gtk::Align::Center
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_valign: gtk::Align::Center,
|
||||
set_vexpand: true,
|
||||
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_halign: gtk::Align::Center,
|
||||
set_spacing: 8,
|
||||
|
||||
gtk::Button {
|
||||
set_label: &tr!("continue"),
|
||||
set_css_classes: &["suggested-action", "pill"],
|
||||
|
||||
connect_clicked => SelectVoiceoversAppMsg::Continue
|
||||
},
|
||||
|
||||
gtk::Button {
|
||||
set_label: &tr!("exit"),
|
||||
add_css_class: "pill",
|
||||
|
||||
connect_clicked => SelectVoiceoversAppMsg::Exit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn init(_init: Self::Init, root: Self::Root, _sender: AsyncComponentSender<Self>) -> AsyncComponentParts<Self> {
|
||||
let model = Self {
|
||||
english: gtk::Switch::new(),
|
||||
japanese: gtk::Switch::new(),
|
||||
korean: gtk::Switch::new(),
|
||||
chinese: gtk::Switch::new()
|
||||
};
|
||||
|
||||
let english = &model.english;
|
||||
let japanese = &model.japanese;
|
||||
let korean = &model.korean;
|
||||
let chinese = &model.chinese;
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
AsyncComponentParts { model, widgets }
|
||||
}
|
||||
|
||||
async fn update(&mut self, msg: Self::Input, sender: AsyncComponentSender<Self>) {
|
||||
match msg {
|
||||
#[allow(unused_must_use)]
|
||||
SelectVoiceoversAppMsg::Continue => {
|
||||
match self.update_config() {
|
||||
Ok(_) => sender.output(Self::Output::ScrollToDownloadComponents),
|
||||
|
||||
Err(err) => sender.output(Self::Output::Toast {
|
||||
title: tr!("config-update-error"),
|
||||
description: Some(err.to_string())
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
SelectVoiceoversAppMsg::Exit => relm4::main_application().quit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectVoiceoversApp {
|
||||
pub fn update_config(&self) -> anyhow::Result<()> {
|
||||
let mut config = Config::get()?;
|
||||
|
||||
config.game.voices = Vec::new();
|
||||
|
||||
if self.english.state() {
|
||||
config.game.voices.push(String::from("en-us"));
|
||||
}
|
||||
|
||||
if self.japanese.state() {
|
||||
config.game.voices.push(String::from("ja-jp"));
|
||||
}
|
||||
|
||||
if self.korean.state() {
|
||||
config.game.voices.push(String::from("ko-kr"));
|
||||
}
|
||||
|
||||
if self.chinese.state() {
|
||||
config.game.voices.push(String::from("zh-cn"));
|
||||
}
|
||||
|
||||
Config::update_raw(config)
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ use relm4::prelude::*;
|
|||
use anime_launcher_sdk::wincompatlib::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::config::ConfigExt;
|
||||
use anime_launcher_sdk::genshin::config::Config;
|
||||
use anime_launcher_sdk::zzz::config::Config;
|
||||
|
||||
use crate::*;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use relm4::prelude::*;
|
||||
use gtk::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::genshin::config::schema::prelude::LauncherBehavior;
|
||||
use anime_launcher_sdk::zzz::config::schema::prelude::LauncherBehavior;
|
||||
|
||||
use crate::*;
|
||||
|
||||
|
@ -22,7 +22,7 @@ pub fn launch(sender: ComponentSender<App>) {
|
|||
}
|
||||
|
||||
std::thread::spawn(move || {
|
||||
if let Err(err) = anime_launcher_sdk::genshin::game::run() {
|
||||
if let Err(err) = anime_launcher_sdk::zzz::game::run() {
|
||||
tracing::error!("Failed to launch game: {err}");
|
||||
|
||||
sender.input(AppMsg::Toast {
|
||||
|
|
|
@ -20,12 +20,12 @@ mod launch;
|
|||
use anime_launcher_sdk::components::loader::ComponentsLoader;
|
||||
|
||||
use anime_launcher_sdk::config::ConfigExt;
|
||||
use anime_launcher_sdk::genshin::config::Config;
|
||||
use anime_launcher_sdk::zzz::config::Config;
|
||||
|
||||
use anime_launcher_sdk::genshin::config::schema::launcher::LauncherStyle;
|
||||
use anime_launcher_sdk::zzz::config::schema::launcher::LauncherStyle;
|
||||
|
||||
use anime_launcher_sdk::genshin::states::*;
|
||||
use anime_launcher_sdk::genshin::consts::*;
|
||||
use anime_launcher_sdk::zzz::states::*;
|
||||
use anime_launcher_sdk::zzz::consts::*;
|
||||
|
||||
use crate::*;
|
||||
use crate::ui::components::*;
|
||||
|
@ -39,7 +39,6 @@ relm4::new_stateless_action!(LauncherFolder, WindowActionGroup, "launcher_folder
|
|||
relm4::new_stateless_action!(GameFolder, WindowActionGroup, "game_folder");
|
||||
relm4::new_stateless_action!(ConfigFile, WindowActionGroup, "config_file");
|
||||
relm4::new_stateless_action!(DebugFile, WindowActionGroup, "debug_file");
|
||||
relm4::new_stateless_action!(WishUrl, WindowActionGroup, "wish_url");
|
||||
|
||||
relm4::new_stateless_action!(About, WindowActionGroup, "about");
|
||||
|
||||
|
@ -118,10 +117,6 @@ impl SimpleComponent for App {
|
|||
&tr!("debug-file") => DebugFile,
|
||||
},
|
||||
|
||||
section! {
|
||||
&tr!("wish-url") => WishUrl
|
||||
},
|
||||
|
||||
section! {
|
||||
&tr!("about") => About
|
||||
}
|
||||
|
@ -306,12 +301,8 @@ impl SimpleComponent for App {
|
|||
},
|
||||
|
||||
"size" = match model.state.as_ref() {
|
||||
Some(LauncherState::PredownloadAvailable { game, voices }) => {
|
||||
let mut size = game.downloaded_size().unwrap_or(0);
|
||||
|
||||
for voice in voices {
|
||||
size += voice.downloaded_size().unwrap_or(0);
|
||||
}
|
||||
Some(LauncherState::PredownloadAvailable { game }) => {
|
||||
let size = game.downloaded_size().unwrap_or(0);
|
||||
|
||||
prettify_bytes(size)
|
||||
}
|
||||
|
@ -325,26 +316,14 @@ impl SimpleComponent for App {
|
|||
|
||||
#[watch]
|
||||
set_sensitive: match model.state.as_ref() {
|
||||
Some(LauncherState::PredownloadAvailable { game, voices }) => {
|
||||
Some(LauncherState::PredownloadAvailable { game }) => {
|
||||
let config = Config::get().unwrap();
|
||||
let temp = config.launcher.temp.unwrap_or_else(std::env::temp_dir);
|
||||
|
||||
let mut downloaded = temp.join(game.file_name().unwrap()).metadata()
|
||||
let downloaded = temp.join(game.file_name().unwrap()).metadata()
|
||||
.map(|metadata| Some(metadata.len()) == game.downloaded_size())
|
||||
.unwrap_or(false);
|
||||
|
||||
if downloaded {
|
||||
for voice in voices {
|
||||
downloaded = !temp.join(voice.file_name().unwrap()).metadata()
|
||||
.map(|metadata| Some(metadata.len()) == voice.downloaded_size())
|
||||
.unwrap_or(false);
|
||||
|
||||
if downloaded {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
!downloaded
|
||||
}
|
||||
|
||||
|
@ -353,26 +332,14 @@ impl SimpleComponent for App {
|
|||
|
||||
#[watch]
|
||||
set_css_classes: match model.state.as_ref() {
|
||||
Some(LauncherState::PredownloadAvailable { game, voices }) => {
|
||||
Some(LauncherState::PredownloadAvailable { game }) => {
|
||||
let config = Config::get().unwrap();
|
||||
let temp = config.launcher.temp.unwrap_or_else(std::env::temp_dir);
|
||||
|
||||
let mut downloaded = temp.join(game.file_name().unwrap()).metadata()
|
||||
let downloaded = temp.join(game.file_name().unwrap()).metadata()
|
||||
.map(|metadata| Some(metadata.len()) == game.downloaded_size())
|
||||
.unwrap_or(false);
|
||||
|
||||
if downloaded {
|
||||
for voice in voices {
|
||||
downloaded = !temp.join(voice.file_name().unwrap()).metadata()
|
||||
.map(|metadata| Some(metadata.len()) == voice.downloaded_size())
|
||||
.unwrap_or(false);
|
||||
|
||||
if downloaded {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if downloaded {
|
||||
&["success", "circular"]
|
||||
} else {
|
||||
|
@ -525,7 +492,7 @@ impl SimpleComponent for App {
|
|||
let result = std::process::Command::new("pkill")
|
||||
.arg("-f") // full text search
|
||||
.arg("-i") // case-insensitive
|
||||
.arg("GenshinImpact|YuanShen|fpsunlock\\.exe")
|
||||
.arg("ZenlessZoneZero")
|
||||
.spawn();
|
||||
|
||||
if let Err(err) = result {
|
||||
|
@ -727,84 +694,6 @@ impl SimpleComponent for App {
|
|||
}
|
||||
})));
|
||||
|
||||
group.add_action::<WishUrl>(RelmAction::new_stateless(clone!(@strong sender => move |_| {
|
||||
std::thread::spawn(clone!(@strong sender => move || {
|
||||
let config = Config::get().unwrap_or_else(|_| CONFIG.clone());
|
||||
|
||||
let web_cache = config.game.path.for_edition(config.launcher.edition)
|
||||
.join(config.launcher.edition.data_folder())
|
||||
.join("webCaches");
|
||||
|
||||
// Find newest cache folder
|
||||
let mut web_cache_id = None;
|
||||
|
||||
if let Ok(entries) = web_cache.read_dir() {
|
||||
for entry in entries.flatten() {
|
||||
if entry.path().is_dir() &&
|
||||
entry.file_name().to_string_lossy().trim_matches(|c| "0123456789.".contains(c)).is_empty() &&
|
||||
Some(entry.file_name()) > web_cache_id
|
||||
{
|
||||
web_cache_id = Some(entry.file_name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(web_cache_id) = web_cache_id {
|
||||
let web_cache = web_cache
|
||||
.join(web_cache_id)
|
||||
.join("Cache/Cache_Data/data_2");
|
||||
|
||||
match std::fs::read(web_cache) {
|
||||
Ok(web_cache) => {
|
||||
let web_cache = String::from_utf8_lossy(&web_cache);
|
||||
|
||||
// https://webstatic-sea.[ho-yo-ver-se].com/[ge-nsh-in]/event/e20190909gacha-v2/index.html?......
|
||||
if let Some(url) = web_cache.lines().rev().find(|line| line.contains("gacha-v3/index.html")) {
|
||||
let url_begin_pos = url.find("https://").unwrap();
|
||||
let url_end_pos = url_begin_pos + url[url_begin_pos..].find("\0\0\0\0").unwrap();
|
||||
|
||||
if let Err(err) = open::that(format!("{}#/log", &url[url_begin_pos..url_end_pos])) {
|
||||
tracing::error!("Failed to open wishes URL: {err}");
|
||||
|
||||
sender.input(AppMsg::Toast {
|
||||
title: tr!("wish-url-opening-error"),
|
||||
description: Some(err.to_string())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
tracing::error!("Couldn't find wishes URL: no url found");
|
||||
|
||||
sender.input(AppMsg::Toast {
|
||||
title: tr!("wish-url-search-failed"),
|
||||
description: None
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Err(err) => {
|
||||
tracing::error!("Couldn't find wishes URL: failed to open cache file: {err}");
|
||||
|
||||
sender.input(AppMsg::Toast {
|
||||
title: tr!("wish-url-search-failed"),
|
||||
description: Some(err.to_string())
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
tracing::error!("Couldn't find wishes URL: cache file doesn't exist");
|
||||
|
||||
sender.input(AppMsg::Toast {
|
||||
title: tr!("wish-url-search-failed"),
|
||||
description: None
|
||||
});
|
||||
}
|
||||
}));
|
||||
})));
|
||||
|
||||
group.add_action::<About>(RelmAction::new_stateless(move |_| {
|
||||
about_dialog_broker.send(AboutDialogMsg::Show);
|
||||
}));
|
||||
|
@ -944,12 +833,6 @@ impl SimpleComponent for App {
|
|||
StateUpdating::Game => {
|
||||
sender.input(AppMsg::SetLoadingStatus(Some(Some(tr!("loading-launcher-state--game")))));
|
||||
}
|
||||
|
||||
StateUpdating::Voice(locale) => {
|
||||
sender.input(AppMsg::SetLoadingStatus(Some(Some(tr!("loading-launcher-state--voice", {
|
||||
"locale" = locale.to_name()
|
||||
})))));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1028,7 +911,7 @@ impl SimpleComponent for App {
|
|||
|
||||
#[allow(unused_must_use)]
|
||||
AppMsg::PredownloadUpdate => {
|
||||
if let Some(LauncherState::PredownloadAvailable { game, mut voices }) = self.state.clone() {
|
||||
if let Some(LauncherState::PredownloadAvailable { mut game }) = self.state.clone() {
|
||||
let tmp = Config::get().unwrap().launcher.temp.unwrap_or_else(std::env::temp_dir);
|
||||
|
||||
self.downloading = true;
|
||||
|
@ -1037,26 +920,18 @@ impl SimpleComponent for App {
|
|||
|
||||
progress_bar_input.send(ProgressBarMsg::UpdateCaption(Some(tr!("downloading"))));
|
||||
|
||||
let mut diffs: Vec<VersionDiff> = vec![game];
|
||||
|
||||
diffs.append(&mut voices);
|
||||
|
||||
std::thread::spawn(move || {
|
||||
for mut diff in diffs {
|
||||
let result = diff.download_to(&tmp, clone!(@strong progress_bar_input => move |curr, total| {
|
||||
progress_bar_input.send(ProgressBarMsg::UpdateProgress(curr, total));
|
||||
}));
|
||||
let result = game.download_to(&tmp, clone!(@strong progress_bar_input => move |curr, total| {
|
||||
progress_bar_input.send(ProgressBarMsg::UpdateProgress(curr, total));
|
||||
}));
|
||||
|
||||
if let Err(err) = result {
|
||||
sender.input(AppMsg::Toast {
|
||||
title: tr!("downloading-failed"),
|
||||
description: Some(err.to_string())
|
||||
});
|
||||
if let Err(err) = result {
|
||||
sender.input(AppMsg::Toast {
|
||||
title: tr!("downloading-failed"),
|
||||
description: Some(err.to_string())
|
||||
});
|
||||
|
||||
tracing::error!("Failed to predownload update: {err}");
|
||||
|
||||
break;
|
||||
}
|
||||
tracing::error!("Failed to predownload update: {err}");
|
||||
}
|
||||
|
||||
sender.input(AppMsg::SetDownloading(false));
|
||||
|
|
|
@ -19,18 +19,8 @@ pub fn repair_game(sender: ComponentSender<App>, progress_bar_input: Sender<Prog
|
|||
|
||||
std::thread::spawn(move || {
|
||||
match repairer::try_get_integrity_files(config.launcher.edition, None) {
|
||||
Ok(mut files) => {
|
||||
// Add voiceovers files
|
||||
Ok(files) => {
|
||||
let game_path = config.game.path.for_edition(config.launcher.edition).to_path_buf();
|
||||
let game = Game::new(&game_path, config.launcher.edition);
|
||||
|
||||
if let Ok(voiceovers) = game.get_voice_packages() {
|
||||
for package in voiceovers {
|
||||
if let Ok(mut voiceover_files) = repairer::try_get_voice_integrity_files(config.launcher.edition, package.locale(), None) {
|
||||
files.append(&mut voiceover_files);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
progress_bar_input.send(ProgressBarMsg::UpdateProgress(0, 0));
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use relm4::factory::*;
|
|||
use adw::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::sessions::SessionsExt;
|
||||
use anime_launcher_sdk::genshin::sessions::Sessions;
|
||||
use anime_launcher_sdk::zzz::sessions::Sessions;
|
||||
|
||||
use crate::*;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use relm4::factory::{
|
|||
use adw::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::config::ConfigExt;
|
||||
use anime_launcher_sdk::genshin::config::Config;
|
||||
use anime_launcher_sdk::zzz::config::Config;
|
||||
use anime_launcher_sdk::config::schema_blanks::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::anime_game_core::installer::downloader::Downloader;
|
||||
|
@ -544,87 +544,6 @@ impl SimpleAsyncComponent for EnhancementsApp {
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
add = &adw::PreferencesGroup {
|
||||
set_title: &tr!("fps-unlocker"),
|
||||
|
||||
adw::ComboRow {
|
||||
set_title: &tr!("enabled"),
|
||||
set_subtitle: &tr!("fps-unlocker-description"),
|
||||
|
||||
#[wrap(Some)]
|
||||
set_model = >k::StringList::new(&[
|
||||
"90",
|
||||
"120",
|
||||
"144",
|
||||
"165",
|
||||
"180",
|
||||
"200",
|
||||
"240",
|
||||
&tr!("custom")
|
||||
]),
|
||||
|
||||
set_selected: match Fps::from_num(CONFIG.game.enhancements.fps_unlocker.config.fps) {
|
||||
Fps::Ninety => 0,
|
||||
Fps::HundredTwenty => 1,
|
||||
Fps::HundredFourtyFour => 2,
|
||||
Fps::HundredSixtyFive => 3,
|
||||
Fps::HundredEighty => 4,
|
||||
Fps::TwoHundred => 5,
|
||||
Fps::TwoHundredFourty => 6,
|
||||
|
||||
Fps::Custom(_) => 7
|
||||
},
|
||||
|
||||
connect_selected_notify => |row| {
|
||||
if is_ready() && row.selected() < Fps::list().len() as u32 - 1 {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
config.game.enhancements.fps_unlocker.config.fps = Fps::list()[row.selected() as usize].to_num();
|
||||
|
||||
Config::update(config);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
add_suffix = >k::Switch {
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
set_active: CONFIG.game.enhancements.fps_unlocker.enabled,
|
||||
|
||||
connect_state_notify => |switch| {
|
||||
if is_ready() {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
config.game.enhancements.fps_unlocker.enabled = switch.is_active();
|
||||
|
||||
Config::update(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
adw::ActionRow {
|
||||
set_title: &tr!("fps-unlocker-interval"),
|
||||
set_subtitle: &tr!("fps-unlocker-interval-description"),
|
||||
|
||||
add_suffix = >k::SpinButton {
|
||||
set_valign: gtk::Align::Center,
|
||||
set_adjustment: >k::Adjustment::new(1.0, 1000.0, 60000.0, 1000.0, 1.0, 0.0),
|
||||
|
||||
set_value: CONFIG.game.enhancements.fps_unlocker.config.interval as f64,
|
||||
|
||||
connect_changed => |row| {
|
||||
if is_ready() {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
config.game.enhancements.fps_unlocker.config.interval = row.value() as u64;
|
||||
|
||||
Config::update(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use relm4::prelude::*;
|
|||
use adw::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::config::ConfigExt;
|
||||
use anime_launcher_sdk::genshin::config::Config;
|
||||
use anime_launcher_sdk::zzz::config::Config;
|
||||
|
||||
use anime_launcher_sdk::config::schema_blanks::prelude::*;
|
||||
|
||||
|
|
|
@ -1,22 +1,16 @@
|
|||
use relm4::prelude::*;
|
||||
|
||||
use relm4::factory::{
|
||||
AsyncFactoryVecDeque,
|
||||
AsyncFactoryComponent,
|
||||
AsyncFactorySender
|
||||
};
|
||||
|
||||
use gtk::prelude::*;
|
||||
use adw::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::wincompatlib::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::config::ConfigExt;
|
||||
use anime_launcher_sdk::genshin::config::Config;
|
||||
use anime_launcher_sdk::genshin::config::schema::prelude::*;
|
||||
use anime_launcher_sdk::zzz::config::Config;
|
||||
use anime_launcher_sdk::zzz::config::schema::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::anime_game_core::genshin::consts::GameEdition;
|
||||
use anime_launcher_sdk::genshin::env_emulation::Environment;
|
||||
use anime_launcher_sdk::anime_game_core::zzz::consts::GameEdition;
|
||||
use anime_launcher_sdk::zzz::env_emulation::Environment;
|
||||
|
||||
pub mod components;
|
||||
|
||||
|
@ -28,81 +22,7 @@ use crate::*;
|
|||
|
||||
use super::main::PreferencesAppMsg;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct VoicePackageComponent {
|
||||
locale: VoiceLocale,
|
||||
installed: bool,
|
||||
sensitive: bool
|
||||
}
|
||||
|
||||
#[relm4::factory(async)]
|
||||
impl AsyncFactoryComponent for VoicePackageComponent {
|
||||
type Init = (VoiceLocale, bool);
|
||||
type Input = GeneralAppMsg;
|
||||
type Output = GeneralAppMsg;
|
||||
type CommandOutput = ();
|
||||
type ParentWidget = adw::ExpanderRow;
|
||||
|
||||
view! {
|
||||
root = adw::ActionRow {
|
||||
set_title: &tr!(&self.locale.to_name().to_ascii_lowercase()),
|
||||
|
||||
add_suffix = >k::Button {
|
||||
#[watch]
|
||||
set_visible: self.installed,
|
||||
|
||||
#[watch]
|
||||
set_sensitive: self.sensitive,
|
||||
|
||||
set_icon_name: "user-trash-symbolic",
|
||||
add_css_class: "flat",
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
connect_clicked[sender, index] => move |_| {
|
||||
sender.input(GeneralAppMsg::RemoveVoicePackage(index.clone()));
|
||||
}
|
||||
},
|
||||
|
||||
add_suffix = >k::Button {
|
||||
#[watch]
|
||||
set_visible: !self.installed,
|
||||
|
||||
#[watch]
|
||||
set_sensitive: self.sensitive,
|
||||
|
||||
set_icon_name: "document-save-symbolic",
|
||||
add_css_class: "flat",
|
||||
set_valign: gtk::Align::Center,
|
||||
|
||||
connect_clicked[sender, index] => move |_| {
|
||||
sender.input(GeneralAppMsg::AddVoicePackage(index.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn init_model(
|
||||
init: Self::Init,
|
||||
_index: &DynamicIndex,
|
||||
_sender: AsyncFactorySender<Self>,
|
||||
) -> Self {
|
||||
Self {
|
||||
locale: init.0,
|
||||
installed: init.1,
|
||||
sensitive: true
|
||||
}
|
||||
}
|
||||
|
||||
async fn update(&mut self, msg: Self::Input, sender: AsyncFactorySender<Self>) {
|
||||
self.installed = !self.installed;
|
||||
|
||||
sender.output(msg)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GeneralApp {
|
||||
voice_packages: AsyncFactoryVecDeque<VoicePackageComponent>,
|
||||
migrate_installation: Controller<MigrateInstallationApp>,
|
||||
components_page: AsyncController<ComponentsPage>,
|
||||
|
||||
|
@ -117,13 +37,6 @@ pub enum GeneralAppMsg {
|
|||
/// was retrieved from the API
|
||||
SetGameDiff(Option<VersionDiff>),
|
||||
|
||||
// If one ever wish to change it to accept VoiceLocale
|
||||
// I'd recommend to use clone!(@strong self.locale as locale => move |_| { .. })
|
||||
// in the VoicePackage component
|
||||
AddVoicePackage(DynamicIndex),
|
||||
RemoveVoicePackage(DynamicIndex),
|
||||
SetVoicePackageSensitivity(DynamicIndex, bool),
|
||||
|
||||
UpdateDownloadedWine,
|
||||
UpdateDownloadedDxvk,
|
||||
|
||||
|
@ -330,12 +243,6 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
}
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
voice_packages -> adw::ExpanderRow {
|
||||
set_title: &tr!("game-voiceovers"),
|
||||
set_subtitle: &tr!("game-voiceovers-description")
|
||||
},
|
||||
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_spacing: 8,
|
||||
|
@ -538,11 +445,7 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
) -> AsyncComponentParts<Self> {
|
||||
tracing::info!("Initializing general settings");
|
||||
|
||||
let mut model = Self {
|
||||
voice_packages: AsyncFactoryVecDeque::builder()
|
||||
.launch_default()
|
||||
.forward(sender.input_sender(), std::convert::identity),
|
||||
|
||||
let model = Self {
|
||||
migrate_installation: MigrateInstallationApp::builder()
|
||||
.launch(())
|
||||
.detach(),
|
||||
|
@ -556,14 +459,6 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
languages: SUPPORTED_LANGUAGES.iter().map(|lang| tr!(format_lang(lang).as_str())).collect()
|
||||
};
|
||||
|
||||
for package in VoiceLocale::list() {
|
||||
model.voice_packages.guard().push_back((
|
||||
*package,
|
||||
CONFIG.game.voices.iter().any(|voice| VoiceLocale::from_str(voice) == Some(*package))
|
||||
));
|
||||
}
|
||||
|
||||
let voice_packages = model.voice_packages.widget();
|
||||
let components_page = model.components_page.widget();
|
||||
|
||||
let widgets = view_output!();
|
||||
|
@ -579,63 +474,6 @@ impl SimpleAsyncComponent for GeneralApp {
|
|||
self.game_diff = diff;
|
||||
}
|
||||
|
||||
#[allow(unused_must_use)]
|
||||
GeneralAppMsg::AddVoicePackage(index) => {
|
||||
if let Some(package) = self.voice_packages.get(index.current_index()) {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
if !config.game.voices.iter().any(|voice| VoiceLocale::from_str(voice) == Some(package.locale)) {
|
||||
config.game.voices.push(package.locale.to_code().to_string());
|
||||
|
||||
Config::update(config);
|
||||
|
||||
sender.output(PreferencesAppMsg::UpdateLauncherState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_must_use)]
|
||||
GeneralAppMsg::RemoveVoicePackage(index) => {
|
||||
if let Some(package) = self.voice_packages.guard().get_mut(index.current_index()) {
|
||||
if let Ok(mut config) = Config::get() {
|
||||
package.sensitive = false;
|
||||
|
||||
config.game.voices.retain(|voice| VoiceLocale::from_str(voice) != Some(package.locale));
|
||||
|
||||
Config::update(config.clone());
|
||||
|
||||
let package = VoicePackage::with_locale(package.locale, config.launcher.edition).unwrap();
|
||||
let game_path = config.game.path.for_edition(config.launcher.edition).to_path_buf();
|
||||
|
||||
if package.is_installed_in(&game_path) {
|
||||
std::thread::spawn(move || {
|
||||
if let Err(err) = package.delete_in(game_path) {
|
||||
tracing::error!("Failed to delete voice package: {:?}", package.locale());
|
||||
|
||||
sender.input(GeneralAppMsg::Toast {
|
||||
title: tr!("voice-package-deletion-error"),
|
||||
description: Some(err.to_string())
|
||||
});
|
||||
}
|
||||
|
||||
sender.input(GeneralAppMsg::SetVoicePackageSensitivity(index, true));
|
||||
sender.output(PreferencesAppMsg::UpdateLauncherState);
|
||||
});
|
||||
}
|
||||
|
||||
else {
|
||||
sender.input(GeneralAppMsg::SetVoicePackageSensitivity(index, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GeneralAppMsg::SetVoicePackageSensitivity(index, sensitive) => {
|
||||
if let Some(package) = self.voice_packages.guard().get_mut(index.current_index()) {
|
||||
package.sensitive = sensitive;
|
||||
}
|
||||
}
|
||||
|
||||
GeneralAppMsg::UpdateDownloadedWine => {
|
||||
self.components_page.sender()
|
||||
.send(ComponentsPageMsg::UpdateDownloadedWine)
|
||||
|
|
|
@ -3,11 +3,11 @@ use relm4::prelude::*;
|
|||
use gtk::prelude::*;
|
||||
use adw::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::anime_game_core::genshin::prelude::*;
|
||||
use anime_launcher_sdk::anime_game_core::zzz::prelude::*;
|
||||
|
||||
use anime_launcher_sdk::config::ConfigExt;
|
||||
use anime_launcher_sdk::genshin::config::Config;
|
||||
use anime_launcher_sdk::genshin::config::schema::launcher::LauncherStyle;
|
||||
use anime_launcher_sdk::zzz::config::Config;
|
||||
use anime_launcher_sdk::zzz::config::schema::launcher::LauncherStyle;
|
||||
|
||||
use crate::tr;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue