mirror of
https://github.com/an-anime-team/an-anime-game-launcher.git
synced 2025-01-30 04:23:31 +03:00
Preparations for loading page
- added `Adw.StatusPage` to the preferences - made preparations for progress bar and launcher states system - fixed toasts resizing window issue
This commit is contained in:
parent
3be54b22d2
commit
178c45ae48
9 changed files with 173 additions and 49 deletions
|
@ -7,9 +7,7 @@ Adw.ApplicationWindow window {
|
|||
|
||||
styles ["devel"]
|
||||
|
||||
content: Gtk.Box {
|
||||
orientation: vertical;
|
||||
|
||||
content: Adw.ToastOverlay toast_overlay {
|
||||
Adw.Leaflet leaflet {
|
||||
can-navigate-back: true;
|
||||
can-unfold: false;
|
||||
|
@ -40,7 +38,7 @@ Adw.ApplicationWindow window {
|
|||
}
|
||||
}
|
||||
|
||||
Adw.PreferencesGroup {
|
||||
Adw.PreferencesGroup launch_game_group {
|
||||
vexpand: true;
|
||||
valign: center;
|
||||
|
||||
|
@ -69,9 +67,32 @@ Adw.ApplicationWindow window {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Adw.ToastOverlay toast_overlay {}
|
||||
Adw.PreferencesGroup progress_bar_group {
|
||||
vexpand: true;
|
||||
valign: center;
|
||||
visible: false;
|
||||
|
||||
Gtk.Box {
|
||||
halign: center;
|
||||
margin-top: 64;
|
||||
spacing: 20;
|
||||
|
||||
Gtk.ProgressBar progress_bar {
|
||||
text: "Downloading: 37% (3.7 of 10 GB)\n";
|
||||
show-text: true;
|
||||
|
||||
width-request: 260;
|
||||
fraction: 0.37;
|
||||
valign: center;
|
||||
}
|
||||
|
||||
Gtk.Button {
|
||||
label: "Pause";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -15,8 +15,16 @@ Gtk.Box preferences {
|
|||
}
|
||||
}
|
||||
|
||||
Adw.Flap {
|
||||
Adw.StatusPage status_page {
|
||||
icon-name: "image-loading-symbolic";
|
||||
title: "Loading data";
|
||||
|
||||
vexpand: true;
|
||||
}
|
||||
|
||||
Adw.Flap flap {
|
||||
vexpand: true;
|
||||
visible: false;
|
||||
|
||||
flap: Gtk.StackSidebar {
|
||||
width-request: 200;
|
||||
|
|
|
@ -4,7 +4,7 @@ use libadwaita::{self as adw, prelude::*};
|
|||
pub mod ui;
|
||||
pub mod lib;
|
||||
|
||||
use ui::MainApp;
|
||||
use ui::*;
|
||||
|
||||
fn main() {
|
||||
gtk::init().expect("GTK initialization failed");
|
||||
|
|
|
@ -3,11 +3,20 @@ use libadwaita::{self as adw, prelude::*};
|
|||
|
||||
use std::io::Error;
|
||||
|
||||
use super::{get_object, add_action};
|
||||
use super::get_object;
|
||||
use super::preferences::PreferencesStack;
|
||||
use super::ToastError;
|
||||
|
||||
use crate::lib::game;
|
||||
|
||||
pub enum AppState {
|
||||
Launch,
|
||||
Progress {
|
||||
title: String,
|
||||
progress: f64
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct App {
|
||||
pub window: adw::ApplicationWindow,
|
||||
|
@ -17,6 +26,10 @@ pub struct App {
|
|||
pub open_preferences: gtk::Button,
|
||||
pub toast_overlay: adw::ToastOverlay,
|
||||
|
||||
pub launch_game_group: adw::PreferencesGroup,
|
||||
pub progress_bar_group: adw::PreferencesGroup,
|
||||
pub progress_bar: gtk::ProgressBar,
|
||||
|
||||
pub preferences_stack: PreferencesStack
|
||||
}
|
||||
|
||||
|
@ -25,16 +38,23 @@ impl App {
|
|||
// Create builder from UI file
|
||||
let builder = gtk::Builder::from_string(include_str!("../../assets/ui/.dist/main.ui"));
|
||||
|
||||
let window = get_object::<adw::ApplicationWindow>(&builder, "window")?;
|
||||
let toast_overlay = get_object::<adw::ToastOverlay>(&builder, "toast_overlay")?;
|
||||
|
||||
// Parse objects from builder
|
||||
let result = Self {
|
||||
window: get_object(&builder, "window")?,
|
||||
window: window.clone(),
|
||||
leaflet: get_object(&builder, "leaflet")?,
|
||||
launch_game: get_object(&builder, "launch_game")?,
|
||||
launch_game_debug: get_object(&builder, "launch_game_debug")?,
|
||||
open_preferences: get_object(&builder, "open_preferences")?,
|
||||
toast_overlay: get_object(&builder, "toast_overlay")?,
|
||||
toast_overlay: toast_overlay.clone(),
|
||||
|
||||
preferences_stack: PreferencesStack::new()?
|
||||
launch_game_group: get_object(&builder, "launch_game_group")?,
|
||||
progress_bar_group: get_object(&builder, "progress_bar_group")?,
|
||||
progress_bar: get_object(&builder, "progress_bar")?,
|
||||
|
||||
preferences_stack: PreferencesStack::new(window, toast_overlay)?
|
||||
};
|
||||
|
||||
// Add preferences page to the leaflet
|
||||
|
@ -73,37 +93,6 @@ impl App {
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
/// Show toast with `toast` title and `See message` button
|
||||
///
|
||||
/// This button will show message dialog with error message
|
||||
pub fn toast_error(&self, toast: &str, err: std::io::Error) {
|
||||
let toast = adw::Toast::new(toast);
|
||||
|
||||
toast.set_button_label(Some("See message"));
|
||||
toast.set_action_name(Some("see-message.see-message"));
|
||||
|
||||
let window_copy = self.window.clone();
|
||||
|
||||
// Show error message in a dialog window
|
||||
add_action(&self.toast_overlay, "see-message", move || {
|
||||
let dialog = gtk::MessageDialog::new(
|
||||
Some(&window_copy),
|
||||
gtk::DialogFlags::all(),
|
||||
gtk::MessageType::Info,
|
||||
gtk::ButtonsType::Close,
|
||||
&err.to_string()
|
||||
);
|
||||
|
||||
dialog.connect_response(move |dialog, _| {
|
||||
dialog.close();
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
});
|
||||
|
||||
self.toast_overlay.add_toast(&toast);
|
||||
}
|
||||
|
||||
pub fn open_preferences_page(&self) -> Result<(), Error> {
|
||||
self.preferences_stack.update()?;
|
||||
|
||||
|
@ -111,4 +100,26 @@ impl App {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update_state(&self, state: AppState) {
|
||||
match state {
|
||||
AppState::Launch => {
|
||||
self.launch_game_group.set_visible(true);
|
||||
self.progress_bar_group.set_visible(false);
|
||||
},
|
||||
AppState::Progress { title, progress } => {
|
||||
self.launch_game_group.set_visible(false);
|
||||
self.progress_bar_group.set_visible(true);
|
||||
|
||||
self.progress_bar.set_text(Some(&title));
|
||||
self.progress_bar.set_fraction(progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToastError for App {
|
||||
fn get_toast_widgets(&self) -> (adw::ApplicationWindow, adw::ToastOverlay) {
|
||||
(self.window.clone(), self.toast_overlay.clone())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,14 @@ use libadwaita::{self as adw, prelude::*};
|
|||
|
||||
mod main;
|
||||
mod preferences;
|
||||
mod toast_error;
|
||||
|
||||
pub use main::App as MainApp;
|
||||
pub use main::{
|
||||
App as MainApp,
|
||||
AppState as MainAppState,
|
||||
};
|
||||
|
||||
pub use toast_error::ToastError;
|
||||
|
||||
/// This function loads object from builder or panics if it doesn't exist
|
||||
pub fn get_object<T: IsA<gtk::glib::Object>>(builder: >k::Builder, name: &str) -> Result<T, String> {
|
||||
|
|
|
@ -103,9 +103,11 @@ impl Page {
|
|||
}
|
||||
|
||||
/// This method is being called by the `PreferencesStack::update`
|
||||
pub fn update(&self) -> Result<(), Error> {
|
||||
pub fn update(&self, status_page: &adw::StatusPage) -> Result<(), Error> {
|
||||
let config = config::get()?;
|
||||
|
||||
status_page.set_description(Some("Loading preferences..."));
|
||||
|
||||
// Update Wine sync
|
||||
self.sync_combo.set_selected(config.game.wine.sync.into());
|
||||
|
||||
|
|
|
@ -32,13 +32,15 @@ impl Page {
|
|||
}
|
||||
|
||||
/// This method is being called by the `PreferencesStack::update`
|
||||
pub fn update(&self) -> Result<(), Error> {
|
||||
pub fn update(&self, status_page: &adw::StatusPage) -> Result<(), Error> {
|
||||
let config = config::get()?;
|
||||
let game = Game::new(config.game.path);
|
||||
|
||||
self.game_version.set_tooltip_text(None);
|
||||
self.patch_version.set_tooltip_text(None);
|
||||
|
||||
status_page.set_description(Some("Updating game info..."));
|
||||
|
||||
match game.try_get_diff()? {
|
||||
VersionDiff::Latest(version) => {
|
||||
self.game_version.set_label(&version.to_string());
|
||||
|
@ -61,6 +63,8 @@ impl Page {
|
|||
}
|
||||
}
|
||||
|
||||
status_page.set_description(Some("Updating patch info..."));
|
||||
|
||||
match Patch::try_fetch(config.patch.servers)? {
|
||||
Patch::NotAvailable => {
|
||||
self.patch_version.set_label("not available");
|
||||
|
|
|
@ -4,6 +4,7 @@ use libadwaita::{self as adw, prelude::*};
|
|||
use std::io::Error;
|
||||
|
||||
use crate::ui::get_object;
|
||||
use crate::ui::ToastError;
|
||||
|
||||
mod general_page;
|
||||
mod enhanced_page;
|
||||
|
@ -15,9 +16,15 @@ pub mod pages {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct PreferencesStack {
|
||||
pub window: adw::ApplicationWindow,
|
||||
pub toast_overlay: adw::ToastOverlay,
|
||||
|
||||
pub preferences: gtk::Box,
|
||||
pub preferences_go_back: gtk::Button,
|
||||
|
||||
pub status_page: adw::StatusPage,
|
||||
pub flap: adw::Flap,
|
||||
|
||||
pub stack: gtk::Stack,
|
||||
|
||||
pub general_page: pages::GeneralPage,
|
||||
|
@ -25,13 +32,21 @@ pub struct PreferencesStack {
|
|||
}
|
||||
|
||||
impl PreferencesStack {
|
||||
pub fn new() -> Result<Self, String> {
|
||||
pub fn new(window: adw::ApplicationWindow, toast_overlay: adw::ToastOverlay) -> Result<Self, String> {
|
||||
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/preferences.ui"));
|
||||
|
||||
let result = Self {
|
||||
window,
|
||||
toast_overlay,
|
||||
|
||||
preferences: get_object(&builder, "preferences")?,
|
||||
preferences_go_back: get_object(&builder, "preferences_go_back")?,
|
||||
|
||||
status_page: get_object(&builder, "status_page")?,
|
||||
flap: get_object(&builder, "flap")?,
|
||||
|
||||
stack: get_object(&builder, "stack")?,
|
||||
|
||||
general_page: pages::GeneralPage::new()?,
|
||||
enhanced_page: pages::EnhancedPage::new()?
|
||||
};
|
||||
|
@ -48,9 +63,24 @@ impl PreferencesStack {
|
|||
///
|
||||
/// TODO: do it asynchronously. The problem is that I somehow need to handle this function's error to display it as a toast
|
||||
pub fn update(&self) -> Result<(), Error> {
|
||||
self.general_page.update()?;
|
||||
self.enhanced_page.update()?;
|
||||
self.status_page.set_visible(true);
|
||||
self.status_page.set_description(None);
|
||||
self.flap.set_visible(false);
|
||||
|
||||
self.general_page.update(&self.status_page)?;
|
||||
self.enhanced_page.update(&self.status_page)?;
|
||||
|
||||
self.status_page.set_visible(false);
|
||||
self.flap.set_visible(true);
|
||||
|
||||
self.toast_error("Aboba amogus", Error::last_os_error());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToastError for PreferencesStack {
|
||||
fn get_toast_widgets(&self) -> (adw::ApplicationWindow, adw::ToastOverlay) {
|
||||
(self.window.clone(), self.toast_overlay.clone())
|
||||
}
|
||||
}
|
||||
|
|
42
src/ui/toast_error.rs
Normal file
42
src/ui/toast_error.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use gtk4::{self as gtk, prelude::*};
|
||||
use libadwaita::{self as adw, prelude::*};
|
||||
|
||||
use std::io::Error;
|
||||
|
||||
use super::add_action;
|
||||
|
||||
pub trait ToastError {
|
||||
fn get_toast_widgets(&self) -> (adw::ApplicationWindow, adw::ToastOverlay);
|
||||
|
||||
/// Show toast with `toast` title and `See message` button
|
||||
///
|
||||
/// This button will show message dialog with error message
|
||||
fn toast_error(&self, toast: &str, err: Error) {
|
||||
let toast = adw::Toast::new(toast);
|
||||
|
||||
toast.set_button_label(Some("See message"));
|
||||
toast.set_action_name(Some("see-message.see-message"));
|
||||
toast.set_timeout(0);
|
||||
|
||||
let (window, toast_overlay) = self.get_toast_widgets();
|
||||
|
||||
// Show error message in a dialog window
|
||||
add_action(&toast_overlay, "see-message", move || {
|
||||
let dialog = gtk::MessageDialog::new(
|
||||
Some(&window),
|
||||
gtk::DialogFlags::all(),
|
||||
gtk::MessageType::Info,
|
||||
gtk::ButtonsType::Close,
|
||||
&err.to_string()
|
||||
);
|
||||
|
||||
dialog.connect_response(move |dialog, _| {
|
||||
dialog.close();
|
||||
});
|
||||
|
||||
dialog.show();
|
||||
});
|
||||
|
||||
toast_overlay.add_toast(&toast);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue