diff --git a/assets/resources.xml b/assets/resources.xml index 856b712..d112228 100644 --- a/assets/resources.xml +++ b/assets/resources.xml @@ -9,12 +9,13 @@ ui/.dist/preferences.ui - ui/.dist/first_run/page_1.ui - ui/.dist/first_run/page_2.ui - ui/.dist/first_run/page_3.ui - ui/.dist/first_run/page_4.ui - ui/.dist/first_run/page_5.ui - ui/.dist/first_run/page_6.ui + ui/.dist/first_run/welcome.ui + ui/.dist/first_run/dependencies.ui + ui/.dist/first_run/tos_warning.ui + ui/.dist/first_run/default_paths.ui + ui/.dist/first_run/voice_packages.ui + ui/.dist/first_run/download_components.ui + ui/.dist/first_run/finish.ui ui/.dist/preferences/general.ui diff --git a/assets/ui/first_run/page_4.blp b/assets/ui/first_run/default_paths.blp similarity index 100% rename from assets/ui/first_run/page_4.blp rename to assets/ui/first_run/default_paths.blp diff --git a/assets/ui/first_run/page_2.blp b/assets/ui/first_run/dependencies.blp similarity index 100% rename from assets/ui/first_run/page_2.blp rename to assets/ui/first_run/dependencies.blp diff --git a/assets/ui/first_run/page_5.blp b/assets/ui/first_run/download_components.blp similarity index 100% rename from assets/ui/first_run/page_5.blp rename to assets/ui/first_run/download_components.blp diff --git a/assets/ui/first_run/page_6.blp b/assets/ui/first_run/finish.blp similarity index 100% rename from assets/ui/first_run/page_6.blp rename to assets/ui/first_run/finish.blp diff --git a/assets/ui/first_run/page_3.blp b/assets/ui/first_run/tos_warning.blp similarity index 100% rename from assets/ui/first_run/page_3.blp rename to assets/ui/first_run/tos_warning.blp diff --git a/assets/ui/first_run/voice_packages.blp b/assets/ui/first_run/voice_packages.blp new file mode 100644 index 0000000..c7bae1e --- /dev/null +++ b/assets/ui/first_run/voice_packages.blp @@ -0,0 +1,44 @@ +using Gtk 4.0; +using Adw 1; + +Gtk.Box page { + orientation: vertical; + hexpand: true; + + Adw.PreferencesPage { + Adw.PreferencesGroup { + Gtk.Label { + label: "Select voice packages"; + margin-top: 16; + + styles ["title-1"] + } + } + + Adw.PreferencesGroup voice_packages_group { + vexpand: true; + valign: center; + } + + Adw.PreferencesGroup { + vexpand: true; + valign: center; + + Gtk.Box { + orientation: horizontal; + spacing: 8; + halign: center; + + Gtk.Button continue_button { + label: "Continue"; + + styles ["suggested-action"] + } + + Gtk.Button exit_button { + label: "Exit"; + } + } + } + } +} diff --git a/assets/ui/first_run/page_1.blp b/assets/ui/first_run/welcome.blp similarity index 91% rename from assets/ui/first_run/page_1.blp rename to assets/ui/first_run/welcome.blp index bcdfa36..d39453a 100644 --- a/assets/ui/first_run/page_1.blp +++ b/assets/ui/first_run/welcome.blp @@ -45,10 +45,9 @@ Gtk.Box page { styles ["suggested-action"] } - Gtk.Button { + Gtk.Button advanced_button { label: "Advanced"; - sensitive: false; - tooltip-text: "Work in progress"; + tooltip-text: "You can choose default folders paths"; } } } diff --git a/src/ui/first_run/page_4.rs b/src/ui/first_run/default_paths.rs similarity index 99% rename from src/ui/first_run/page_4.rs rename to src/ui/first_run/default_paths.rs index 63a3209..4807ba0 100644 --- a/src/ui/first_run/page_4.rs +++ b/src/ui/first_run/default_paths.rs @@ -53,7 +53,7 @@ pub struct Page { impl Page { pub fn new(window: gtk::Window) -> Result { - let builder = gtk::Builder::from_resource("/org/app/ui/first_run/page_4.ui"); + let builder = gtk::Builder::from_resource("/org/app/ui/first_run/default_paths.ui"); let result = Self { window, diff --git a/src/ui/first_run/page_2.rs b/src/ui/first_run/dependencies.rs similarity index 98% rename from src/ui/first_run/page_2.rs rename to src/ui/first_run/dependencies.rs index 065333b..4c4c8c0 100644 --- a/src/ui/first_run/page_2.rs +++ b/src/ui/first_run/dependencies.rs @@ -18,7 +18,7 @@ pub struct Page { impl Page { pub fn new() -> Result { - let builder = gtk::Builder::from_resource("/org/app/ui/first_run/page_2.ui"); + let builder = gtk::Builder::from_resource("/org/app/ui/first_run/dependencies.ui"); let result = Self { page: get_object(&builder, "page")?, diff --git a/src/ui/first_run/page_5.rs b/src/ui/first_run/download_components.rs similarity index 98% rename from src/ui/first_run/page_5.rs rename to src/ui/first_run/download_components.rs index 7368ff7..2e4576f 100644 --- a/src/ui/first_run/page_5.rs +++ b/src/ui/first_run/download_components.rs @@ -25,7 +25,7 @@ pub struct Page { impl Page { pub fn new() -> Result { - let builder = gtk::Builder::from_resource("/org/app/ui/first_run/page_5.ui"); + let builder = gtk::Builder::from_resource("/org/app/ui/first_run/download_components.ui"); let mut result = Self { page: get_object(&builder, "page")?, diff --git a/src/ui/first_run/page_6.rs b/src/ui/first_run/finish.rs similarity index 95% rename from src/ui/first_run/page_6.rs rename to src/ui/first_run/finish.rs index 35ae70c..6a49cf0 100644 --- a/src/ui/first_run/page_6.rs +++ b/src/ui/first_run/finish.rs @@ -11,7 +11,7 @@ pub struct Page { impl Page { pub fn new() -> Result { - let builder = gtk::Builder::from_resource("/org/app/ui/first_run/page_6.ui"); + let builder = gtk::Builder::from_resource("/org/app/ui/first_run/finish.ui"); Ok(Self { page: get_object(&builder, "page")?, diff --git a/src/ui/first_run/mod.rs b/src/ui/first_run/mod.rs index 936d3dc..0176c6e 100644 --- a/src/ui/first_run/mod.rs +++ b/src/ui/first_run/mod.rs @@ -10,12 +10,13 @@ use std::process::Command; use anime_game_core::prelude::*; -mod page_1; -mod page_2; -mod page_3; -mod page_4; -mod page_5; -mod page_6; +mod welcome; +mod dependencies; +mod tos_warning; +mod default_paths; +mod voice_packages; +mod download_components; +mod finish; use crate::ui::*; use crate::ui::components::progress_bar::*; @@ -34,13 +35,13 @@ pub struct AppWidgets { pub window: adw::ApplicationWindow, pub carousel: adw::Carousel, - // TODO: use names instead of numbers - pub page_1: page_1::Page, - pub page_2: page_2::Page, - pub page_3: page_3::Page, - pub page_4: page_4::Page, - pub page_5: page_5::Page, - pub page_6: page_6::Page + pub welcome: welcome::Page, + pub dependencies: dependencies::Page, + pub tos_warning: tos_warning::Page, + pub default_paths: default_paths::Page, + pub voice_packages: voice_packages::Page, + pub download_components: download_components::Page, + pub finish: finish::Page } impl AppWidgets { @@ -51,21 +52,23 @@ impl AppWidgets { window: get_object(&builder, "window")?, carousel: get_object(&builder, "carousel")?, - page_1: page_1::Page::new()?, - page_2: page_2::Page::new()?, - page_3: page_3::Page::new()?, - page_4: page_4::Page::new(get_object(&builder, "window")?)?, - page_5: page_5::Page::new()?, - page_6: page_6::Page::new()? + welcome: welcome::Page::new()?, + dependencies: dependencies::Page::new()?, + tos_warning: tos_warning::Page::new()?, + default_paths: default_paths::Page::new(get_object(&builder, "window")?)?, + voice_packages: voice_packages::Page::new()?, + download_components: download_components::Page::new()?, + finish: finish::Page::new()? }; // Add pages to carousel - result.carousel.append(&result.page_1.page); - result.carousel.append(&result.page_2.page); - result.carousel.append(&result.page_3.page); - result.carousel.append(&result.page_4.page); - result.carousel.append(&result.page_5.page); - result.carousel.append(&result.page_6.page); + result.carousel.append(&result.welcome.page); + result.carousel.append(&result.dependencies.page); + result.carousel.append(&result.tos_warning.page); + result.carousel.append(&result.default_paths.page); + result.carousel.append(&result.voice_packages.page); + result.carousel.append(&result.download_components.page); + result.carousel.append(&result.finish.page); // Set devel style to ApplicationWindow if it's debug mode if crate::APP_DEBUG { @@ -83,12 +86,14 @@ impl AppWidgets { /// Has to implement glib::Downgrade` trait #[derive(Debug, glib::Downgrade)] pub enum Actions { - FirstPageContinue, - SecondPageCheck, - ThirdPageContinue, - FourthPageContinue, - FifthPageDownload, - FifthPageContinue, + WelcomeContinue, + WelcomeAdvanced, + DependenciesContinue, + TosWarningContinue, + DefaultPathsContinue, + VoicePackagesContinue, + DownloadComponents, + DownloadComponentsContinue, Restart, Exit } @@ -115,7 +120,8 @@ impl Actions { #[derive(Clone)] pub struct App { widgets: AppWidgets, - actions: Rc>>> + actions: Rc>>>, + advanced: Rc> } impl App { @@ -124,7 +130,8 @@ impl App { // Get default widgets from ui file and add events to them let result = Self { widgets: AppWidgets::try_get()?, - actions: Default::default() + actions: Default::default(), + advanced: Default::default() }.init_events().init_actions(); // Bind app to the window @@ -135,20 +142,23 @@ impl App { /// Add default events and values to the widgets fn init_events(self) -> Self { - self.widgets.page_1.continue_button.connect_clicked(Actions::FirstPageContinue.into_fn(&self)); - self.widgets.page_3.continue_button.connect_clicked(Actions::ThirdPageContinue.into_fn(&self)); - self.widgets.page_4.continue_button.connect_clicked(Actions::FourthPageContinue.into_fn(&self)); + self.widgets.welcome.continue_button.connect_clicked(Actions::WelcomeContinue.into_fn(&self)); + self.widgets.tos_warning.continue_button.connect_clicked(Actions::TosWarningContinue.into_fn(&self)); + self.widgets.default_paths.continue_button.connect_clicked(Actions::DefaultPathsContinue.into_fn(&self)); + self.widgets.dependencies.check_button.connect_clicked(Actions::DependenciesContinue.into_fn(&self)); + self.widgets.voice_packages.continue_button.connect_clicked(Actions::VoicePackagesContinue.into_fn(&self)); - self.widgets.page_2.check_button.connect_clicked(Actions::SecondPageCheck.into_fn(&self)); - self.widgets.page_5.download_button.connect_clicked(Actions::FifthPageDownload.into_fn(&self)); + self.widgets.welcome.advanced_button.connect_clicked(Actions::WelcomeAdvanced.into_fn(&self)); + self.widgets.download_components.download_button.connect_clicked(Actions::DownloadComponents.into_fn(&self)); - self.widgets.page_6.restart_button.connect_clicked(Actions::Restart.into_fn(&self)); + self.widgets.dependencies.exit_button.connect_clicked(Actions::Exit.into_fn(&self)); + self.widgets.tos_warning.exit_button.connect_clicked(Actions::Exit.into_fn(&self)); + self.widgets.default_paths.exit_button.connect_clicked(Actions::Exit.into_fn(&self)); + self.widgets.voice_packages.exit_button.connect_clicked(Actions::Exit.into_fn(&self)); + self.widgets.download_components.exit_button.connect_clicked(Actions::Exit.into_fn(&self)); + self.widgets.finish.exit_button.connect_clicked(Actions::Exit.into_fn(&self)); - self.widgets.page_2.exit_button.connect_clicked(Actions::Exit.into_fn(&self)); - self.widgets.page_3.exit_button.connect_clicked(Actions::Exit.into_fn(&self)); - self.widgets.page_4.exit_button.connect_clicked(Actions::Exit.into_fn(&self)); - self.widgets.page_5.exit_button.connect_clicked(Actions::Exit.into_fn(&self)); - self.widgets.page_6.exit_button.connect_clicked(Actions::Exit.into_fn(&self)); + self.widgets.finish.restart_button.connect_clicked(Actions::Restart.into_fn(&self)); self } @@ -166,44 +176,62 @@ impl App { println!("[update] action: {:?}", &action); match action { - Actions::FirstPageContinue => { + Actions::WelcomeContinue => { this.widgets.carousel.scroll_to({ if lib::is_available("git") && lib::is_available("xdelta3") { - &this.widgets.page_3.page + &this.widgets.tos_warning.page } else { - &this.widgets.page_2.page + &this.widgets.dependencies.page } }, true); } - Actions::SecondPageCheck => { + Actions::WelcomeAdvanced => { + this.advanced.set(true); + + this.update(Actions::WelcomeContinue).unwrap(); + } + + Actions::DependenciesContinue => { if lib::is_available("git") && lib::is_available("xdelta3") { - this.widgets.carousel.scroll_to(&this.widgets.page_3.page, true); + this.widgets.carousel.scroll_to(&this.widgets.tos_warning.page, true); } } - Actions::ThirdPageContinue => { - this.widgets.carousel.scroll_to(&this.widgets.page_4.page, true); + Actions::TosWarningContinue => { + this.widgets.carousel.scroll_to({ + if this.advanced.get() { + &this.widgets.default_paths.page + } else { + &this.widgets.voice_packages.page + } + }, true); } - Actions::FourthPageContinue => { - config::update_raw(this.widgets.page_4.update_config(config::get().unwrap())).unwrap(); + Actions::DefaultPathsContinue => { + config::update_raw(this.widgets.default_paths.update_config(config::get().unwrap())).unwrap(); - this.widgets.carousel.scroll_to(&this.widgets.page_5.page, true); + this.widgets.carousel.scroll_to(&this.widgets.voice_packages.page, true); } - Actions::FifthPageDownload => { - this.widgets.page_5.wine_version.set_sensitive(false); - this.widgets.page_5.dxvk_version.set_sensitive(false); + Actions::VoicePackagesContinue => { + config::update_raw(this.widgets.voice_packages.update_config(config::get().unwrap())).unwrap(); - this.widgets.page_5.progress_bar.show(); + this.widgets.carousel.scroll_to(&this.widgets.download_components.page, true); + } + + Actions::DownloadComponents => { + this.widgets.download_components.wine_version.set_sensitive(false); + this.widgets.download_components.dxvk_version.set_sensitive(false); + + this.widgets.download_components.progress_bar.show(); let (sender, receiver) = glib::MainContext::channel::(glib::PRIORITY_DEFAULT); - let progress_bar = this.widgets.page_5.progress_bar.clone(); + let progress_bar = this.widgets.download_components.progress_bar.clone(); - let wine_version = this.widgets.page_5.get_wine_version().clone(); - let dxvk_version = this.widgets.page_5.get_dxvk_version().clone(); + let wine_version = this.widgets.download_components.get_wine_version().clone(); + let dxvk_version = this.widgets.download_components.get_dxvk_version().clone(); let wine_version_copy = wine_version.clone(); @@ -276,7 +304,7 @@ impl App { std::fs::remove_file(format!("{}/.first-run", launcher_dir)).unwrap(); // Show next page - this.update(Actions::FifthPageContinue).unwrap(); + this.update(Actions::DownloadComponentsContinue).unwrap(); } } }); @@ -287,8 +315,8 @@ impl App { }); } - Actions::FifthPageContinue => { - this.widgets.carousel.scroll_to(&this.widgets.page_6.page, true); + Actions::DownloadComponentsContinue => { + this.widgets.carousel.scroll_to(&this.widgets.finish.page, true); } Actions::Restart => { diff --git a/src/ui/first_run/page_3.rs b/src/ui/first_run/tos_warning.rs similarity index 94% rename from src/ui/first_run/page_3.rs rename to src/ui/first_run/tos_warning.rs index e6b89a4..bc34428 100644 --- a/src/ui/first_run/page_3.rs +++ b/src/ui/first_run/tos_warning.rs @@ -11,7 +11,7 @@ pub struct Page { impl Page { pub fn new() -> Result { - let builder = gtk::Builder::from_resource("/org/app/ui/first_run/page_3.ui"); + let builder = gtk::Builder::from_resource("/org/app/ui/first_run/tos_warning.ui"); Ok(Self { page: get_object(&builder, "page")?, diff --git a/src/ui/first_run/voice_packages.rs b/src/ui/first_run/voice_packages.rs new file mode 100644 index 0000000..7a87732 --- /dev/null +++ b/src/ui/first_run/voice_packages.rs @@ -0,0 +1,80 @@ +use gtk4 as gtk; +use libadwaita::{self as adw, prelude::*}; + +use anime_game_core::voice_data::prelude::*; + +use crate::lib::config; +use crate::ui::*; + +#[derive(Clone)] +pub struct Page { + pub page: gtk::Box, + pub voice_packages_group: adw::PreferencesGroup, + + pub continue_button: gtk::Button, + pub exit_button: gtk::Button, + + pub voice_packages: Vec<(VoiceLocale, adw::ActionRow, gtk::Switch)> +} + +impl Page { + pub fn new() -> Result { + let builder = gtk::Builder::from_resource("/org/app/ui/first_run/voice_packages.ui"); + + let mut result = Self { + page: get_object(&builder, "page")?, + voice_packages_group: get_object(&builder, "voice_packages_group")?, + + continue_button: get_object(&builder, "continue_button")?, + exit_button: get_object(&builder, "exit_button")?, + + voice_packages: Vec::new() + }; + + let mut packages = Vec::new(); + + for package in VoicePackage::list_latest().expect("Failed to list voice packages") { + let row = adw::ActionRow::new(); + let switch = gtk::Switch::new(); + + row.set_title(package.locale().to_name()); + switch.set_valign(gtk::Align::Center); + + row.add_suffix(&switch); + + result.voice_packages_group.add(&row); + + packages.push((package.locale(), row, switch)); + } + + if let Ok(config) = config::get() { + for voice in config.game.voices { + if let Some(voice) = VoiceLocale::from_str(voice) { + for (locale, _, switcher) in &packages { + if voice == *locale { + switcher.set_state(true); + } + } + } + } + } + + result.voice_packages = packages; + + Ok(result) + } + + pub fn update_config(&self, mut config: config::Config) -> config::Config { + let mut voices = Vec::new(); + + for (locale, _, switcher) in &self.voice_packages { + if switcher.state() { + voices.push(locale.to_code().to_string()); + } + } + + config.game.voices = voices; + + config + } +} diff --git a/src/ui/first_run/page_1.rs b/src/ui/first_run/welcome.rs similarity index 68% rename from src/ui/first_run/page_1.rs rename to src/ui/first_run/welcome.rs index c0618f2..b61d2f3 100644 --- a/src/ui/first_run/page_1.rs +++ b/src/ui/first_run/welcome.rs @@ -5,16 +5,18 @@ use crate::ui::*; #[derive(Clone)] pub struct Page { pub page: gtk::Box, - pub continue_button: gtk::Button + pub continue_button: gtk::Button, + pub advanced_button: gtk::Button } impl Page { pub fn new() -> Result { - let builder = gtk::Builder::from_resource("/org/app/ui/first_run/page_1.ui"); + let builder = gtk::Builder::from_resource("/org/app/ui/first_run/welcome.ui"); Ok(Self { page: get_object(&builder, "page")?, - continue_button: get_object(&builder, "continue_button")? + continue_button: get_object(&builder, "continue_button")?, + advanced_button: get_object(&builder, "advanced_button")? }) } }