Several changes

- added subfolders support for blueprint compiler;
  moved first_run and preferences pages to subfolders
- added 2 first run pages:
  + when you don't have some required components
  + to select default folders paths
This commit is contained in:
Observer KRypt0n_ 2022-07-29 14:44:48 +02:00
parent 3e413064da
commit dcf2a7821a
No known key found for this signature in database
GPG key ID: 844DA47BA25FE1E2
19 changed files with 814 additions and 380 deletions

View file

@ -16,293 +16,6 @@ Adw.ApplicationWindow window {
Adw.Carousel carousel {
allow-mouse-drag: false;
// First page (welcome message)
Gtk.Box first_page {
orientation: vertical;
hexpand: true;
Adw.PreferencesPage {
Adw.PreferencesGroup {
Gtk.Image {
resource: "/org/app/assets/images/icon.png";
vexpand: true;
margin-top: 16;
}
Gtk.Label {
label: "An Anime Game Launcher";
margin-top: 32;
styles ["title-1"]
}
Gtk.Label {
label: "Hi there! Welcome to the An Anime Game Launcher. We need to prepare some stuff and download default components before you could run the game";
wrap: true;
justify: center;
margin-top: 32;
}
}
Adw.PreferencesGroup {
vexpand: true;
valign: center;
Gtk.Box {
orientation: horizontal;
spacing: 8;
halign: center;
Gtk.Button first_page_continue {
label: "Continue";
styles ["suggested-action"]
}
Gtk.Button {
label: "Advanced";
sensitive: false;
}
}
}
}
}
// Second page (warning message)
Gtk.Box second_page {
orientation: vertical;
hexpand: true;
Adw.PreferencesPage {
Adw.PreferencesGroup {
Gtk.Label {
label: "ToS violation warning";
margin-top: 8;
styles ["title-1"]
}
Gtk.Box {
orientation: vertical;
margin-top: 32;
spacing: 12;
Gtk.Label {
label: "This launcher is an unofficial tool, in no way related to miHoYo nor COGNOSPHERE.";
wrap: true;
halign: start;
}
Gtk.Label {
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.";
wrap: true;
halign: start;
}
Gtk.Label {
label: "It does so by using existing components and making the experience simple for the user.";
wrap: true;
halign: start;
}
Gtk.Label {
label: "However, some components used here likely break the miHoYo Terms of Service for Genshin Impact.";
wrap: true;
halign: start;
}
Gtk.Label {
label: "If you are using this launcher, your player account could become identified as TOS-non-compliant by miHoYo/COGNOSPHERE.";
wrap: true;
halign: start;
}
Gtk.Label {
label: "If this happens, as your account would be disobeying TOS, miHoYo/COGNOSPHERE are free to do what they want. Including banning.";
wrap: true;
halign: start;
}
Gtk.Label {
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!";
wrap: true;
halign: start;
}
}
}
Adw.PreferencesGroup {
vexpand: true;
valign: center;
Gtk.Box {
orientation: horizontal;
spacing: 8;
halign: center;
Gtk.Button second_page_continue {
label: "Continue";
styles ["suggested-action"]
}
Gtk.Button second_page_exit {
label: "Exit";
}
}
}
}
}
// Third page (downloading components)
Gtk.Box third_page {
orientation: vertical;
hexpand: true;
Adw.PreferencesPage {
Adw.PreferencesGroup {
Gtk.Label {
label: "Download default components";
margin-top: 16;
styles ["title-1"]
}
}
Adw.PreferencesGroup {
vexpand: true;
valign: center;
Adw.ComboRow third_page_wine_version {
title: "Wine version";
model: Gtk.StringList {
strings [
"Wine-GE-Proton 7-22"
]
};
}
Adw.ComboRow third_page_dxvk_version {
title: "DXVK version";
model: Gtk.StringList {
strings [
"dxvk-1.10.2"
]
};
}
}
Adw.PreferencesGroup third_page_buttons_group {
vexpand: true;
valign: center;
Gtk.Box {
orientation: horizontal;
spacing: 8;
halign: center;
Gtk.Button third_page_download {
label: "Download";
styles ["suggested-action"]
}
Gtk.Button third_page_exit {
label: "Exit";
}
}
}
Adw.PreferencesGroup third_page_progress_bar_group {
vexpand: true;
valign: center;
visible: false;
Gtk.Box {
halign: center;
margin-top: 64;
spacing: 20;
Gtk.ProgressBar third_page_progress_bar {
text: "Downloading: 37% (3.7 of 10 GB)";
show-text: true;
width-request: 360;
fraction: 0.37;
valign: center;
}
Gtk.Button {
label: "Pause";
sensitive: false;
tooltip-text: "Work in progress";
}
}
}
}
}
// Fourth page (downloading finished)
Gtk.Box fourth_page {
orientation: vertical;
hexpand: true;
Adw.PreferencesPage {
Adw.PreferencesGroup {
Gtk.Label {
label: "Downloading finished!";
margin-top: 64;
styles ["title-1"]
}
Gtk.Label {
label: "All the basic components were downloaded. Now you can restart the launcher and download the game. Welcome to our club!";
wrap: true;
justify: center;
margin-top: 32;
}
}
Adw.PreferencesGroup {
vexpand: true;
valign: center;
Gtk.Box {
orientation: horizontal;
spacing: 8;
halign: center;
Gtk.Button fourth_page_restart {
label: "Restart";
styles ["suggested-action"]
}
Gtk.Button fourth_page_exit {
label: "Exit";
}
}
}
}
}
}
Adw.CarouselIndicatorDots {

View file

@ -0,0 +1,56 @@
using Gtk 4.0;
using Adw 1;
Gtk.Box page {
orientation: vertical;
hexpand: true;
Adw.PreferencesPage {
Adw.PreferencesGroup {
Gtk.Image {
resource: "/org/app/assets/images/icon.png";
vexpand: true;
margin-top: 16;
}
Gtk.Label {
label: "An Anime Game Launcher";
margin-top: 32;
styles ["title-1"]
}
Gtk.Label {
label: "Hi there! Welcome to the An Anime Game Launcher. We need to prepare some stuff and download default components before you could run the game";
wrap: true;
justify: center;
margin-top: 32;
}
}
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 {
label: "Advanced";
sensitive: false;
tooltip-text: "Work in progress";
}
}
}
}
}

View file

@ -0,0 +1,102 @@
using Gtk 4.0;
using Adw 1;
Gtk.Box page {
orientation: vertical;
hexpand: true;
Adw.PreferencesPage {
Adw.PreferencesGroup {
Gtk.Label {
label: "You're missing some dependencies!";
margin-top: 32;
styles ["title-1"]
}
Gtk.Label {
label: "You must install some packages to your system before continue installation process";
wrap: true;
justify: center;
margin-top: 32;
}
}
Adw.PreferencesGroup {
vexpand: true;
valign: center;
Gtk.Box {
orientation: vertical;
spacing: 16;
Gtk.Box pkg_pacman {
orientation: vertical;
spacing: 16;
visible: false;
Gtk.Label {
label: "Arch (pacman)";
}
Gtk.Entry {
text: "sudo pacman -Syu git";
editable: false;
}
}
Gtk.Box pkg_apt {
orientation: vertical;
spacing: 16;
visible: false;
Gtk.Label {
label: "Debian / Ubuntu (apt)";
}
Gtk.Entry {
text: "sudo apt install git";
editable: false;
}
}
Gtk.Box pkg_dnf {
orientation: vertical;
spacing: 16;
visible: false;
Gtk.Label {
label: "Fedora (dnf)";
}
Gtk.Entry {
text: "sudo dnf install git";
editable: false;
}
}
}
}
Adw.PreferencesGroup {
vexpand: true;
valign: center;
Gtk.Box {
orientation: horizontal;
spacing: 8;
halign: center;
Gtk.Button check_button {
label: "Check";
styles ["suggested-action"]
}
Gtk.Button exit_button {
label: "Exit";
}
}
}
}
}

View file

