Added game and patch status updating in settings
This commit is contained in:
parent
86de977e05
commit
59405f440c
8 changed files with 180 additions and 22 deletions
|
@ -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";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
|
@ -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(())
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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(¤t.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(¤t.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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue