mirror of
https://github.com/an-anime-team/an-anime-game-launcher.git
synced 2025-02-03 14:30:50 +03:00
Made an abstraction over widgets with downloading functionality
This commit is contained in:
parent
30c7d836bd
commit
741513ab91
8 changed files with 122 additions and 95 deletions
|
@ -1,22 +1,10 @@
|
|||
use gtk4::{self as gtk, prelude::*};
|
||||
use libadwaita::{self as adw, prelude::*};
|
||||
|
||||
use gtk::glib;
|
||||
use gtk::Align;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use anime_game_core::prelude::*;
|
||||
use wait_not_await::Await;
|
||||
|
||||
use crate::lib::wine::Version;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DownloadingResult {
|
||||
DownloadingError(std::io::Error),
|
||||
UnpackingError,
|
||||
Done
|
||||
}
|
||||
use crate::ui::traits::download_component::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WineRow {
|
||||
|
@ -60,10 +48,6 @@ impl WineRow {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_downloaded<T: ToString>(&self, runners_folder: T) -> bool {
|
||||
Path::new(&format!("{}/{}", runners_folder.to_string(), self.version.name)).exists()
|
||||
}
|
||||
|
||||
pub fn update_state<T: ToString>(&self, runners_folder: T) {
|
||||
if self.is_downloaded(runners_folder) {
|
||||
self.button.set_icon_name("user-trash-symbolic");
|
||||
|
@ -73,80 +57,19 @@ impl WineRow {
|
|||
self.button.set_icon_name("document-save-symbolic");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Download wine
|
||||
///
|
||||
/// This method doesn't update components states, so you need to call `update_state` method manually
|
||||
pub fn download<T: ToString>(&self, runners_folder: T) -> std::io::Result<Await<DownloadingResult>> {
|
||||
let (sender, receiver) = glib::MainContext::channel::<InstallerUpdate>(glib::PRIORITY_DEFAULT);
|
||||
let this = self.clone();
|
||||
|
||||
this.progress_bar.set_visible(true);
|
||||
this.button.set_visible(false);
|
||||
|
||||
let (downl_send, downl_recv) = std::sync::mpsc::channel();
|
||||
|
||||
receiver.attach(None, move |state| {
|
||||
match state {
|
||||
InstallerUpdate::DownloadingStarted(_) => (),
|
||||
InstallerUpdate::DownloadingFinished => (),
|
||||
InstallerUpdate::UnpackingStarted(_) => (),
|
||||
|
||||
InstallerUpdate::DownloadingProgress(curr, total) => {
|
||||
let progress = curr as f64 / total as f64;
|
||||
|
||||
this.progress_bar.set_fraction(progress);
|
||||
this.progress_bar.set_text(Some(&format!("Downloading: {}%", (progress * 100.0) as u64)));
|
||||
},
|
||||
|
||||
InstallerUpdate::UnpackingProgress(curr, total) => {
|
||||
let progress = curr as f64 / total as f64;
|
||||
|
||||
this.progress_bar.set_fraction(progress);
|
||||
this.progress_bar.set_text(Some(&format!("Unpacking: {}%", (progress * 100.0) as u64)));
|
||||
},
|
||||
|
||||
InstallerUpdate::UnpackingFinished => {
|
||||
this.progress_bar.set_visible(false);
|
||||
this.button.set_visible(true);
|
||||
|
||||
downl_send.send(DownloadingResult::Done);
|
||||
},
|
||||
|
||||
InstallerUpdate::DownloadingError(err) => {
|
||||
downl_send.send(DownloadingResult::DownloadingError(err.into()));
|
||||
},
|
||||
|
||||
InstallerUpdate::UnpackingError => {
|
||||
downl_send.send(DownloadingResult::UnpackingError);
|
||||
}
|
||||
}
|
||||
|
||||
glib::Continue(true)
|
||||
});
|
||||
|
||||
let (send, recv) = std::sync::mpsc::channel();
|
||||
|
||||
let installer = Installer::new(&self.version.uri)?;
|
||||
let runners_folder = runners_folder.to_string();
|
||||
|
||||
send.send(installer);
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let mut installer = recv.recv().unwrap();
|
||||
|
||||
installer.install(runners_folder, move |state| {
|
||||
sender.send(state);
|
||||
});
|
||||
});
|
||||
|
||||
Ok(Await::new(move || {
|
||||
downl_recv.recv().unwrap()
|
||||
}))
|
||||
impl DownloadComponent for WineRow {
|
||||
fn get_component_path<T: ToString>(&self, installation_path: T) -> String {
|
||||
format!("{}/{}", installation_path.to_string(), self.version.name)
|
||||
}
|
||||
|
||||
pub fn delete<T: ToString>(&self, runners_folder: T) -> std::io::Result<()> {
|
||||
std::fs::remove_dir_all(format!("{}/{}", runners_folder.to_string(), self.version.name))
|
||||
fn get_downloading_widgets(&self) -> (gtk::ProgressBar, gtk::Button) {
|
||||
(self.progress_bar.clone(), self.button.clone())
|
||||
}
|
||||
|
||||
fn get_download_uri(&self) -> String {
|
||||
self.version.uri.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::cell::Cell;
|
|||
use crate::ui::*;
|
||||
|
||||
use super::preferences::PreferencesStack;
|
||||
use super::ToastError;
|
||||
use super::traits::toast_error::ToastError;
|
||||
|
||||
use crate::lib::game;
|
||||
use crate::lib::tasks;
|
||||
|
|
|
@ -3,7 +3,7 @@ use libadwaita::{self as adw, prelude::*};
|
|||
|
||||
mod main;
|
||||
mod preferences;
|
||||
mod toast_error;
|
||||
mod traits;
|
||||
|
||||
pub mod components;
|
||||
|
||||
|
@ -12,8 +12,6 @@ pub use main::{
|
|||
// 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> {
|
||||
match builder.object::<T>(name) {
|
||||
|
|
|
@ -15,6 +15,7 @@ use crate::lib::dxvk;
|
|||
use crate::lib::wine;
|
||||
|
||||
use crate::ui::*;
|
||||
use crate::ui::traits::prelude::*;
|
||||
use crate::ui::components::dxvk_row::DxvkRow;
|
||||
use crate::ui::components::wine_group::WineGroup;
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ use gtk::glib;
|
|||
|
||||
use std::io::Error;
|
||||
|
||||
use crate::ui::get_object;
|
||||
use crate::ui::ToastError;
|
||||
use crate::ui::*;
|
||||
use crate::ui::traits::prelude::*;
|
||||
|
||||
mod general_page;
|
||||
mod enhanced_page;
|
||||
|
|
98
src/ui/traits/download_component.rs
Normal file
98
src/ui/traits/download_component.rs
Normal file
|
@ -0,0 +1,98 @@
|
|||
use gtk4::{self as gtk, prelude::*};
|
||||
use libadwaita::{self as adw, prelude::*};
|
||||
|
||||
use gtk::glib;
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use anime_game_core::prelude::*;
|
||||
use wait_not_await::Await;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DownloadingResult {
|
||||
DownloadingError(std::io::Error),
|
||||
UnpackingError,
|
||||
Done
|
||||
}
|
||||
|
||||
pub trait DownloadComponent {
|
||||
fn get_component_path<T: ToString>(&self, installation_path: T) -> String;
|
||||
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 {
|
||||
Path::new(&self.get_component_path(installation_path)).exists()
|
||||
}
|
||||
|
||||
fn download<T: ToString>(&self, installation_path: T) -> std::io::Result<Await<DownloadingResult>> {
|
||||
let (sender, receiver) = glib::MainContext::channel::<InstallerUpdate>(glib::PRIORITY_DEFAULT);
|
||||
let (progress_bar, button) = self.get_downloading_widgets();
|
||||
|
||||
progress_bar.set_visible(true);
|
||||
button.set_visible(false);
|
||||
|
||||
let (downl_send, downl_recv) = std::sync::mpsc::channel();
|
||||
|
||||
receiver.attach(None, move |state| {
|
||||
match state {
|
||||
InstallerUpdate::DownloadingStarted(_) => (),
|
||||
InstallerUpdate::DownloadingFinished => (),
|
||||
InstallerUpdate::UnpackingStarted(_) => (),
|
||||
|
||||
InstallerUpdate::DownloadingProgress(curr, total) => {
|
||||
let progress = curr as f64 / total as f64;
|
||||
|
||||
progress_bar.set_fraction(progress);
|
||||
progress_bar.set_text(Some(&format!("Downloading: {}%", (progress * 100.0) as u64)));
|
||||
},
|
||||
|
||||
InstallerUpdate::UnpackingProgress(curr, total) => {
|
||||
let progress = curr as f64 / total as f64;
|
||||
|
||||
progress_bar.set_fraction(progress);
|
||||
progress_bar.set_text(Some(&format!("Unpacking: {}%", (progress * 100.0) as u64)));
|
||||
},
|
||||
|
||||
InstallerUpdate::UnpackingFinished => {
|
||||
progress_bar.set_visible(false);
|
||||
button.set_visible(true);
|
||||
|
||||
downl_send.send(DownloadingResult::Done);
|
||||
},
|
||||
|
||||
InstallerUpdate::DownloadingError(err) => {
|
||||
downl_send.send(DownloadingResult::DownloadingError(err.into()));
|
||||
},
|
||||
|
||||
InstallerUpdate::UnpackingError => {
|
||||
downl_send.send(DownloadingResult::UnpackingError);
|
||||
}
|
||||
}
|
||||
|
||||
glib::Continue(true)
|
||||
});
|
||||
|
||||
let (send, recv) = std::sync::mpsc::channel();
|
||||
|
||||
let installer = Installer::new(self.get_download_uri())?;
|
||||
let installation_path = installation_path.to_string();
|
||||
|
||||
send.send(installer);
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let mut installer = recv.recv().unwrap();
|
||||
|
||||
installer.install(installation_path, move |state| {
|
||||
sender.send(state);
|
||||
});
|
||||
});
|
||||
|
||||
Ok(Await::new(move || {
|
||||
downl_recv.recv().unwrap()
|
||||
}))
|
||||
}
|
||||
|
||||
fn delete<T: ToString>(&self, installation_path: T) -> std::io::Result<()> {
|
||||
std::fs::remove_dir_all(self.get_component_path(installation_path))
|
||||
}
|
||||
}
|
7
src/ui/traits/mod.rs
Normal file
7
src/ui/traits/mod.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
pub mod toast_error;
|
||||
pub mod download_component;
|
||||
|
||||
pub mod prelude {
|
||||
pub use super::toast_error::*;
|
||||
pub use super::download_component::*;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use gtk4::{self as gtk, prelude::*};
|
||||
use libadwaita::{self as adw, prelude::*};
|
||||
|
||||
use super::add_action;
|
||||
use crate::ui::add_action;
|
||||
|
||||
pub trait ToastError {
|
||||
fn get_toast_widgets(&self) -> (adw::ApplicationWindow, adw::ToastOverlay);
|
Loading…
Add table
Reference in a new issue