@ -0,0 +1,94 @@
using Gtk 4.0;
using Adw 1;
Gtk.Box page {
orientation: vertical;
hexpand: true;
Adw.PreferencesPage {
Adw.PreferencesGroup {
Gtk.Label {
label: "ToS violation warning";
margin-top: 8;
styles ["title-1"]
}
Gtk.Box {
orientation: vertical;
margin-top: 32;
spacing: 12;
Gtk.Label {
label: "This launcher is an unofficial tool, in no way related to miHoYo nor COGNOSPHERE.";
wrap: true;
halign: start;
}
Gtk.Label {
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.";
wrap: true;
halign: start;
}
Gtk.Label {
label: "It does so by using existing components and making the experience simple for the user.";
wrap: true;
halign: start;
}
Gtk.Label {
label: "However, some components used here likely break the miHoYo Terms of Service for Genshin Impact.";
wrap: true;
halign: start;
}
Gtk.Label {
label: "If you are using this launcher, your player account could become identified as TOS-non-compliant by miHoYo/COGNOSPHERE.";
wrap: true;
halign: start;
}
Gtk.Label {
label: "If this happens, as your account would be disobeying TOS, miHoYo/COGNOSPHERE are free to do what they want. Including banning.";
wrap: true;
halign: start;
}
Gtk.Label {
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!";
wrap: true;
halign: start;
}
}
}
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";
}
}
}
}
}

View file

@ -0,0 +1,69 @@
using Gtk 4.0;
using Adw 1;
Gtk.Box page {
orientation: vertical;
hexpand: true;
Adw.PreferencesPage {
Adw.PreferencesGroup {
Gtk.Label {
label: "Set default paths";
margin-top: 16;
styles ["title-1"]
}
}
Adw.PreferencesGroup {
vexpand: true;
valign: center;
Adw.ActionRow runners_folder {
title: "Runners saving folder";
activatable: true;
}
Adw.ActionRow dxvk_folder {
title: "DXVK saving folder";
activatable: true;
}
Adw.ActionRow prefix_folder {
title: "Wine prefix folder";
activatable: true;
}
Adw.ActionRow game_folder {
title: "Game installation folder";
activatable: true;
}
Adw.ActionRow temp_folder {
title: "Temp data saving folder";
activatable: true;
}
}
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";
}
}
}
}
}

View file

@ -0,0 +1,91 @@
using Gtk 4.0;
using Adw 1;
Gtk.Box page {
orientation: vertical;
hexpand: true;
Adw.PreferencesPage {
Adw.PreferencesGroup {
Gtk.Label {
label: "Download default components";
margin-top: 16;
styles ["title-1"]
}
}
Adw.PreferencesGroup {
vexpand: true;
valign: center;
Adw.ComboRow wine_version {
title: "Wine version";
model: Gtk.StringList {
strings [
"Wine-GE-Proton 7-22"
]
};
}
Adw.ComboRow dxvk_version {
title: "DXVK version";
model: Gtk.StringList {
strings [
"dxvk-1.10.2"
]
};
}
}
Adw.PreferencesGroup buttons_group {
vexpand: true;
valign: center;
Gtk.Box {
orientation: horizontal;
spacing: 8;
halign: center;
Gtk.Button download_button {
label: "Download";
styles ["suggested-action"]
}
Gtk.Button exit_button {
label: "Exit";
}
}
}
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)";
show-text: true;
width-request: 360;
fraction: 0.37;
valign: center;
}
Gtk.Button {
label: "Pause";
sensitive: false;
tooltip-text: "Work in progress";
}
}
}
}
}

View file

@ -0,0 +1,47 @@
using Gtk 4.0;
using Adw 1;
Gtk.Box page {
orientation: vertical;
hexpand: true;
Adw.PreferencesPage {
Adw.PreferencesGroup {
Gtk.Label {
label: "Downloading finished!";
margin-top: 64;
styles ["title-1"]
}
Gtk.Label {
label: "All the basic components were downloaded. Now you can restart the launcher and download the game. Welcome to our club!";
wrap: true;
justify: center;
margin-top: 32;
}
}
Adw.PreferencesGroup {
vexpand: true;
valign: center;
Gtk.Box {
orientation: horizontal;
spacing: 8;
halign: center;
Gtk.Button restart_button {
label: "Restart";
styles ["suggested-action"]
}
Gtk.Button exit_button {
label: "Exit";
}
}
}
}
}

