feat(ui): added new pages to the first run window

Added new "ToS warning" and "Dependencies" working pages to the first run window
This commit is contained in:
Observer KRypt0n_ 2023-02-23 21:16:49 +02:00
parent 3f5ce430f9
commit 9d4ad8df34
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
5 changed files with 413 additions and 8 deletions

View file

@ -0,0 +1,199 @@
use relm4::prelude::*;
use relm4::component::*;
use adw::prelude::*;
use anime_launcher_sdk::is_available;
use std::process::{Command, Stdio};
use super::main::FirstRunAppMsg;
pub struct DependenciesApp {
show_arch: bool,
show_debian: bool,
show_fedora: bool
}
#[derive(Debug, Clone)]
pub enum DependenciesAppMsg {
Continue,
Exit
}
#[relm4::component(async, pub)]
impl SimpleAsyncComponent for DependenciesApp {
type Init = ();
type Input = DependenciesAppMsg;
type Output = FirstRunAppMsg;
view! {
adw::PreferencesPage {
set_hexpand: true,
add = &adw::PreferencesGroup {
gtk::Label {
set_label: "You're missing some dependencies!",
set_margin_top: 32,
add_css_class: "title-1"
},
gtk::Label {
set_label: "You must install some packages to your system before continue installation process",
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::Vertical,
set_spacing: 16,
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 16,
#[watch]
set_visible: model.show_arch,
gtk::Label {
set_label: "Arch (pacman)"
},
gtk::Entry {
set_text: "sudo pacman -Syu git xdelta3",
set_editable: false
}
},
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 16,
#[watch]
set_visible: model.show_debian,
gtk::Label {
set_label: "Debian / Ubuntu (apt)"
},
gtk::Entry {
set_text: "sudo apt install git xdelta3",
set_editable: false
}
},
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_spacing: 16,
#[watch]
set_visible: model.show_fedora,
gtk::Label {
set_label: "Fedora (dnf)"
},
gtk::Entry {
set_text: "sudo dnf install git xdelta",
set_editable: false
}
}
}
},
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: "Check",
add_css_class: "suggested-action",
connect_clicked => DependenciesAppMsg::Continue
},
gtk::Button {
set_label: "Exit",
connect_clicked => DependenciesAppMsg::Exit
}
}
}
}
}
async fn init(
_init: Self::Init,
root: Self::Root,
_sender: AsyncComponentSender<Self>,
) -> AsyncComponentParts<Self> {
let mut model = Self {
show_arch: false,
show_debian: false,
show_fedora: false
};
// Decide which packaging format used in system
match Command::new("pacman").stdout(Stdio::null()).spawn() {
Ok(_) => model.show_arch = true,
Err(_) => match Command::new("apt").stdout(Stdio::null()).spawn() {
Ok(_) => model.show_debian = true,
Err(_) => match Command::new("dnf").stdout(Stdio::null()).spawn() {
Ok(_) => model.show_fedora = true,
Err(_) => {
model.show_arch = true;
model.show_debian = true;
model.show_fedora = true;
}
}
}
}
let widgets = view_output!();
AsyncComponentParts { model, widgets }
}
async fn update(&mut self, msg: Self::Input, sender: AsyncComponentSender<Self>) {
match msg {
#[allow(unused_must_use)]
DependenciesAppMsg::Continue => {
let packages = ["git", "xdelta3"];
for package in packages {
if !is_available(package) {
sender.output(Self::Output::Toast {
title: format!("Package is not available: {package}"),
description: None
});
return;
}
}
sender.output(Self::Output::ScrollToDefaultPaths);
}
DependenciesAppMsg::Exit => {
// TODO: relm4 has some function for it
std::process::exit(0);
}
}
}
}

View file

@ -7,19 +7,30 @@ use adw::prelude::*;
use crate::i18n::tr;
use super::welcome::*;
use super::tos_warning::*;
use super::dependencies::*;
static mut MAIN_WINDOW: Option<adw::Window> = None;
pub struct FirstRunApp {
welcome: AsyncController<WelcomeApp>,
tos_warning: AsyncController<TosWarningApp>,
dependencies: AsyncController<DependenciesApp>,
toast_overlay: adw::ToastOverlay,
carousel: adw::Carousel
carousel: adw::Carousel,
title: String
}
#[derive(Debug, Clone)]
pub enum FirstRunAppMsg {
ScrollToTosWarning,
ScrollToDependencies,
ScrollToDefaultPaths,
ScrollToDownloadComponents,
ScrollToChooseVoiceovers,
ScrollToFinish,
Toast {
title: String,
@ -35,9 +46,11 @@ impl SimpleComponent for FirstRunApp {
view! {
window = adw::Window {
set_title: Some("Welcome"), // TODO: update this based on currently open page
set_default_size: (780, 560),
#[watch]
set_title: Some(&model.title),
#[local_ref]
toast_overlay -> adw::ToastOverlay {
gtk::Box {
@ -52,10 +65,12 @@ impl SimpleComponent for FirstRunApp {
set_allow_mouse_drag: false,
append = model.welcome.widget(),
append = model.tos_warning.widget(),
append = model.dependencies.widget(),
},
adw::CarouselIndicatorDots {
set_carousel: Some(&carousel),
set_carousel: Some(carousel),
set_height_request: 32
}
}
@ -66,7 +81,7 @@ impl SimpleComponent for FirstRunApp {
fn init(
_parent: Self::Init,
root: &Self::Root,
_sender: ComponentSender<Self>,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
tracing::info!("Initializing first run window");
@ -76,10 +91,20 @@ impl SimpleComponent for FirstRunApp {
let model = Self {
welcome: WelcomeApp::builder()
.launch(())
.detach(),
.forward(sender.input_sender(), std::convert::identity),
tos_warning: TosWarningApp::builder()
.launch(())
.forward(sender.input_sender(), std::convert::identity),
dependencies: DependenciesApp::builder()
.launch(())
.forward(sender.input_sender(), std::convert::identity),
toast_overlay,
carousel
carousel,
title: String::from("Welcome")
};
let toast_overlay = &model.toast_overlay;
@ -94,11 +119,43 @@ impl SimpleComponent for FirstRunApp {
ComponentParts { model, widgets } // will return soon
}
fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>) {
fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) {
tracing::debug!("Called first run window event: {:?}", msg);
match msg {
FirstRunAppMsg::ScrollToTosWarning => {
self.title = String::from("ToS Warning");
self.carousel.scroll_to(self.tos_warning.widget(), true);
}
FirstRunAppMsg::ScrollToDependencies => {
self.title = String::from("Dependencies");
self.carousel.scroll_to(self.dependencies.widget(), true);
}
FirstRunAppMsg::ScrollToDefaultPaths => {
self.title = String::from("Default paths");
self.carousel.scroll_to(self.welcome.widget(), true);
}
FirstRunAppMsg::ScrollToDownloadComponents => {
self.title = String::from("Download components");
self.carousel.scroll_to(self.welcome.widget(), true);
}
FirstRunAppMsg::ScrollToChooseVoiceovers => {
self.title = String::from("Select voiceovers");
self.carousel.scroll_to(self.welcome.widget(), true);
}
FirstRunAppMsg::ScrollToFinish => {
self.title = String::from("Finish");
self.carousel.scroll_to(self.welcome.widget(), true);
}

View file

@ -1,2 +1,4 @@
pub mod main;
pub mod welcome;
pub mod tos_warning;
pub mod dependencies;

View file

@ -0,0 +1,148 @@
use relm4::prelude::*;
use relm4::component::*;
use adw::prelude::*;
use anime_launcher_sdk::is_available;
use super::main::FirstRunAppMsg;
pub struct TosWarningApp;
#[derive(Debug, Clone)]
pub enum TosWarningAppMsg {
Continue,
Exit
}
#[relm4::component(async, pub)]
impl SimpleAsyncComponent for TosWarningApp {
type Init = ();
type Input = TosWarningAppMsg;
type Output = FirstRunAppMsg;
view! {
adw::PreferencesPage {
set_hexpand: true,
add = &adw::PreferencesGroup {
gtk::Label {
set_label: "ToS violation warning",
set_margin_top: 8,
add_css_class: "title-1"
},
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_margin_top: 32,
set_spacing: 12,
set_hexpand: true,
// TODO: use some kind of multiline text field
gtk::Label {
set_label: "This launcher is an unofficial tool, in no way related to miHoYo nor COGNOSPHERE.",
set_wrap: true,
set_halign: gtk::Align::Center
},
gtk::Label {
set_label: "This tool is designed to facilitate playing Genshin Impact on Linux, and was built with the sole purpose of installing and running the game with less hassle.",
set_wrap: true,
set_halign: gtk::Align::Center
},
gtk::Label {
set_label: "It does so by using existing components and making the experience simple for the user.",
set_wrap: true,
set_halign: gtk::Align::Center
},
gtk::Label {
set_label: "However, some components used here likely break the miHoYo Terms of Service for Genshin Impact.",
set_wrap: true,
set_halign: gtk::Align::Center
},
gtk::Label {
set_label: "If you are using this launcher, your player account could become identified as TOS-non-compliant by miHoYo/COGNOSPHERE.",
set_wrap: true,
set_halign: gtk::Align::Center
},
gtk::Label {
set_label: "If this happens, as your account would be disobeying TOS, miHoYo/COGNOSPHERE are free to do what they want. Including banning.",
set_wrap: true,
set_halign: gtk::Align::Center
},
gtk::Label {
set_label: "If you understand the risk of trying to play the game in an unofficial capacity, press OK and let's go researching the world of Teyvat!",
set_wrap: true,
set_halign: gtk::Align::Center
}
}
},
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: "Continue",
add_css_class: "suggested-action",
connect_clicked => TosWarningAppMsg::Continue
},
gtk::Button {
set_label: "Exit",
connect_clicked => TosWarningAppMsg::Exit
}
}
}
}
}
async fn init(
_init: Self::Init,
root: Self::Root,
_sender: AsyncComponentSender<Self>,
) -> AsyncComponentParts<Self> {
let model = Self;
let widgets = view_output!();
AsyncComponentParts { model, widgets }
}
async fn update(&mut self, msg: Self::Input, sender: AsyncComponentSender<Self>) {
match msg {
#[allow(unused_must_use)]
TosWarningAppMsg::Continue => {
if is_available("git") && is_available("xdelta3") {
sender.output(Self::Output::ScrollToDefaultPaths);
} else {
sender.output(Self::Output::ScrollToDependencies);
}
}
TosWarningAppMsg::Exit => {
// TODO: relm4 has some function for it
std::process::exit(0);
}
}
}
}

View file

@ -3,7 +3,6 @@ use relm4::component::*;
use adw::prelude::*;
use crate::*;
use super::main::FirstRunAppMsg;
pub struct WelcomeApp;