Added game and patch status updating in settings

This commit is contained in:
Observer KRypt0n_ 2022-07-01 20:12:25 +02:00
parent 86de977e05
commit 59405f440c
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
8 changed files with 180 additions and 22 deletions

View file

@ -58,7 +58,7 @@ Adw.ApplicationWindow window {
styles ["suggested-action"] styles ["suggested-action"]
popover: Gtk.Popover { popover: Gtk.Popover {
Gtk.Button { Gtk.Button launch_game_debug {
label: "Launch in debug mode"; label: "Launch in debug mode";
} }
}; };

View file

@ -26,7 +26,7 @@ Adw.PreferencesPage general_page {
Adw.ActionRow { Adw.ActionRow {
title: "Game version"; title: "Game version";
Gtk.Label { Gtk.Label game_version {
label: "2.7.0"; label: "2.7.0";
styles ["success"] styles ["success"]
@ -36,7 +36,7 @@ Adw.PreferencesPage general_page {
Adw.ActionRow { Adw.ActionRow {
title: "Patch version"; title: "Patch version";
Gtk.Label { Gtk.Label patch_version {
label: "2.7.0"; label: "2.7.0";
styles ["success"] styles ["success"]

View file

@ -27,6 +27,22 @@ impl Terminal {
Terminal::Xfce4Terminal Terminal::Xfce4Terminal
].into_iter() ].into_iter()
} }
pub fn get_args(&self, bash_command: &str) -> Vec<String> {
match self {
Terminal::GnomeTerminal => vec![
String::from("--"),
String::from("bash"),
String::from("-c"),
format!("{} && bash", bash_command)
],
Terminal::Konsole | Terminal::Xfce4Terminal => vec![
String::from("--hold"),
String::from("-e"),
format!("\"bash -c '{} && bash'\"", bash_command)
]
}
}
} }
/// Try to get GUI terminal installed in system /// Try to get GUI terminal installed in system
@ -43,7 +59,9 @@ pub fn try_get_terminal() -> Option<Terminal> {
} }
/// Try to run the game /// Try to run the game
pub fn run() -> Result<(), Error> { ///
/// If `debug = true`, then the game will be run in the new terminal window
pub fn run(debug: bool) -> Result<(), Error> {
let config = config::get()?; let config = config::get()?;
if !Path::new(&config.game.path).exists() { if !Path::new(&config.game.path).exists() {
@ -57,12 +75,31 @@ pub fn run() -> Result<(), Error> {
let mut command = Command::new(wine_executable); let mut command = Command::new(wine_executable);
if debug {
// Is not supported now because new spawned terminal needs
// to have cwd and env variables specified directly
// which is kinda difficult
todo!();
match try_get_terminal() {
Some(terminal) => {
command = Command::new(terminal.get_command());
command.args(terminal.get_args("launcher.bat"));
},
None => return Err(Error::new(ErrorKind::Other, "Couldn't find terminal application"))
}
}
else {
command.arg("launcher.bat");
}
command.env("WINEPREFIX", &config.game.wine.prefix); command.env("WINEPREFIX", &config.game.wine.prefix);
command.envs(config.get_wine_sync_env_vars()); command.envs(config.get_wine_sync_env_vars());
command.envs(config.game.environment) command.envs(config.game.environment)
.current_dir(config.game.path) .current_dir(config.game.path)
.arg("launcher.bat")
.spawn()?; .spawn()?;
Ok(()) Ok(())

View file

@ -20,8 +20,12 @@ fn main() {
application.connect_activate(|app| { application.connect_activate(|app| {
let app = MainApp::new(app).unwrap(); let app = MainApp::new(app).unwrap();
let app_copy = app.clone();
app.open_preferences.connect_clicked(move |_| { app.open_preferences.connect_clicked(move |_| {
app.leaflet.set_visible_child_name("preferences_page"); if let Err(err) = app_copy.open_preferences_page() {
app_copy.toast_error("Failed to open settings page", err);
}
}); });
app.window.show(); app.window.show();

View file

@ -1,6 +1,8 @@
use gtk4::{self as gtk, prelude::*}; use gtk4::{self as gtk, prelude::*};
use libadwaita::{self as adw, prelude::*}; use libadwaita::{self as adw, prelude::*};
use std::io::Error;
use super::{get_object, add_action}; use super::{get_object, add_action};
use super::preferences::PreferencesStack; use super::preferences::PreferencesStack;
@ -11,8 +13,11 @@ pub struct App {
pub window: adw::ApplicationWindow, pub window: adw::ApplicationWindow,
pub leaflet: adw::Leaflet, pub leaflet: adw::Leaflet,
pub launch_game: adw::SplitButton, pub launch_game: adw::SplitButton,
pub launch_game_debug: gtk::Button,
pub open_preferences: gtk::Button, pub open_preferences: gtk::Button,
pub toast_overlay: adw::ToastOverlay pub toast_overlay: adw::ToastOverlay,
pub preferences_stack: PreferencesStack
} }
impl App { impl App {
@ -25,18 +30,20 @@ impl App {
window: get_object(&builder, "window")?, window: get_object(&builder, "window")?,
leaflet: get_object(&builder, "leaflet")?, leaflet: get_object(&builder, "leaflet")?,
launch_game: get_object(&builder, "launch_game")?, launch_game: get_object(&builder, "launch_game")?,
launch_game_debug: get_object(&builder, "launch_game_debug")?,
open_preferences: get_object(&builder, "open_preferences")?, open_preferences: get_object(&builder, "open_preferences")?,
toast_overlay: get_object(&builder, "toast_overlay")? toast_overlay: get_object(&builder, "toast_overlay")?,
preferences_stack: PreferencesStack::new()?
}; };
// Add preferences page to the leaflet // Add preferences page to the leaflet
let stack = PreferencesStack::new()?;
let leaflet = result.leaflet.clone(); let leaflet = result.leaflet.clone();
result.leaflet.append(&stack.preferences).set_name(Some("preferences_page")); result.leaflet.append(&result.preferences_stack.preferences).set_name(Some("preferences_page"));
// Go back button for preferences page // Go back button for preferences page
stack.preferences_go_back.connect_clicked(move |_| { result.preferences_stack.preferences_go_back.connect_clicked(move |_| {
leaflet.navigate(adw::NavigationDirection::Back); leaflet.navigate(adw::NavigationDirection::Back);
}); });
@ -45,11 +52,21 @@ impl App {
result.launch_game.connect_clicked(move |_| { result.launch_game.connect_clicked(move |_| {
// Display toast message if the game is failed to run // Display toast message if the game is failed to run
if let Err(err) = game::run() { if let Err(err) = game::run(false) {
app_copy.toast_error("Failed to run game", err); app_copy.toast_error("Failed to run game", err);
} }
}); });
// Launch game in debug mode
/*let app_copy = result.clone();
result.launch_game_debug.connect_clicked(move |_| {
// Display toast message if the game is failed to run
if let Err(err) = game::run(true) {
app_copy.toast_error("Failed to run game", err);
}
});*/
// Bind app to the window // Bind app to the window
result.window.set_application(Some(app)); result.window.set_application(Some(app));
@ -86,4 +103,12 @@ impl App {
self.toast_overlay.add_toast(&toast); self.toast_overlay.add_toast(&toast);
} }
pub fn open_preferences_page(&self) -> Result<(), Error> {
self.preferences_stack.update()?;
self.leaflet.set_visible_child_name("preferences_page");
Ok(())
}
} }

View file

@ -3,13 +3,18 @@ use libadwaita::{self as adw, prelude::*};
use crate::ui::get_object; use crate::ui::get_object;
pub struct Page; #[derive(Clone)]
pub struct Page {
pub page: adw::PreferencesPage
}
impl Page { impl Page {
pub fn get() -> Result<adw::PreferencesPage, String> { pub fn new() -> Result<Self, String> {
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/preferences_enhanced.ui")); let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/preferences_enhanced.ui"));
Ok(get_object(&builder, "enhanced_page")?) Ok(Self {
page: get_object(&builder, "enhanced_page")?
})
} }
pub fn title() -> String { pub fn title() -> String {

View file

@ -3,13 +3,22 @@ use libadwaita::{self as adw, prelude::*};
use crate::ui::get_object; use crate::ui::get_object;
pub struct Page; #[derive(Clone)]
pub struct Page {
pub page: adw::PreferencesPage,
pub game_version: gtk::Label,
pub patch_version: gtk::Label
}
impl Page { impl Page {
pub fn get() -> Result<adw::PreferencesPage, String> { pub fn new() -> Result<Self, String> {
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/preferences_general.ui")); let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/preferences_general.ui"));
Ok(get_object(&builder, "general_page")?) Ok(Self {
page: get_object(&builder, "general_page")?,
game_version: get_object(&builder, "game_version")?,
patch_version: get_object(&builder, "patch_version")?
})
} }
pub fn title() -> String { pub fn title() -> String {

View file

@ -1,7 +1,12 @@
use gtk4::{self as gtk, prelude::*}; use gtk4::{self as gtk, prelude::*};
use libadwaita::{self as adw, prelude::*}; use libadwaita::{self as adw, prelude::*};
use std::io::Error;
use anime_game_core::prelude::*;
use crate::ui::get_object; use crate::ui::get_object;
use crate::lib::config;
mod general_page; mod general_page;
mod enhanced_page; mod enhanced_page;
@ -11,10 +16,13 @@ pub mod pages {
pub use super::enhanced_page::Page as EnhancedPage; pub use super::enhanced_page::Page as EnhancedPage;
} }
#[derive(Clone)]
pub struct PreferencesStack { pub struct PreferencesStack {
pub preferences: gtk::Box, pub preferences: gtk::Box,
pub preferences_go_back: gtk::Button, pub preferences_go_back: gtk::Button,
pub stack: gtk::Stack pub stack: gtk::Stack,
pub general_page: pages::GeneralPage,
pub enhanced_page: pages::EnhancedPage
} }
impl PreferencesStack { impl PreferencesStack {
@ -24,12 +32,82 @@ impl PreferencesStack {
let result = Self { let result = Self {
preferences: get_object(&builder, "preferences")?, preferences: get_object(&builder, "preferences")?,
preferences_go_back: get_object(&builder, "preferences_go_back")?, preferences_go_back: get_object(&builder, "preferences_go_back")?,
stack: get_object(&builder, "stack")? stack: get_object(&builder, "stack")?,
general_page: pages::GeneralPage::new()?,
enhanced_page: pages::EnhancedPage::new()?
}; };
result.stack.add_titled(&pages::GeneralPage::get()?, None, &pages::GeneralPage::title()); result.stack.add_titled(&result.general_page.page, None, &pages::GeneralPage::title());
result.stack.add_titled(&pages::EnhancedPage::get()?, None, &pages::EnhancedPage::title()); result.stack.add_titled(&result.enhanced_page.page, None, &pages::EnhancedPage::title());
Ok(result) Ok(result)
} }
/// Update page info before opening it
///
/// Being called from the `MainApp` struct
///
/// TODO: do it asynchronously
pub fn update(&self) -> Result<(), Error> {
let config = config::get()?;
let game = Game::new(config.game.path);
self.general_page.game_version.set_tooltip_text(None);
self.general_page.patch_version.set_tooltip_text(None);
match game.try_get_diff()? {
VersionDiff::Latest(version) => {
self.general_page.game_version.set_label(&version.to_string());
},
VersionDiff::Diff { current, latest, .. } => {
self.general_page.game_version.set_label(&current.to_string());
self.general_page.game_version.set_css_classes(&["warning"]);
self.general_page.game_version.set_tooltip_text(Some(&format!("Game update available: {} -> {}", current, latest)));
},
VersionDiff::Outdated { current, latest } => {
self.general_page.game_version.set_label(&current.to_string());
self.general_page.game_version.set_css_classes(&["error"]);
self.general_page.game_version.set_tooltip_text(Some(&format!("Game is too outdated and can't be updated. Latest version: {}", latest)));
},
VersionDiff::NotInstalled { .. } => {
self.general_page.game_version.set_label("not installed");
self.general_page.game_version.set_css_classes(&[]);
}
}
match Patch::try_fetch(config.patch.servers)? {
Patch::NotAvailable => {
self.general_page.patch_version.set_label("not available");
self.general_page.patch_version.set_css_classes(&["error"]);
self.general_page.patch_version.set_tooltip_text(Some("Patch is not available"));
},
Patch::Outdated { current, latest, .. } => {
self.general_page.patch_version.set_label("outdated");
self.general_page.patch_version.set_css_classes(&["warning"]);
self.general_page.patch_version.set_tooltip_text(Some(&format!("Patch is outdated ({} -> {})", current, latest)));
},
Patch::Preparation { .. } => {
self.general_page.patch_version.set_label("preparation");
self.general_page.patch_version.set_css_classes(&["warning"]);
self.general_page.patch_version.set_tooltip_text(Some("Patch is in preparation state and will be available later"));
},
Patch::Testing { version, .. } => {
self.general_page.patch_version.set_label(&version.to_string());
self.general_page.patch_version.set_css_classes(&["warning"]);
self.general_page.patch_version.set_tooltip_text(Some("Patch is in testing phase"));
},
Patch::Available { version, .. } => {
self.general_page.patch_version.set_label(&version.to_string());
self.general_page.patch_version.set_css_classes(&["success"]);
}
}
Ok(())
}
} }