View file

@ -26,30 +26,25 @@ fn compile_blueprint<T: ToString>(path: T) -> Result<String, String> {
}
}
fn main() {
if let Ok(_) = read_to_string("assets/resources.xml") {
gtk4::gio::compile_resources(
"assets",
"assets/resources.xml",
".assets.gresource",
);
}
fn blp_process_dir(dir: String) {
let source_dir = format!("assets/ui/{}", &dir).replace("//", "/");
let dist_dir = format!("assets/ui/.dist/{}", &dir).replace("//", "/");
if let Ok(entries) = read_dir("assets/ui") {
if let Err(_) = read_dir("assets/ui/.dist") {
create_dir_all("assets/ui/.dist").expect("UI dist dir couldn't be created");
if let Ok(entries) = read_dir(&source_dir) {
if let Err(_) = read_dir(&dist_dir) {
create_dir_all(&dist_dir).expect("UI dist dir couldn't be created");
}
println!("cargo:rerun-if-changed=assets/ui/*.blp");
println!("cargo:rerun-if-changed={}/*.blp", &source_dir);
for entry in entries {
if let Ok(entry) = entry {
if let Ok(metadata) = entry.metadata() {
if metadata.is_file() {
let entry_path = entry.path().to_str().unwrap().to_string();
let entry_filename = entry.file_name().to_str().unwrap().to_string();
let entry_path = entry.path().to_str().unwrap().to_string();
let entry_filename = entry.file_name().to_str().unwrap().to_string();
let entry_dist_path = format!("assets/ui/.dist/{}.ui", &entry_filename[..entry_filename.len() - 4]);
if metadata.is_file() {
let entry_dist_path = format!("{}/{}.ui", &dist_dir, &entry_filename[..entry_filename.len() - 4]);
match compile_blueprint(&entry_path) {
Ok(xml) => {
@ -68,8 +63,24 @@ fn main() {
}
}
}
else if metadata.is_dir() && &entry_filename[0..1] != "." {
blp_process_dir(format!("{}/{}", &dir, &entry_filename));
}
}
}
}
}
}
fn main() {
if let Ok(_) = read_to_string("assets/resources.xml") {
gtk4::gio::compile_resources(
"assets",
"assets/resources.xml",
".assets.gresource",
);
}
blp_process_dir(String::new());
}

View file

@ -6,9 +6,17 @@ use gtk::glib::clone;
use std::rc::Rc;
use std::cell::Cell;
use std::process::{Command, Stdio};
use anime_game_core::prelude::*;
mod page_1;
mod page_2;
mod page_3;
mod page_4;
mod page_5;
mod page_6;
use crate::ui::*;
use crate::ui::components::progress_bar::*;
@ -27,69 +35,39 @@ pub struct AppWidgets {
pub window: adw::ApplicationWindow,
pub carousel: adw::Carousel,
// First page
pub first_page: gtk::Box,
pub first_page_continue: gtk::Button,
// Second page
pub second_page: gtk::Box,
pub second_page_continue: gtk::Button,
pub second_page_exit: gtk::Button,
// Third page
pub third_page: gtk::Box,
pub third_page_wine_version: adw::ComboRow,
pub third_page_dxvk_version: adw::ComboRow,
pub third_page_download: gtk::Button,
pub third_page_exit: gtk::Button,
pub third_page_progress_bar: ProgressBar,
// Fourth page
pub fourth_page: gtk::Box,
pub fourth_page_restart: gtk::Button,
pub fourth_page_exit: gtk::Button
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
}
impl AppWidgets {
pub fn try_get() -> Result<Self, String> {
let builder = gtk::Builder::from_string(include_str!("../../assets/ui/.dist/first_run.ui"));
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/first_run.ui"));
Ok(Self {
let result = Self {
window: get_object(&builder, "window")?,
carousel: get_object(&builder, "carousel")?,
// First page
first_page: get_object(&builder, "first_page")?,
first_page_continue: get_object(&builder, "first_page_continue")?,
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()?
};
// Second page
second_page: get_object(&builder, "second_page")?,
second_page_continue: get_object(&builder, "second_page_continue")?,
second_page_exit: get_object(&builder, "second_page_exit")?,
// 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);
// Third page
third_page: get_object(&builder, "third_page")?,
third_page_wine_version: get_object(&builder, "third_page_wine_version")?,
third_page_dxvk_version: get_object(&builder, "third_page_dxvk_version")?,
third_page_download: get_object(&builder, "third_page_download")?,
third_page_exit: get_object(&builder, "third_page_exit")?,
third_page_progress_bar: ProgressBar::new(
get_object(&builder, "third_page_progress_bar")?,
get_object(&builder, "third_page_buttons_group")?,
get_object(&builder, "third_page_progress_bar_group")?
),
// Fourth page
fourth_page: get_object(&builder, "fourth_page")?,
fourth_page_restart: get_object(&builder, "fourth_page_restart")?,
fourth_page_exit: get_object(&builder, "fourth_page_exit")?
})
Ok(result)
}
}
@ -101,10 +79,12 @@ impl AppWidgets {
#[derive(Debug, glib::Downgrade)]
pub enum Actions {
FirstPageContinue,
SecondPageContinue,
ThirdPageDownload,
SecondPageCheck,
ThirdPageContinue,
FourthPageRestart,
FourthPageContinue,
FifthPageDownload,
FifthPageContinue,
Restart,
Exit
}
@ -160,14 +140,20 @@ impl App {
/// Add default events and values to the widgets
fn init_events(self) -> Self {
self.widgets.first_page_continue.connect_clicked(Actions::FirstPageContinue.into_fn(&self));
self.widgets.second_page_continue.connect_clicked(Actions::SecondPageContinue.into_fn(&self));
self.widgets.third_page_download.connect_clicked(Actions::ThirdPageDownload.into_fn(&self));
self.widgets.fourth_page_restart.connect_clicked(Actions::FourthPageRestart.into_fn(&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.second_page_exit.connect_clicked(Actions::Exit.into_fn(&self));
self.widgets.third_page_exit.connect_clicked(Actions::Exit.into_fn(&self));
self.widgets.fourth_page_exit.connect_clicked(Actions::Exit.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.page_6.restart_button.connect_clicked(Actions::Restart.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
}
@ -186,22 +172,38 @@ impl App {
match action {
Actions::FirstPageContinue => {
this.widgets.carousel.scroll_to(&this.widgets.second_page, true);
match Command::new("git").stdout(Stdio::null()).spawn() {
Ok(_) => this.widgets.carousel.scroll_to(&this.widgets.page_3.page, true),
Err(_) => this.widgets.carousel.scroll_to(&this.widgets.page_2.page, true)
}
}
Actions::SecondPageContinue => {
this.widgets.carousel.scroll_to(&this.widgets.third_page, true);
Actions::SecondPageCheck => {
match Command::new("git").stdout(Stdio::null()).spawn() {
Ok(_) => this.widgets.carousel.scroll_to(&this.widgets.page_3.page, true),
Err(_) => {
// todo
}
}
}
Actions::ThirdPageDownload => {
this.widgets.third_page_wine_version.set_sensitive(false);
this.widgets.third_page_dxvk_version.set_sensitive(false);
Actions::ThirdPageContinue => {
this.widgets.carousel.scroll_to(&this.widgets.page_4.page, true);
}
this.widgets.third_page_progress_bar.show();
Actions::FourthPageContinue => {
this.widgets.carousel.scroll_to(&this.widgets.page_5.page, true);
}
Actions::FifthPageDownload => {
this.widgets.page_5.wine_version.set_sensitive(false);
this.widgets.page_5.dxvk_version.set_sensitive(false);
this.widgets.page_5.progress_bar.show();
let (sender, receiver) = glib::MainContext::channel::<InstallerUpdate>(glib::PRIORITY_DEFAULT);
let progress_bar = this.widgets.third_page_progress_bar.clone();
let progress_bar = this.widgets.page_5.progress_bar.clone();
let wine_version = WineVersion::latest().unwrap();
let dxvk_version = DxvkVersion::latest().unwrap();
@ -277,7 +279,7 @@ impl App {
std::fs::remove_file(format!("{}/.first-run", launcher_dir)).unwrap();
// Show next page
this.update(Actions::ThirdPageContinue).unwrap();
this.update(Actions::FifthPageContinue).unwrap();
}
}
});
@ -288,12 +290,12 @@ impl App {
});
}
Actions::ThirdPageContinue => {
this.widgets.carousel.scroll_to(&this.widgets.fourth_page, true);
Actions::FifthPageContinue => {
this.widgets.carousel.scroll_to(&this.widgets.page_6.page, true);
}
// FIXME
Actions::FourthPageRestart => {
Actions::Restart => {
this.widgets.window.close();
}

View file

@ -0,0 +1,20 @@
use gtk4 as gtk;
use crate::ui::*;
#[derive(Clone)]
pub struct Page {
pub page: gtk::Box,
pub continue_button: gtk::Button
}
impl Page {
pub fn new() -> Result<Self, String> {
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/first_run/page_1.ui"));
Ok(Self {
page: get_object(&builder, "page")?,
continue_button: get_object(&builder, "continue_button")?
})
}
}

View file

@ -0,0 +1,55 @@
use gtk4 as gtk;
use std::process::{Command, Stdio};
use crate::ui::*;
#[derive(Clone)]
pub struct Page {
pub page: gtk::Box,
pub pkg_pacman: gtk::Box,
pub pkg_apt: gtk::Box,
pub pkg_dnf: gtk::Box,
pub check_button: gtk::Button,
pub exit_button: gtk::Button
}
impl Page {
pub fn new() -> Result<Self, String> {
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/first_run/page_2.ui"));
let result = Self {
page: get_object(&builder, "page")?,
pkg_pacman: get_object(&builder, "pkg_pacman")?,
pkg_apt: get_object(&builder, "pkg_apt")?,
pkg_dnf: get_object(&builder, "pkg_dnf")?,
check_button: get_object(&builder, "check_button")?,
exit_button: get_object(&builder, "exit_button")?
};
// Decide which packaging format used in system
match Command::new("pacman").stdout(Stdio::null()).spawn() {
Ok(_) => result.pkg_pacman.show(),
Err(_) => match Command::new("apt").stdout(Stdio::null()).spawn() {
Ok(_) => result.pkg_apt.show(),
Err(_) => match Command::new("dnf").stdout(Stdio::null()).spawn() {
Ok(_) => result.pkg_dnf.show(),
Err(_) => {
result.pkg_pacman.show();
result.pkg_apt.show();
result.pkg_dnf.show();
}
}
}
}
Ok(result)
}
}

View file

@ -0,0 +1,22 @@
use gtk4 as gtk;
use crate::ui::*;
#[derive(Clone)]
pub struct Page {
pub page: gtk::Box,
pub continue_button: gtk::Button,
pub exit_button: gtk::Button
}
impl Page {
pub fn new() -> Result<Self, String> {
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/first_run/page_3.ui"));
Ok(Self {
page: get_object(&builder, "page")?,
continue_button: get_object(&builder, "continue_button")?,
exit_button: get_object(&builder, "exit_button")?
})
}
}

View file

@ -0,0 +1,90 @@
use gtk4 as gtk;
use libadwaita::{self as adw, prelude::*};
use gtk::glib;
use gtk::glib::clone;
use wait_not_await::Await;
use crate::lib::config;
use crate::ui::*;
pub fn choose_dir<T: IsA<gtk::Window>>(current_folder: String, parent: &T) -> Await<String> {
let dialogue = gtk::FileChooserDialog::new(
Some("Select folder"),
Some(parent),
gtk::FileChooserAction::SelectFolder,
&[("Select", gtk::ResponseType::Accept)]
);
dialogue.set_current_folder(Some(&gtk::gio::File::for_path(current_folder))).unwrap();
let (sender, receiver) = std::sync::mpsc::channel();
dialogue.connect_response(move |dialogue, response| {
if response == gtk::ResponseType::Accept {
sender.send(dialogue.current_folder().unwrap().to_string()).unwrap();
}
});
dialogue.show();
Await::new(move || {
receiver.recv().unwrap()
})
}
#[derive(Clone)]
pub struct Page {
pub window: gtk::Window,
pub page: gtk::Box,
pub runners_folder: adw::ActionRow,
pub dxvk_folder: adw::ActionRow,
pub prefix_folder: adw::ActionRow,
pub game_folder: adw::ActionRow,
pub temp_folder: adw::ActionRow,
pub continue_button: gtk::Button,
pub exit_button: gtk::Button
}
impl Page {
pub fn new(window: gtk::Window) -> Result<Self, String> {
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/first_run/page_4.ui"));
let result = Self {
window,
page: get_object(&builder, "page")?,
runners_folder: get_object(&builder, "runners_folder")?,
dxvk_folder: get_object(&builder, "dxvk_folder")?,
prefix_folder: get_object(&builder, "prefix_folder")?,
game_folder: get_object(&builder, "game_folder")?,
temp_folder: get_object(&builder, "temp_folder")?,
continue_button: get_object(&builder, "continue_button")?,
exit_button: get_object(&builder, "exit_button")?
};
let config = match config::get() {
Ok(config) => config,
Err(err) => return Err(err.to_string())
};
result.runners_folder.set_subtitle(&config.game.wine.builds);
result.dxvk_folder.set_subtitle(&config.game.dxvk.builds);
result.prefix_folder.set_subtitle(&config.game.wine.prefix);
result.game_folder.set_subtitle(&config.game.path);
result.temp_folder.set_subtitle(&match config.launcher.temp {
Some(temp) => temp,
None => String::from("/tmp")
});
result.runners_folder.connect_activated(clone!(@strong result.window as window => move |row| {
choose_dir(row.subtitle().unwrap().to_string(), &window);
}));
Ok(result)
}
}

View file

@ -0,0 +1,40 @@
use gtk4 as gtk;
use libadwaita as adw;
use crate::ui::*;
use crate::ui::components::progress_bar::ProgressBar;
#[derive(Clone)]
pub struct Page {
pub page: gtk::Box,
pub wine_version: adw::ComboRow,
pub dxvk_version: adw::ComboRow,
pub download_button: gtk::Button,
pub exit_button: gtk::Button,
pub progress_bar: ProgressBar
}
impl Page {
pub fn new() -> Result<Self, String> {
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/first_run/page_5.ui"));
Ok(Self {
page: get_object(&builder, "page")?,
wine_version: get_object(&builder, "wine_version")?,
dxvk_version: get_object(&builder, "dxvk_version")?,
download_button: get_object(&builder, "download_button")?,
exit_button: get_object(&builder, "exit_button")?,
progress_bar: ProgressBar::new(
get_object(&builder, "progress_bar")?,
get_object(&builder, "buttons_group")?,
get_object(&builder, "progress_bar_group")?
)
})
}
}

View file

@ -0,0 +1,22 @@
use gtk4 as gtk;
use crate::ui::*;
#[derive(Clone)]
pub struct Page {
pub page: gtk::Box,
pub restart_button: gtk::Button,
pub exit_button: gtk::Button
}
impl Page {
pub fn new() -> Result<Self, String> {
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/first_run/page_6.ui"));
Ok(Self {
page: get_object(&builder, "page")?,
restart_button: get_object(&builder, "restart_button")?,
exit_button: get_object(&builder, "exit_button")?
})
}
}

View file

@ -31,7 +31,7 @@ pub struct AppWidgets {
impl AppWidgets {
fn try_get() -> Result<Self, String> {
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/preferences_enhancements.ui"));
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/preferences/enhancements.ui"));
let result = Self {
page: get_object(&builder, "enhanced_page")?,

View file

@ -52,7 +52,7 @@ pub struct AppWidgets {
impl AppWidgets {
pub fn try_get(window: adw::ApplicationWindow, toast_overlay: adw::ToastOverlay) -> Result<Self, String> {
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/preferences_general.ui"));
let builder = gtk::Builder::from_string(include_str!("../../../assets/ui/.dist/preferences/general.ui"));
let mut result = Self {
window,