diff --git a/src/ui/first_run/download_components.rs b/src/ui/first_run/download_components.rs index 942e248..5cbf860 100644 --- a/src/ui/first_run/download_components.rs +++ b/src/ui/first_run/download_components.rs @@ -13,6 +13,7 @@ use std::path::PathBuf; use super::main::FirstRunAppMsg; use crate::ui::components::*; use crate::i18n::*; +use crate::FIRST_RUN_FILE; fn get_installer(uri: &str, temp: Option<&PathBuf>, speed_limit: u64) -> anyhow::Result { let mut installer = Installer::new(uri)?; @@ -159,8 +160,15 @@ impl SimpleAsyncComponent for DownloadComponentsApp { #[watch] set_icon_name: match model.downloading_wine { Some(true) => Some("emblem-ok"), - Some(false) => Some("process-working"), + Some(false) => None, // Some("process-working"), None => None + }, + + add_prefix = >k::Spinner { + set_spinning: true, + + #[watch] + set_visible: model.downloading_wine == Some(false), } }, @@ -170,8 +178,15 @@ impl SimpleAsyncComponent for DownloadComponentsApp { #[watch] set_icon_name: match model.creating_prefix { Some(true) => Some("emblem-ok"), - Some(false) => Some("process-working"), + Some(false) => None, // Some("process-working"), None => None + }, + + add_prefix = >k::Spinner { + set_spinning: true, + + #[watch] + set_visible: model.creating_prefix == Some(false), } }, @@ -181,8 +196,15 @@ impl SimpleAsyncComponent for DownloadComponentsApp { #[watch] set_icon_name: match model.downloading_dxvk { Some(true) => Some("emblem-ok"), - Some(false) => Some("process-working"), + Some(false) => None, // Some("process-working"), None => None + }, + + add_prefix = >k::Spinner { + set_spinning: true, + + #[watch] + set_visible: model.downloading_dxvk == Some(false), } }, @@ -192,8 +214,15 @@ impl SimpleAsyncComponent for DownloadComponentsApp { #[watch] set_icon_name: match model.applying_dxvk { Some(true) => Some("emblem-ok"), - Some(false) => Some("process-working"), + Some(false) => None, // Some("process-working"), None => None + }, + + add_prefix = >k::Spinner { + set_spinning: true, + + #[watch] + set_visible: model.applying_dxvk == Some(false), } } }, @@ -480,6 +509,8 @@ impl SimpleAsyncComponent for DownloadComponentsApp { #[allow(unused_must_use)] DownloadComponentsAppMsg::Continue => { + std::fs::remove_file(FIRST_RUN_FILE.as_path()); + sender.output(Self::Output::ScrollToFinish); } diff --git a/src/ui/first_run/finish.rs b/src/ui/first_run/finish.rs new file mode 100644 index 0000000..c2d5514 --- /dev/null +++ b/src/ui/first_run/finish.rs @@ -0,0 +1,98 @@ +use relm4::prelude::*; +use relm4::component::*; + +use adw::prelude::*; + +use crate::i18n::*; +use super::main::*; + +pub struct FinishApp; + +#[derive(Debug, Clone)] +pub enum FinishAppMsg { + Restart, + Exit +} + +#[relm4::component(async, pub)] +impl SimpleAsyncComponent for FinishApp { + type Init = (); + type Input = FinishAppMsg; + type Output = FirstRunAppMsg; + + view! { + adw::PreferencesPage { + set_hexpand: true, + + add = &adw::PreferencesGroup { + set_valign: gtk::Align::Center, + set_vexpand: true, + + gtk::Label { + set_label: "Everything's done!", + add_css_class: "title-1" + }, + + gtk::Label { + set_label: "All the basic components were downloaded. Now you can restart the launcher and download the game. Welcome to our club!", + + set_justify: gtk::Justification::Center, + set_wrap: true, + set_margin_top: 32 + } + }, + + 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: "Restart", + set_css_classes: &["suggested-action", "pill"], + + connect_clicked => FinishAppMsg::Restart + }, + + gtk::Button { + set_label: "Exit", + add_css_class: "pill", + + connect_clicked => FinishAppMsg::Exit + } + } + } + } + } + + async fn init( + _init: Self::Init, + root: Self::Root, + _sender: AsyncComponentSender, + ) -> AsyncComponentParts { + let model = Self; + let widgets = view_output!(); + + AsyncComponentParts { model, widgets } + } + + async fn update(&mut self, msg: Self::Input, _sender: AsyncComponentSender) { + match msg { + FinishAppMsg::Restart => { + std::process::Command::new(std::env::current_exe().unwrap()).spawn().unwrap(); + + // TODO: relm4 has some function for it + std::process::exit(0); + } + + FinishAppMsg::Exit => { + // TODO: relm4 has some function for it + std::process::exit(0); + } + } + } +} diff --git a/src/ui/first_run/main.rs b/src/ui/first_run/main.rs index 983baf6..8d28c93 100644 --- a/src/ui/first_run/main.rs +++ b/src/ui/first_run/main.rs @@ -12,6 +12,7 @@ use super::dependencies::*; use super::default_paths::*; use super::select_voiceovers::*; use super::download_components::*; +use super::finish::*; pub static mut MAIN_WINDOW: Option = None; @@ -22,6 +23,7 @@ pub struct FirstRunApp { default_paths: AsyncController, select_voiceovers: AsyncController, download_components: AsyncController, + finish: AsyncController, toast_overlay: adw::ToastOverlay, carousel: adw::Carousel, @@ -76,6 +78,7 @@ impl SimpleComponent for FirstRunApp { append = model.default_paths.widget(), append = model.select_voiceovers.widget(), append = model.download_components.widget(), + append = model.finish.widget(), }, adw::CarouselIndicatorDots { @@ -122,6 +125,10 @@ impl SimpleComponent for FirstRunApp { .launch(()) .forward(sender.input_sender(), std::convert::identity), + finish: FinishApp::builder() + .launch(()) + .forward(sender.input_sender(), std::convert::identity), + toast_overlay, carousel, @@ -179,7 +186,7 @@ impl SimpleComponent for FirstRunApp { FirstRunAppMsg::ScrollToFinish => { self.title = String::from("Finish"); - self.carousel.scroll_to(self.welcome.widget(), true); + self.carousel.scroll_to(self.finish.widget(), true); } FirstRunAppMsg::Toast { title, description } => unsafe { diff --git a/src/ui/first_run/mod.rs b/src/ui/first_run/mod.rs index b530087..37e26e1 100644 --- a/src/ui/first_run/mod.rs +++ b/src/ui/first_run/mod.rs @@ -5,3 +5,4 @@ pub mod dependencies; pub mod default_paths; pub mod select_voiceovers; pub mod download_components; +pub mod finish;